analysis/webservice/webapp.py (107 lines of code) (raw):
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import configparser
import logging
import sys
import os
from datetime import datetime
import tornado.web
from tornado.routing import Rule, RuleRouter, AnyMatches
from tornado.options import define, options, parse_command_line
from webservice.redirect import RemoteCollectionMatcher
from webservice.nexus_tornado.app_builders import NexusAppBuilder
from webservice.nexus_tornado.app_builders import RedirectAppBuilder
from nexustiles.nexustiles import NexusTileService
try:
from importlib.metadata import version as _version
from importlib.metadata import files as _files
except ImportError:
from importlib_metadata import version as _version
try:
__version__ = _version('sdap-nexus')
except Exception:
__version__ = 'Cannot be determined'
banner = [
'',
' ____ ____ _ ____ | ',
'/ ___|| _ \\ / \\ | _ \\ | Apache SDAP (TM)',
'\\___ \\| | | |/ _ \\ | |_) | | Science Data Analytics Platform',
f' ___) | |_| / ___ \\| __/ | Version: {__version__}',
'|____/|____/_/ \\_\\_| | ',
''
]
def inject_args_in_config(args, config):
"""
Takes command argparse arguments and push them in the config
with syntax args.<section>-<option>
"""
log = logging.getLogger(__name__)
for t_opt in list(args._options.values()):
n = t_opt.name
first_ = n.find('_')
if first_ > 0:
s, o = n[:first_], n[first_ + 1:]
v = t_opt.value()
log.info('inject argument {} = {} in configuration section {}, option {}'.format(n, v, s, o))
if not config.has_section(s):
config.add_section(s)
config.set(s, o, v)
return config
def main():
start = datetime.now()
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt="%Y-%m-%dT%H:%M:%S", stream=sys.stdout
)
log = logging.getLogger(__name__)
for line in banner:
log.info(line)
web_config = configparser.RawConfigParser()
web_config.read_file(open(os.path.join(os.path.dirname(__file__), "config", "web.ini")))
algorithm_config = configparser.RawConfigParser()
algorithm_config.read_file(open(os.path.join(os.path.dirname(__file__), "config", "algorithms.ini")))
define("debug", default=False, help="run in debug mode")
define("port", default=web_config.get("global", "server.socket_port"), help="run on the given port", type=int)
define("address", default=web_config.get("global", "server.socket_host"), help="Bind to the given address")
define('solr_time_out', default=60,
help='time out for solr requests in seconds, default (60) is ok for most deployments'
' when solr performances are not good this might need to be increased')
define('solr_host', help='solr host and port')
define('cassandra_host', help='cassandra host')
define('cassandra_username', help='cassandra username')
define('cassandra_password', help='cassandra password')
define('collections_path', default=None, help='collection config path')
parse_command_line()
algorithm_config = inject_args_in_config(options, algorithm_config)
remote_collections = None
router_rules = []
if options.collections_path:
# build retirect app
remote_collection_matcher = RemoteCollectionMatcher(options.collections_path)
remote_collections = remote_collection_matcher.get_remote_collections()
remote_sdap_app = RedirectAppBuilder(remote_collection_matcher).build(
host=options.address,
debug=options.debug)
router_rules.append(Rule(remote_collection_matcher, remote_sdap_app))
# build nexus app
nexus_app_builder = NexusAppBuilder().set_modules(
web_config.get("modules", "module_dirs").split(","),
algorithm_config,
remote_collections=remote_collections
)
if web_config.get("static", "static_enabled") == "true":
nexus_app_builder.enable_static(
web_config.get("static", "static_dir")
)
else:
log.info("Static resources disabled")
local_sdap_app = nexus_app_builder.build(host=options.address, debug=options.debug)
router_rules.append(Rule(AnyMatches(), local_sdap_app))
router = RuleRouter(router_rules)
log.info("Initializing on host address '%s'" % options.address)
log.info("Initializing on port '%s'" % options.port)
log.info("Starting web server in debug mode: %s" % options.debug)
server = tornado.web.HTTPServer(router)
server.listen(options.port)
log.info('Waiting for dataset backends to come up...')
with NexusTileService.DS_LOCK:
if not NexusTileService.is_update_thread_alive():
log.critical('A fatal error occurred when loading the datasets')
exit(-1)
log.info(f"SDAP started in {datetime.now() - start}. Starting HTTP listener...")
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()