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()