From 951a3f680e25f25efca676671acadcf76906e962 Mon Sep 17 00:00:00 2001 From: John Chilton <jmchilton@gmail.com> Date: Tue, 3 Jun 2014 20:47:45 -0500 Subject: [PATCH] Move all web stuffs into lwr.web. Refactor core app into lwr/core.py. Deprecating old wsgi app_factory module in lieu of lwr.web.wsgi. --- lwr/app.py | 166 +----------------------------------- lwr/core.py | 119 ++++++++++++++++++++++++++ lwr/lwr_client/interface.py | 4 +- lwr/web/__init__.py | 0 lwr/{ => web}/framework.py | 0 lwr/{ => web}/routes.py | 4 +- lwr/web/wsgi.py | 45 ++++++++++ server.ini.sample | 2 +- test/routes_test.py | 2 +- test/test_utils.py | 2 +- 10 files changed, 175 insertions(+), 169 deletions(-) create mode 100644 lwr/core.py create mode 100644 lwr/web/__init__.py rename lwr/{ => web}/framework.py (100%) rename lwr/{ => web}/routes.py (99%) create mode 100644 lwr/web/wsgi.py diff --git a/lwr/app.py b/lwr/app.py index 13e62c46..d9b6da7a 100644 --- a/lwr/app.py +++ b/lwr/app.py @@ -1,164 +1,6 @@ +""" Deprecated module for wsgi app factory. LWR servers should transition to +``lwr.web.wsgi:app_factory``. """ -""" -import atexit -import inspect -import os -from tempfile import tempdir - -from lwr.manager_factory import build_managers -from lwr.cache import Cache -from lwr.framework import RoutingApp -from lwr.tools import ToolBox -from lwr.tools.authorization import get_authorizer -from lwr import messaging -import lwr.routes -from galaxy.objectstore import build_object_store_from_config -from galaxy.tools.deps import DependencyManager -from galaxy.jobs.metrics import JobMetrics -from galaxy.util.bunch import Bunch - -from logging import getLogger -log = getLogger(__name__) - -DEFAULT_PRIVATE_KEY = None -DEFAULT_STAGING_DIRECTORY = "lwr_staging" -DEFAULT_PERSISTENCE_DIRECTORY = "persisted_data" - - -NOT_WHITELIST_WARNING = "Starting the LWR without a toolbox to white-list." + \ - "Ensure this application is protected by firewall or a configured private token." - - -class LwrApp(object): - - def __init__(self, **conf): - if conf is None: - conf = {} - self.__setup_staging_directory(conf.get("staging_directory", DEFAULT_STAGING_DIRECTORY)) - self.__setup_private_key(conf.get("private_key", DEFAULT_PRIVATE_KEY)) - self.__setup_persistence_directory(conf.get("persistence_directory", None)) - self.__setup_tool_config(conf) - self.__setup_object_store(conf) - self.__setup_dependency_manager(conf) - self.__setup_job_metrics(conf) - self.__setup_managers(conf) - self.__setup_file_cache(conf) - self.__setup_bind_to_message_queue(conf) - - def shutdown(self): - for manager in self.managers.values(): - try: - manager.shutdown() - except Exception: - pass - - if self.__queue_state: - self.__queue_state.deactivate() - - def __setup_bind_to_message_queue(self, conf): - message_queue_url = conf.get("message_queue_url", None) - queue_state = None - if message_queue_url: - queue_state = messaging.bind_app(self, message_queue_url, conf) - self.__queue_state = queue_state - - def __setup_tool_config(self, conf): - """ - Setups toolbox object and authorization mechanism based - on supplied toolbox_path. - """ - tool_config_files = conf.get("tool_config_files", None) - if not tool_config_files: - # For compatibity with Galaxy, allow tool_config_file - # option name. - tool_config_files = conf.get("tool_config_file", None) - toolbox = None - if tool_config_files: - toolbox = ToolBox(tool_config_files) - else: - log.info(NOT_WHITELIST_WARNING) - self.toolbox = toolbox - self.authorizer = get_authorizer(toolbox) - - def __setup_staging_directory(self, staging_directory): - self.staging_directory = os.path.abspath(staging_directory) - - def __setup_managers(self, conf): - self.managers = build_managers(self, conf) - - def __setup_private_key(self, private_key): - self.private_key = private_key - if private_key: - log.info("Securing LWR web app with private key, please verify you are using HTTPS so key cannot be obtained by monitoring traffic.") - - def __setup_routes(self): - for func_name, func in inspect.getmembers(lwr.routes, lambda x: getattr(x, '__controller__', False)): - self.__add_route_for_function(func) - - def __setup_persistence_directory(self, persistence_directory): - self.persistence_directory = persistence_directory or DEFAULT_PERSISTENCE_DIRECTORY - - def __setup_file_cache(self, conf): - file_cache_dir = conf.get('file_cache_dir', None) - self.file_cache = Cache(file_cache_dir) if file_cache_dir else None - - def __setup_object_store(self, conf): - if "object_store_config_file" not in conf: - self.object_store = None - return - object_store_config = Bunch( - object_store_config_file=conf['object_store_config_file'], - file_path=conf.get("object_store_file_path", None), - object_store_check_old_style=False, - job_working_directory=conf.get("object_store_job_working_directory", None), - new_file_path=conf.get("object_store_new_file_path", tempdir), - umask=int(conf.get("object_store_umask", "0000")), - ) - self.object_store = build_object_store_from_config(object_store_config) - - def __setup_dependency_manager(self, conf): - dependencies_dir = conf.get("tool_dependency_dir", "dependencies") - resolvers_config_file = conf.get("dependency_resolvers_config_file", "dependency_resolvers_conf.xml") - self.dependency_manager = DependencyManager(dependencies_dir, resolvers_config_file) - - def __setup_job_metrics(self, conf): - job_metrics_config_file = conf.get("job_metrics_config_file", "job_metrics_conf.xml") - self.job_metrics = JobMetrics(job_metrics_config_file) - - -def app_factory(global_conf, **local_conf): - """ - Returns the LWR WSGI application. - """ - lwr_app = LwrApp(global_conf=global_conf, **local_conf) - webapp = LwrWebApp(lwr_app=lwr_app) - atexit.register(webapp.shutdown) - return webapp - - -class LwrWebApp(RoutingApp): - """ - Web application for LWR web server. - """ - - def __init__(self, lwr_app): - super(LwrWebApp, self).__init__() - self.lwr_app = lwr_app - self.__setup_routes() - - def __setup_routes(self): - for func_name, func in inspect.getmembers(lwr.routes, lambda x: getattr(x, '__controller__', False)): - self.__add_route_for_function(func) - - def __add_route_for_function(self, function): - route_suffix = '/%s' % function.__name__ - # Default or old-style route without explicit manager specified, - # will be routed to manager '_default_'. - default_manager_route = route_suffix - self.add_route(default_manager_route, function) - # Add route for named manager as well. - named_manager_route = '/managers/{manager_name}%s' % route_suffix - self.add_route(named_manager_route, function) +from lwr.web.wsgi import app_factory - def __getattr__(self, name): - return getattr(self.lwr_app, name) +__all__ = ['app_factory'] diff --git a/lwr/core.py b/lwr/core.py new file mode 100644 index 00000000..7b9d3772 --- /dev/null +++ b/lwr/core.py @@ -0,0 +1,119 @@ +""" +""" +import inspect +import os +from tempfile import tempdir + +from lwr.manager_factory import build_managers +from lwr.cache import Cache +from lwr.tools import ToolBox +from lwr.tools.authorization import get_authorizer +from lwr import messaging +from galaxy.objectstore import build_object_store_from_config +from galaxy.tools.deps import DependencyManager +from galaxy.jobs.metrics import JobMetrics +from galaxy.util.bunch import Bunch + +from logging import getLogger +log = getLogger(__name__) + +DEFAULT_PRIVATE_KEY = None +DEFAULT_STAGING_DIRECTORY = "lwr_staging" +DEFAULT_PERSISTENCE_DIRECTORY = "persisted_data" + + +NOT_WHITELIST_WARNING = "Starting the LWR without a toolbox to white-list." + \ + "Ensure this application is protected by firewall or a configured private token." + + +class LwrApp(object): + + def __init__(self, **conf): + if conf is None: + conf = {} + self.__setup_staging_directory(conf.get("staging_directory", DEFAULT_STAGING_DIRECTORY)) + self.__setup_private_key(conf.get("private_key", DEFAULT_PRIVATE_KEY)) + self.__setup_persistence_directory(conf.get("persistence_directory", None)) + self.__setup_tool_config(conf) + self.__setup_object_store(conf) + self.__setup_dependency_manager(conf) + self.__setup_job_metrics(conf) + self.__setup_managers(conf) + self.__setup_file_cache(conf) + self.__setup_bind_to_message_queue(conf) + + def shutdown(self): + for manager in self.managers.values(): + try: + manager.shutdown() + except Exception: + pass + + if self.__queue_state: + self.__queue_state.deactivate() + + def __setup_bind_to_message_queue(self, conf): + message_queue_url = conf.get("message_queue_url", None) + queue_state = None + if message_queue_url: + queue_state = messaging.bind_app(self, message_queue_url, conf) + self.__queue_state = queue_state + + def __setup_tool_config(self, conf): + """ + Setups toolbox object and authorization mechanism based + on supplied toolbox_path. + """ + tool_config_files = conf.get("tool_config_files", None) + if not tool_config_files: + # For compatibity with Galaxy, allow tool_config_file + # option name. + tool_config_files = conf.get("tool_config_file", None) + toolbox = None + if tool_config_files: + toolbox = ToolBox(tool_config_files) + else: + log.info(NOT_WHITELIST_WARNING) + self.toolbox = toolbox + self.authorizer = get_authorizer(toolbox) + + def __setup_staging_directory(self, staging_directory): + self.staging_directory = os.path.abspath(staging_directory) + + def __setup_managers(self, conf): + self.managers = build_managers(self, conf) + + def __setup_private_key(self, private_key): + self.private_key = private_key + if private_key: + log.info("Securing LWR web app with private key, please verify you are using HTTPS so key cannot be obtained by monitoring traffic.") + + def __setup_persistence_directory(self, persistence_directory): + self.persistence_directory = persistence_directory or DEFAULT_PERSISTENCE_DIRECTORY + + def __setup_file_cache(self, conf): + file_cache_dir = conf.get('file_cache_dir', None) + self.file_cache = Cache(file_cache_dir) if file_cache_dir else None + + def __setup_object_store(self, conf): + if "object_store_config_file" not in conf: + self.object_store = None + return + object_store_config = Bunch( + object_store_config_file=conf['object_store_config_file'], + file_path=conf.get("object_store_file_path", None), + object_store_check_old_style=False, + job_working_directory=conf.get("object_store_job_working_directory", None), + new_file_path=conf.get("object_store_new_file_path", tempdir), + umask=int(conf.get("object_store_umask", "0000")), + ) + self.object_store = build_object_store_from_config(object_store_config) + + def __setup_dependency_manager(self, conf): + dependencies_dir = conf.get("tool_dependency_dir", "dependencies") + resolvers_config_file = conf.get("dependency_resolvers_config_file", "dependency_resolvers_conf.xml") + self.dependency_manager = DependencyManager(dependencies_dir, resolvers_config_file) + + def __setup_job_metrics(self, conf): + job_metrics_config_file = conf.get("job_metrics_config_file", "job_metrics_conf.xml") + self.job_metrics = JobMetrics(job_metrics_config_file) diff --git a/lwr/lwr_client/interface.py b/lwr/lwr_client/interface.py index fbacc567..95538d22 100644 --- a/lwr/lwr_client/interface.py +++ b/lwr/lwr_client/interface.py @@ -78,8 +78,8 @@ class LocalLwrInterface(LwrInteface): def execute(self, command, args={}, data=None, input_path=None, output_path=None): # If data set, should be unicode (on Python 2) or str (on Python 3). - from lwr import routes - from lwr.framework import build_func_args + from lwr.web import routes + from lwr.web.framework import build_func_args controller = getattr(routes, command) action = controller.func body_args = dict(body=self.__build_body(data, input_path)) diff --git a/lwr/web/__init__.py b/lwr/web/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/lwr/framework.py b/lwr/web/framework.py similarity index 100% rename from lwr/framework.py rename to lwr/web/framework.py diff --git a/lwr/routes.py b/lwr/web/routes.py similarity index 99% rename from lwr/routes.py rename to lwr/web/routes.py index 3919c9f1..1d491f8b 100644 --- a/lwr/routes.py +++ b/lwr/web/routes.py @@ -7,9 +7,9 @@ from galaxy.util import ( copy_to_temp, ) from lwr.lwr_client.job_directory import verify_is_in_directory -from lwr.framework import Controller +from lwr.web.framework import Controller from lwr.manager_factory import DEFAULT_MANAGER_NAME -from .manager_endpoint_util import ( +from lwr.manager_endpoint_util import ( submit_job, setup_job, full_status, diff --git a/lwr/web/wsgi.py b/lwr/web/wsgi.py new file mode 100644 index 00000000..334a9a76 --- /dev/null +++ b/lwr/web/wsgi.py @@ -0,0 +1,45 @@ +import atexit +import inspect + +from lwr.core import LwrApp +from lwr.web.framework import RoutingApp + +import lwr.web.routes + + +def app_factory(global_conf, **local_conf): + """ + Returns the LWR WSGI application. + """ + lwr_app = LwrApp(global_conf=global_conf, **local_conf) + webapp = LwrWebApp(lwr_app=lwr_app) + atexit.register(webapp.shutdown) + return webapp + + +class LwrWebApp(RoutingApp): + """ + Web application for LWR web server. + """ + + def __init__(self, lwr_app): + super(LwrWebApp, self).__init__() + self.lwr_app = lwr_app + self.__setup_routes() + + def __setup_routes(self): + for func_name, func in inspect.getmembers(lwr.web.routes, lambda x: getattr(x, '__controller__', False)): + self.__add_route_for_function(func) + + def __add_route_for_function(self, function): + route_suffix = '/%s' % function.__name__ + # Default or old-style route without explicit manager specified, + # will be routed to manager '_default_'. + default_manager_route = route_suffix + self.add_route(default_manager_route, function) + # Add route for named manager as well. + named_manager_route = '/managers/{manager_name}%s' % route_suffix + self.add_route(named_manager_route, function) + + def __getattr__(self, name): + return getattr(self.lwr_app, name) diff --git a/server.ini.sample b/server.ini.sample index 9cc58970..73507e7d 100644 --- a/server.ini.sample +++ b/server.ini.sample @@ -17,7 +17,7 @@ host = localhost # ssl_pem = host.pem [app:main] -paste.app_factory = lwr.app:app_factory +paste.app_factory = lwr.web.wsgi:app_factory ## Directory to stage files to. This should likely be updated to point ## to an absolute path, such as /tmp/lwr_staging or C:\\lwr_staging diff --git a/test/routes_test.py b/test/routes_test.py index ebb8b68a..7f5b5295 100644 --- a/test/routes_test.py +++ b/test/routes_test.py @@ -1,6 +1,6 @@ from os.path import join -from lwr.routes import _output_path +from lwr.web.routes import _output_path from .test_utils import test_manager diff --git a/test/test_utils.py b/test/test_utils.py index 60ec50e6..6ee20d9f 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -25,7 +25,7 @@ from webtest.http import StopableWSGIServer import galaxy.util from lwr.tools import ToolBox from lwr.managers.base import JobDirectory -from lwr.framework import file_response +from lwr.web.framework import file_response TEST_DIR = dirname(__file__) ROOT_DIR = join(TEST_DIR, pardir) -- GitLab