diff --git a/config/external_service_types_conf.xml.sample b/config/external_service_types_conf.xml.sample deleted file mode 100644 index b64c0fd2c23..00000000000 --- a/config/external_service_types_conf.xml.sample +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/config/galaxy.ini.sample b/config/galaxy.ini.sample index 1d14bbb025a..8deb3317110 100644 --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -425,15 +425,6 @@ paste.app_factory = galaxy.web.buildapp:app_factory #citation_cache_data_dir = database/citations/data #citation_cache_lock_dir = database/citations/lock -# External service types config file, defining what types of external_services -# configurations are available in Galaxy (.sample is used if default does not -# exist). -#external_service_type_config_file = config/external_service_types_conf.xml - -# Path to the directory containing the external_service_types defined in the -# config. -#external_service_type_path = external_service_types - # Tools with a number of outputs not known until runtime can write these # outputs to a directory for collection by Galaxy when the job is done. # Previously, this directory was new_file_path, but using one global directory diff --git a/external_service_types/454_life_sciences.xml b/external_service_types/454_life_sciences.xml deleted file mode 100644 index 13c71ba33b7..00000000000 --- a/external_service_types/454_life_sciences.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - 1 - - - - - - - - - - - -
- - - - - - - - -
- -
diff --git a/external_service_types/applied_biosystems_solid.xml b/external_service_types/applied_biosystems_solid.xml deleted file mode 100644 index a2c70efe49f..00000000000 --- a/external_service_types/applied_biosystems_solid.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - 3 - - - - - - - - - - - - - -
- - - - - - - - - - - - - - -
- -
diff --git a/external_service_types/pacific_biosciences_smrt_portal.xml b/external_service_types/pacific_biosciences_smrt_portal.xml deleted file mode 100644 index afe1fa0081c..00000000000 --- a/external_service_types/pacific_biosciences_smrt_portal.xml +++ /dev/null @@ -1,134 +0,0 @@ - - - 1 - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
- - - http://${fields.host}/smrtportal/api - http://${fields.host}/smrtportal/# -
- - ${api_url}/Jobs - ${web_url}/MonitorJobs - - - - ${item.run_details.run.info.content.get( 'secondary_analysis_job_id' )} - - - ${jobs.jobs_url}/${jobs.job_sample.sample.secondary_analysis_job_id} - ${jobs.monitor_jobs_url}/DetailsOfJob/${jobs.job_sample.sample.secondary_analysis_job_id} - - - - ${jobs.job_sample.sample.valid_job_sample.valid.monitor_job_url} - - - - - - ${jobs.job_sample.sample.valid_job_sample.valid.job_sample_url}/Status - - - - - - - ${jobs.job_sample.sample.valid_job_sample.valid.job_sample_url}/History - - - - - - - ${jobs.job_sample.sample.valid_job_sample.valid.job_sample_url}/Log - - - - - - - ${jobs.job_sample.sample.valid_job_sample.valid.job_sample_url}/Contents - - - - - - - ${jobs.job_sample.sample.valid_job_sample.valid.job_sample_url}/Inputs - - - - - - - - - - - - - - -
-
- -
diff --git a/external_service_types/simple_unknown_sequencer.xml b/external_service_types/simple_unknown_sequencer.xml deleted file mode 100644 index 4064d37dfa4..00000000000 --- a/external_service_types/simple_unknown_sequencer.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - -
- - - - - - - - -
-
\ No newline at end of file diff --git a/lib/galaxy/app.py b/lib/galaxy/app.py index ddd905fee8d..25de2617105 100644 --- a/lib/galaxy/app.py +++ b/lib/galaxy/app.py @@ -15,7 +15,6 @@ from galaxy.managers.collections import DatasetCollectionManager from galaxy.managers.tags import GalaxyTagManager from galaxy.openid.providers import OpenIDProviders from galaxy.queue_worker import GalaxyQueueWorker -from galaxy.sample_tracking import external_service_types from galaxy.tools.cache import ( ToolCache, ToolShedRepositoryCache @@ -192,10 +191,6 @@ class UniverseApplication(object, config.ConfiguresGalaxyMixin): self.job_manager = manager.JobManager(self) self.application_stack.register_postfork_function(self.job_manager.start) self.proxy_manager = ProxyManager(self.config) - # Initialize the external service types - self.external_service_types = external_service_types.ExternalServiceTypesCollection( - self.config.external_service_type_config_file, - self.config.external_service_type_path, self) from galaxy.workflow import scheduling_manager # Must be initialized after job_config. diff --git a/lib/galaxy/config.py b/lib/galaxy/config.py index 72fbd663208..cf751d0edb9 100644 --- a/lib/galaxy/config.py +++ b/lib/galaxy/config.py @@ -41,7 +41,6 @@ PATH_DEFAULTS = dict( data_manager_config_file=['config/data_manager_conf.xml', 'data_manager_conf.xml', 'config/data_manager_conf.xml.sample'], datatypes_config_file=['config/datatypes_conf.xml', 'datatypes_conf.xml', 'config/datatypes_conf.xml.sample'], build_sites_config_file=['config/build_sites.yml', 'config/build_sites.yml.sample'], - external_service_type_config_file=['config/external_service_types_conf.xml', 'external_service_types_conf.xml', 'config/external_service_types_conf.xml.sample'], job_config_file=['config/job_conf.xml', 'job_conf.xml'], tool_destinations_config_file=['config/tool_destinations.yml', 'config/tool_destinations.yml.sample'], job_metrics_config_file=['config/job_metrics_conf.xml', 'job_metrics_conf.xml', 'config/job_metrics_conf.xml.sample'], @@ -350,8 +349,6 @@ class Configuration(object): self.persistent_communication_rooms = listify(kwargs.get("persistent_communication_rooms", []), do_strip=True) self.enable_openid = string_as_bool(kwargs.get('enable_openid', 'False')) self.enable_quotas = string_as_bool(kwargs.get('enable_quotas', 'False')) - # External Service types used in sample tracking - self.external_service_type_path = resolve_path(kwargs.get('external_service_type_path', 'external_service_types'), self.root) # Tasked job runner. self.use_tasked_jobs = string_as_bool(kwargs.get('use_tasked_jobs', False)) self.local_task_queue_workers = int(kwargs.get("local_task_queue_workers", 2)) diff --git a/lib/galaxy/external_services/__init__.py b/lib/galaxy/external_services/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/galaxy/external_services/actions.py b/lib/galaxy/external_services/actions.py deleted file mode 100644 index d39c3a05d36..00000000000 --- a/lib/galaxy/external_services/actions.py +++ /dev/null @@ -1,195 +0,0 @@ -# Contains actions that are used in External Services -import logging - -import requests - -from galaxy.util.template import fill_template -from galaxy.web import url_for -from .result_handlers.basic import ExternalServiceActionResultHandler - -log = logging.getLogger(__name__) - - -class PopulatedExternalServiceAction(object): - def __init__(self, action, param_dict): - self.action = action - self.param_dict = param_dict - self.result = None - self.handled_results = None - - def __getattr__(self, name): - return getattr(self.action, name) - - def get_action_access_link(self, trans): - return self.action.get_action_access_link(trans, self.param_dict) - - def perform_action(self): - if self.result is None: - self.result = self.action.perform_action(self.param_dict) - return self.result - - def handle_results(self, trans): - if self.result is None: - self.perform_action() - if self.handled_results is None: - self.handled_results = self.action.handle_action(self.result, self.param_dict, trans) - return self.handled_results - - -class ExternalServiceAction(object): - """ Abstract Class for External Service Actions """ - - type = None - - @classmethod - def from_elem(cls, elem, parent): - action_type = elem.get('type', None) - assert action_type, 'ExternalServiceAction requires a type' - return action_type_to_class[action_type](elem, parent) - - def __init__(self, elem, parent): - self.name = elem.get('name', None) - assert self.name, 'ExternalServiceAction requires a name' - self.label = elem.get('label', self.name) - self.parent = parent - self.result_handlers = [] - for handler in elem.findall('result_handler'): - self.result_handlers.append(ExternalServiceActionResultHandler.from_elem(handler, self)) - - def __action_url_id(self, param_dict): - rval = self.name - parent = self.parent - while hasattr(parent.parent, 'parent'): - rval = "%s|%s" % (parent.name, rval) - parent = parent.parent - rval = "%s|%s" % (param_dict['service_instance'].id, rval) - return rval - - def get_action_access_link(self, trans, param_dict): - return url_for(controller='/external_services', - action="access_action", - external_service_action=self.__action_url_id(param_dict), - item=param_dict['item'].id, - item_type=param_dict['item'].__class__.__name__) - - def populate_action(self, param_dict): - return PopulatedExternalServiceAction(self, param_dict) - - def handle_action(self, completed_action, param_dict, trans): - handled_results = [] - for handled_result in self.result_handlers: - handled_results.append(handled_result.handle_result(completed_action, param_dict, trans)) - return handled_results - - def perform_action(self, param_dict): - raise Exception('Abstract Method') - - -class ExternalServiceResult(object): - def __init__(self, name, param_dict): - self.name = name - self.param_dict = param_dict - - @property - def content(self): - raise Exception('Abstract Method') - - -class ExternalServiceWebAPIActionResult(ExternalServiceResult): - def __init__(self, name, param_dict, url, method, target): # display_handler = None ): - ExternalServiceResult.__init__(self, name, param_dict) - self.url = url - self.method = method - self.target = target - self._content = None - - @property - def content(self): - if self._content is None: - self._content = requests.get(self.url).text - return self._content - - -class ExternalServiceValueResult(ExternalServiceResult): - def __init__(self, name, param_dict, value): - self.name = name - self.param_dict = param_dict - self.value = value - - @property - def content(self): - return self.value - - -class ExternalServiceWebAPIAction(ExternalServiceAction): - """ Action that accesses an external Web API and provides handlers for the requested content """ - - type = 'web_api' - - class ExternalServiceWebAPIActionRequest(object): - def __init__(self, elem, parent): - self.target = elem.get('target', '_blank') - self.method = elem.get('method', 'post') - self.parent = parent - self.url = Template(elem.find('url'), parent) - - def get_web_api_action(self, param_dict): - name = self.parent.name - target = self.target - method = self.method - url = self.url.build_template(param_dict).strip() - return ExternalServiceWebAPIActionResult(name, param_dict, url, method, target) - - def __init__(self, elem, parent): - ExternalServiceAction.__init__(self, elem, parent) - self.web_api_request = self.ExternalServiceWebAPIActionRequest(elem.find('request'), parent) - - def perform_action(self, param_dict): - return self.web_api_request.get_web_api_action(param_dict) - - -class ExternalServiceWebAction(ExternalServiceAction): - """ Action that accesses an external web application """ - - type = 'web' - - def __init__(self, elem, parent): - ExternalServiceAction.__init__(self, elem, parent) - self.request_elem = elem.find('request') - self.url = Template(self.request_elem.find('url'), parent) - self.target = self.request_elem.get('target', '_blank') - self.method = self.request_elem.get('method', 'get') - - def get_action_access_link(self, trans, param_dict): - url = self.url.build_template(param_dict).strip() - return url - - -class ExternalServiceTemplateAction(ExternalServiceAction): - """ Action that redirects to an external URL """ - - type = 'template' - - def __init__(self, elem, parent): - ExternalServiceAction.__init__(self, elem, parent) - self.template = Template(elem.find('template'), parent) - - def perform_action(self, param_dict): - return ExternalServiceValueResult(self.name, param_dict, self.template.build_template(param_dict)) - - -action_type_to_class = { - ExternalServiceWebAction.type: ExternalServiceWebAction, - ExternalServiceWebAPIAction.type: ExternalServiceWebAPIAction, - ExternalServiceTemplateAction.type: ExternalServiceTemplateAction} - - -# utility classes -class Template(object): - def __init__(self, elem, parent): - self.text = elem.text - self.parent = parent - - def build_template(self, param_dict): - template = fill_template(self.text, context=param_dict) - return template diff --git a/lib/galaxy/external_services/parameters.py b/lib/galaxy/external_services/parameters.py deleted file mode 100644 index 5445d1a6a74..00000000000 --- a/lib/galaxy/external_services/parameters.py +++ /dev/null @@ -1,44 +0,0 @@ -# Contains parameters that are used in External Services -from galaxy.util import string_as_bool -from galaxy.util.template import fill_template - - -class ExternalServiceParameter(object): - """ Abstract Class for External Service Parameters """ - - type = None - requires_user_input = False - - @classmethod - def from_elem(cls, elem, parent): - param_type = elem.get('type', None) - assert param_type, 'ExternalServiceParameter requires a type' - return parameter_type_to_class[param_type](elem, parent) - - def __init__(self, elem, parent): - self.name = elem.get('name', None) - assert self.name, 'ExternalServiceParameter requires a name' - self.parent = parent - - def get_value(self, param_dict): - raise Exception('Abstract Method') - - -class ExternalServiceTemplateParameter(ExternalServiceParameter): - """ Parameter that returns a string containing the requested content """ - - type = 'template' - - def __init__(self, elem, parent): - ExternalServiceParameter.__init__(self, elem, parent) - self.strip = string_as_bool(elem.get('strip', 'False')) - self.text = elem.text - - def get_value(self, param_dict): - value = fill_template(self.text, context=param_dict) - if self.strip: - value = value.strip() - return value - - -parameter_type_to_class = {ExternalServiceTemplateParameter.type: ExternalServiceTemplateParameter} diff --git a/lib/galaxy/external_services/result_handlers/__init__.py b/lib/galaxy/external_services/result_handlers/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/galaxy/external_services/result_handlers/basic.py b/lib/galaxy/external_services/result_handlers/basic.py deleted file mode 100644 index 256cde1b9da..00000000000 --- a/lib/galaxy/external_services/result_handlers/basic.py +++ /dev/null @@ -1,68 +0,0 @@ -import logging -from json import loads - -log = logging.getLogger(__name__) - - -class ExternalServiceActionResultHandler(object): - """ Basic Class for External Service Actions Result Handlers""" - - type = 'display' - - @classmethod - def from_elem(cls, elem, parent): - result_type = elem.get('type', None) - assert result_type, 'ExternalServiceActionResultHandler requires a type' - return result_type_to_class[result_type](elem, parent) - - def __init__(self, elem, parent): - self.parent = parent - - def handle_result(self, result, param_dict, trans): - return result.content - # need to think about how to restore or set mime type: - # both as specified in xml and also as set by an action, - # e.g. mimetype returned from web_api action should be reused here... - - -class ExternalServiceActionURLRedirectResultHandler(ExternalServiceActionResultHandler): - """ Basic Class for External Service Actions Result Handlers""" - - type = 'web_redirect' - - @classmethod - def from_elem(cls, elem, parent): - result_type = elem.get('type', None) - assert result_type, 'ExternalServiceActionResultHandler requires a type' - return result_type_to_class[result_type](elem, parent) - - def __init__(self, elem, parent): - self.parent = parent - - def handle_result(self, result, param_dict, trans): - return trans.response.send_redirect(result.content) - - -class ExternalServiceActionJSONResultHandler(ExternalServiceActionResultHandler): - """Class for External Service Actions JQuery Result Handler""" - - type = 'json_display' - - def handle_result(self, result, param_dict, trans): - rval = loads(result.content) - return trans.fill_template('/external_services/generic_json.mako', result=rval, param_dict=param_dict, action=self.parent) - - -class ExternalServiceActionJQueryGridResultHandler(ExternalServiceActionResultHandler): - """Class for External Service Actions JQuery Result Handler""" - - type = 'jquery_grid' - - def handle_result(self, result, param_dict, trans): - rval = loads(result.content) - return trans.fill_template('/external_services/generic_jquery_grid.mako', result=rval, param_dict=param_dict, action=self.parent) - - -result_type_to_class = {} -for handler_class in [ExternalServiceActionResultHandler, ExternalServiceActionURLRedirectResultHandler, ExternalServiceActionJQueryGridResultHandler, ExternalServiceActionJSONResultHandler]: - result_type_to_class[handler_class.type] = handler_class diff --git a/lib/galaxy/external_services/service.py b/lib/galaxy/external_services/service.py deleted file mode 100644 index 5b5a15cf3b2..00000000000 --- a/lib/galaxy/external_services/service.py +++ /dev/null @@ -1,247 +0,0 @@ -# Contains objects for accessing external services applications -import logging - -from galaxy.util.bunch import Bunch -from .actions import ExternalServiceAction -from .parameters import ExternalServiceParameter - -log = logging.getLogger(__name__) - - -class ExternalServiceActionsGroup(object): - def __init__(self, parent, name, label=None): - self.name = name - self.label = label - self.parent = parent - self.items = [] - - @classmethod - def from_elem(self, elem, parent=None): - """ - Return ExternalServiceActionsGroup created from an xml element. - """ - if elem is not None: - name = elem.get('name') - label = elem.get('label') - rval = ExternalServiceActionsGroup(parent, name, label=label) - rval.load_sub_elems(elem) - else: - rval = ExternalServiceActionsGroup(None, None) - return rval - - def load_sub_elems(self, elem): - for sub_elem in elem: - if sub_elem.tag == 'param': - self.add_item(ExternalServiceParameter.from_elem(sub_elem, self)) - elif sub_elem.tag == 'action': - self.add_item(ExternalServiceAction.from_elem(sub_elem, self)) - elif sub_elem.tag == 'section': - self.add_item(ExternalServiceActionsGroup.from_elem(sub_elem, self)) - elif sub_elem.tag == 'conditional': - self.add_item(ExternalServiceActionsConditional(sub_elem, self)) - else: - raise ValueError('Unknown tag: %s' % sub_elem.tag) - - def add_item(self, item): - self.items.append(item) - - def populate(self, service_instance, item=None, param_dict=None): - return PopulatedExternalService(self, service_instance, item, param_dict) - - def prepare_actions(self, param_dict, parent_dict, parent_section): - group = Bunch() - group_section = ActionSection(self.name, self.label) - parent_section.append(group_section) - parent_dict[self.name] = group - for item in self.items: - if isinstance(item, ExternalServiceParameter): - group[item.name] = item.get_value(param_dict) - elif isinstance(item, ExternalServiceActionsGroup): - group[item.name] = item.prepare_actions(param_dict, group, group_section) - elif isinstance(item, ExternalServiceAction): - group_section.append(item.populate_action(param_dict)) - elif isinstance(item, ExternalServiceActionsConditional): - conditional_group = Bunch() - conditional_group_section = ActionSection(item.name, item.label) - group_section.append(conditional_group_section) - group[item.name] = conditional_group - for case in item.get_current_cases(param_dict): - conditional_group[case.name] = case.prepare_actions(param_dict, conditional_group, conditional_group_section) - else: - raise TypeError('unknown item type found: %s' % item) - return group - - -class ExternalServiceActionsGroupWhen(ExternalServiceActionsGroup): - type = "when" - - @classmethod - def from_elem(self, parent, elem): - """Loads the proper when by attributes of elem""" - when_type = elem.get('type') - assert when_type in when_type_to_class, TypeError("When type not implemented: %s" % when_type) - return when_type_to_class[when_type].from_elem(parent, elem) - - def is_case(self, param_dict): - raise TypeError("Abstract method") - - def get_ref(self, param_dict): - ref = param_dict - for ref_name in self.parent.ref: - assert ref_name in ref, "Required dependency '%s' not found in incoming values" % ref_name - ref = ref.get(ref_name) - return ref - - -class ValueExternalServiceActionsGroupWhen(ExternalServiceActionsGroupWhen): - type = "value" - - def __init__(self, parent, name, value, label=None): - super(ValueExternalServiceActionsGroupWhen, self).__init__(parent, name, label) - self.value = value - - @classmethod - def from_elem(self, parent, elem): - """Returns an instance of this when""" - rval = ValueExternalServiceActionsGroupWhen(parent, elem.get('name'), elem.get('value'), elem.get('label')) - rval.load_sub_elems(elem) - return rval - - def is_case(self, param_dict): - ref = self.get_ref(param_dict) - return bool(str(ref) == self.value) - - -class BooleanExternalServiceActionsGroupWhen(ExternalServiceActionsGroupWhen): - type = "boolean" - - def __init__(self, parent, name, value, label=None): - super(BooleanExternalServiceActionsGroupWhen, self).__init__(parent, name, label) - self.value = value - - @classmethod - def from_elem(self, parent, elem): - """Returns an instance of this when""" - rval = BooleanExternalServiceActionsGroupWhen(parent, elem.get('name'), elem.get('label')) - rval.load_sub_elems(elem) - return rval - - def is_case(self, param_dict): - ref = self.get_ref(param_dict) - return bool(ref) - - -class ItemIsInstanceExternalServiceActionsGroupWhen(ExternalServiceActionsGroupWhen): - type = "item_type" - - def __init__(self, parent, name, value, label=None): - super(ItemIsInstanceExternalServiceActionsGroupWhen, self).__init__(parent, name, label) - self.value = value - - @classmethod - def from_elem(self, parent, elem): - """Returns an instance of this when""" - rval = ItemIsInstanceExternalServiceActionsGroupWhen(parent, elem.get('name'), elem.get('value'), elem.get('label')) - rval.load_sub_elems(elem) - return rval - - def is_case(self, param_dict): - ref = self.get_ref(param_dict) - return ref.__class__.__name__.lower() in map(lambda x: x.lower(), self.value.split('.')) # HACK! - - -when_type_to_class = {} -for class_type in [ValueExternalServiceActionsGroupWhen, BooleanExternalServiceActionsGroupWhen, ItemIsInstanceExternalServiceActionsGroupWhen]: - when_type_to_class[class_type.type] = class_type - - -class ExternalServiceActionsConditional(object): - type = "conditional" - - def __init__(self, elem, parent): - self.parent = parent - self.name = elem.get('name', None) - assert self.name is not None, "Required 'name' attribute missing from ExternalServiceActionsConditional" - self.label = elem.get('label') - self.ref = elem.get('ref', None) - assert self.ref is not None, "Required 'ref' attribute missing from ExternalServiceActionsConditional" - self.ref = self.ref.split('.') - self.cases = [] - for when_elem in elem.findall('when'): - self.cases.append(ExternalServiceActionsGroupWhen.from_elem(self, when_elem)) - - def get_current_cases(self, param_dict): - rval = [] - for case in self.cases: - if case.is_case(param_dict): - rval.append(case) - return rval - - -class ActionSection(list): - def __init__(self, name, label): - list.__init__(self) - self.name = name - self.label = label - - def has_action(self): - for item in self: - if not isinstance(item, ActionSection): - return True - else: - if item.has_action(): - return True - return False - - -class PopulatedExternalService(object): - def __init__(self, service_group, service_instance, item, param_dict=None): - self.service_group = service_group - self.service_instance = service_instance - self.item = item - self.param_dict = param_dict - self.populate() - - def __getattr__(self, name): - return getattr(self.service_instance, name) # should .service or.service_instance should be here... - - def populate(self): - param_dict = {} - param_dict['fields'] = Bunch(**self.service_instance.form_values.content) - param_dict['item'] = self.item - param_dict['service'] = self.service_group.parent - param_dict['service_instance'] = self.service_instance - action_list = ActionSection(self.service_group.name, self.service_group.label) - for item in self.service_group.items: - if isinstance(item, ExternalServiceParameter): - param_dict[item.name] = item.get_value(param_dict) - elif isinstance(item, ExternalServiceAction): - action_list.append(item.populate_action(param_dict)) - elif isinstance(item, ExternalServiceActionsGroup): - item.prepare_actions(param_dict, param_dict, action_list) - else: - raise Exception('unknown item type found') - self.param_dict = param_dict - self.actions = action_list - - def perform_action_by_name(self, actions_list): - action = self.get_action_by_name(actions_list) - action.perform_action() - return action - - def get_action_by_name(self, actions_list): - action = None - actions = self.actions # populated actions - for name in actions_list: - action_found = False - for action in actions: - if action.name == name: - action_found = True - actions = action - break - assert action_found, 'Action not found: %s in %s' % (name, actions_list) - assert action, 'Action not found: %s' % actions_list - return action - - def __nonzero__(self): - return self.actions.has_action() diff --git a/lib/galaxy/jobs/deferred/__init__.py b/lib/galaxy/jobs/deferred/__init__.py deleted file mode 100644 index 292fabd6483..00000000000 --- a/lib/galaxy/jobs/deferred/__init__.py +++ /dev/null @@ -1,192 +0,0 @@ -""" -Queue for running deferred code via plugins. -""" -import logging -import os -import threading -from Queue import Queue - -from galaxy import model -from galaxy.util.bunch import Bunch -from galaxy.util.sleeper import Sleeper - -log = logging.getLogger(__name__) - - -class DeferredJobQueue(object): - job_states = Bunch(READY='ready', - WAIT='wait', - INVALID='invalid') - - def __init__(self, app): - self.app = app - self.sa_session = app.model.context.current - self.queue = Queue() - self.plugins = {} - self._load_plugins() - self.sleeper = Sleeper() - self.running = True - self.waiting_jobs = [] - self.__check_jobs_at_startup() - self.monitor_thread = threading.Thread(target=self.__monitor) - self.monitor_thread.start() - log.info('Deferred job queue started') - - def _load_plugins(self): - for fname in os.listdir(os.path.dirname(__file__)): - if not fname.startswith('_') and fname.endswith('.py'): - name = fname[:-3] - module_name = 'galaxy.jobs.deferred.' + name - try: - module = __import__(module_name) - except ImportError: - log.exception('Deferred job plugin appears to exist but is not loadable: %s', module_name) - continue - for comp in module_name.split(".")[1:]: - module = getattr(module, comp) - if '__all__' not in dir(module): - log.error('Plugin "%s" does not contain a list of exported classes in __all__' % module_name) - continue - for obj in module.__all__: - display_name = ':'.join((module_name, obj)) - plugin = getattr(module, obj) - for name in ('check_job', 'run_job'): - if name not in dir(plugin): - log.error('Plugin "%s" does not contain required method "%s()"' % (display_name, name)) - break - else: - self.plugins[obj] = plugin(self.app) - self.plugins[obj].job_states = self.job_states - log.debug('Loaded deferred job plugin: %s' % display_name) - - def __check_jobs_at_startup(self): - waiting_jobs = self.sa_session.query(model.DeferredJob) \ - .filter(model.DeferredJob.state == model.DeferredJob.states.WAITING).all() - for job in waiting_jobs: - if not self.__check_job_plugin(job): - continue - if 'check_interval' in dir(self.plugins[job.plugin]): - job.check_interval = self.plugins[job.plugin].check_interval - log.info('Recovered deferred job (id: %s) at startup' % job.id) - # Pass the job ID as opposed to the job, since the monitor thread - # needs to load it in its own threadlocal scoped session. - self.waiting_jobs.append(job.id) - - def __monitor(self): - while self.running: - try: - self.__monitor_step() - except Exception: - log.exception('Exception in monitor_step') - self.sleeper.sleep(1) - log.info('job queue stopped') - - def __monitor_step(self): - # TODO: Querying the database with this frequency is bad, we need message passing - new_jobs = self.sa_session.query(model.DeferredJob) \ - .filter(model.DeferredJob.state == model.DeferredJob.states.NEW).all() - for job in new_jobs: - if not self.__check_job_plugin(job): - continue - job.state = model.DeferredJob.states.WAITING - self.sa_session.add(job) - self.sa_session.flush() - if 'check_interval' in dir(self.plugins[job.plugin]): - job.check_interval = self.plugins[job.plugin].check_interval - self.waiting_jobs.append(job) - new_waiting = [] - for job in self.waiting_jobs: - try: - # Recovered jobs are passed in by ID - assert type(job) is int - job = self.sa_session.query(model.DeferredJob).get(job) - except Exception: - pass - if job.is_check_time: - try: - job_state = self.plugins[job.plugin].check_job(job) - except Exception: - self.__fail_job(job) - log.exception('Set deferred job %s to error because of an exception in check_job()' % job.id) - continue - if job_state == self.job_states.READY: - try: - self.plugins[job.plugin].run_job(job) - except Exception: - self.__fail_job(job) - log.exception('Set deferred job %s to error because of an exception in run_job()' % job.id) - continue - elif job_state == self.job_states.INVALID: - self.__fail_job(job) - log.error('Unable to run deferred job (id: %s): Plugin "%s" marked it as invalid' % (job.id, job.plugin)) - continue - else: - new_waiting.append(job) - job.last_check = 'now' - else: - new_waiting.append(job) - self.waiting_jobs = new_waiting - - def __check_job_plugin(self, job): - if job.plugin not in self.plugins: - log.error('Invalid deferred job plugin: %s') % job.plugin - job.state = model.DeferredJob.states.ERROR - self.sa_session.add(job) - self.sa_session.flush() - return False - return True - - def __check_if_ready_to_run(self, job): - return self.plugins[job.plugin].check_job(job) - - def __fail_job(self, job): - job.state = model.DeferredJob.states.ERROR - self.sa_session.add(job) - self.sa_session.flush() - - def shutdown(self): - self.running = False - self.sleeper.wake() - - -class FakeTrans(object): - """A fake trans for calling the external set metadata tool""" - - def __init__(self, app, history=None, user=None): - class Dummy(object): - def __init__(self): - self.id = None - self.app = app - self.sa_session = app.model.context.current - self.dummy = Dummy() - if not history: - self.history = Dummy() - else: - self.history = history - if not user: - self.user = Dummy() - else: - self.user = user - self.model = app.model - - def get_galaxy_session(self): - return self.dummy - - def log_event(self, message, tool_id=None): - pass - - def get_current_user_roles(self): - if self.user: - return self.user.all_roles() - else: - return [] - - def db_dataset_for(self, dbkey): - if self.history is None: - return None - datasets = self.sa_session.query(self.app.model.HistoryDatasetAssociation) \ - .filter_by(deleted=False, history_id=self.history.id, extension="len") - for ds in datasets: - if dbkey == ds.dbkey: - return ds - return None diff --git a/lib/galaxy/jobs/deferred/data_transfer.py b/lib/galaxy/jobs/deferred/data_transfer.py deleted file mode 100644 index 4b7e93d8ce2..00000000000 --- a/lib/galaxy/jobs/deferred/data_transfer.py +++ /dev/null @@ -1,384 +0,0 @@ -""" -Module for managing data transfer jobs. -""" -import logging -import re -import shutil - -from sqlalchemy import and_ - -from galaxy.datatypes import sniff -from galaxy.jobs.actions.post import ActionBox -from galaxy.jobs.deferred import FakeTrans -from galaxy.tools.parameters import visit_input_values -from galaxy.tools.parameters.basic import DataToolParameter -from galaxy.util.odict import odict -from galaxy.workflow.modules import module_factory - - -log = logging.getLogger(__name__) - -__all__ = ('DataTransfer', ) - - -class DataTransfer(object): - check_interval = 15 - dataset_name_re = re.compile('(dataset\d+)_(name)') - dataset_datatype_re = re.compile('(dataset\d+)_(datatype)') - - def __init__(self, app): - self.app = app - self.sa_session = app.model.context.current - - def create_job(self, trans, **kwd): - raise Exception("Unimplemented Method") - - def check_job(self, job): - raise Exception("Unimplemented Method") - - def run_job(self, job): - if job.params['type'] == 'init_transfer': - # TODO: don't create new downloads on restart. - if job.params['protocol'] in ['http', 'https']: - results = [] - for result in job.params['results'].values(): - result['transfer_job'] = self.app.transfer_manager.new(protocol=job.params['protocol'], - name=result['name'], - datatype=result['datatype'], - url=result['url']) - results.append(result) - elif job.params['protocol'] == 'scp': - results = [] - result = {} - sample_datasets_dict = job.params['sample_datasets_dict'] - # sample_datasets_dict looks something like the following. The outer dictionary keys are SampleDataset ids. - # {'7': {'status': 'Not started', 'name': '3.bed', 'file_path': '/tmp/library/3.bed', 'sample_id': 7, - # 'external_service_id': 2, 'error_msg': '', 'size': '8.0K'}} - for sample_dataset_id, sample_dataset_info_dict in sample_datasets_dict.items(): - result = {} - result['transfer_job'] = self.app.transfer_manager.new(protocol=job.params['protocol'], - host=job.params['host'], - user_name=job.params['user_name'], - password=job.params['password'], - sample_dataset_id=sample_dataset_id, - status=sample_dataset_info_dict['status'], - name=sample_dataset_info_dict['name'], - file_path=sample_dataset_info_dict['file_path'], - sample_id=sample_dataset_info_dict['sample_id'], - external_service_id=sample_dataset_info_dict['external_service_id'], - error_msg=sample_dataset_info_dict['error_msg'], - size=sample_dataset_info_dict['size']) - results.append(result) - self.app.transfer_manager.run([r['transfer_job'] for r in results]) - for result in results: - transfer_job = result.pop('transfer_job') - self.create_job(None, - transfer_job_id=transfer_job.id, - result=transfer_job.params, - sample_id=job.params['sample_id']) - # Update the state of the relevant SampleDataset - new_status = self.app.model.SampleDataset.transfer_status.IN_QUEUE - self._update_sample_dataset_status(protocol=job.params['protocol'], - sample_id=job.params['sample_id'], - result_dict=transfer_job.params, - new_status=new_status, - error_msg='') - job.state = self.app.model.DeferredJob.states.OK - self.sa_session.add(job) - self.sa_session.flush() - # TODO: Error handling: failure executing, or errors returned from the manager - if job.params['type'] == 'finish_transfer': - protocol = job.params['protocol'] - # Update the state of the relevant SampleDataset - new_status = self.app.model.SampleDataset.transfer_status.ADD_TO_LIBRARY - if protocol in ['http', 'https']: - result_dict = job.params['result'] - library_dataset_name = result_dict['name'] - extension = result_dict['datatype'] - elif protocol in ['scp']: - # In this case, job.params will be a dictionary that contains a key named 'result'. The value - # of the result key is a dictionary that looks something like: - # {'sample_dataset_id': '8', 'status': 'Not started', 'protocol': 'scp', 'name': '3.bed', - # 'file_path': '/data/library/3.bed', 'host': '127.0.0.1', 'sample_id': 8, 'external_service_id': 2, - # 'local_path': '/tmp/kjl2Ss4', 'password': 'galaxy', 'user_name': 'gvk', 'error_msg': '', 'size': '8.0K'} - try: - tj = self.sa_session.query(self.app.model.TransferJob).get(int(job.params['transfer_job_id'])) - result_dict = tj.params - result_dict['local_path'] = tj.path - except Exception as e: - log.error("Updated transfer result unavailable, using old result. Error was: %s" % str(e)) - result_dict = job.params['result'] - library_dataset_name = result_dict['name'] - # Determine the data format (see the relevant TODO item in the manual_data_transfer plugin).. - extension = sniff.guess_ext(result_dict['local_path'], sniff_order=self.app.datatypes_registry.sniff_order) - self._update_sample_dataset_status(protocol=job.params['protocol'], - sample_id=int(job.params['sample_id']), - result_dict=result_dict, - new_status=new_status, - error_msg='') - sample = self.sa_session.query(self.app.model.Sample).get(int(job.params['sample_id'])) - ld = self.app.model.LibraryDataset(folder=sample.folder, name=library_dataset_name) - self.sa_session.add(ld) - self.sa_session.flush() - self.app.security_agent.copy_library_permissions(FakeTrans(self.app), sample.folder, ld) - ldda = self.app.model.LibraryDatasetDatasetAssociation(name=library_dataset_name, - extension=extension, - dbkey='?', - library_dataset=ld, - create_dataset=True, - sa_session=self.sa_session) - ldda.message = 'Transferred by the Data Transfer Plugin' - self.sa_session.add(ldda) - self.sa_session.flush() - ldda.state = ldda.states.QUEUED # flushed in the set property - ld.library_dataset_dataset_association_id = ldda.id - self.sa_session.add(ld) - self.sa_session.flush() - try: - # Move the dataset from its temporary location - shutil.move(job.transfer_job.path, ldda.file_name) - ldda.init_meta() - for name, spec in ldda.metadata.spec.items(): - if name not in ['name', 'info', 'dbkey', 'base_name']: - if spec.get('default'): - setattr(ldda.metadata, name, spec.unwrap(spec.get('default'))) - self.app.datatypes_registry.set_external_metadata_tool.tool_action.execute(self.app.datatypes_registry.set_external_metadata_tool, - FakeTrans(self.app, - history=sample.history, - user=sample.request.user), - incoming={'input1': ldda}) - ldda.state = ldda.states.OK - # TODO: not sure if this flush is necessary - self.sa_session.add(ldda) - self.sa_session.flush() - except Exception as e: - log.exception('Failure preparing library dataset for finished transfer job (id: %s) via deferred job (id: %s):' % - (str(job.transfer_job.id), str(job.id))) - ldda.state = ldda.states.ERROR - if sample.workflow: - log.debug("\n\nLogging sample mappings as: %s" % sample.workflow['mappings']) - log.debug("job.params: %s" % job.params) - # We have a workflow. Update all mappings to ldda's, and when the final one is done - # execute_workflow with either the provided history, or a new one. - sub_done = True - rep_done = False - for k, v in sample.workflow['mappings'].items(): - if 'hda' not in v and v['ds_tag'].startswith('hi|'): - sample.workflow['mappings'][k]['hda'] = self.app.security.decode_id(v['ds_tag'][3:]) - for key, value in sample.workflow['mappings'].items(): - if 'url' in value and value['url'] == job.params['result']['url']: - # DBTODO Make sure all ds| mappings get the URL of the dataset, for linking to later. - # If this dataset maps to what we just finished, update the ldda id in the sample. - sample.workflow['mappings'][key]['ldda'] = ldda.id - rep_done = True - # DBTODO replace the hi| mappings with the hda here. Just rip off the first three chars. - elif 'ldda' not in value and 'hda' not in value: - # We're not done if some mappings still don't have ldda or hda mappings. - sub_done = False - if sub_done and rep_done: - if not sample.history: - new_history = self.app.model.History(name="New History From %s" % sample.name, user=sample.request.user) - self.sa_session.add(new_history) - sample.history = new_history - self.sa_session.flush() - self._execute_workflow(sample) - # Check the workflow for substitution done-ness - self.sa_session.add(sample) - self.sa_session.flush() - elif sample.history: - # We don't have a workflow, but a history was provided. - # No processing, go ahead and chunk everything in the history. - if ldda.dataset.state in ['new', 'upload', 'queued', 'running', 'empty', 'discarded']: - log.error("Cannot import dataset '%s' to user history since its state is '%s'. " % (ldda.name, ldda.dataset.state)) - elif ldda.dataset.state in ['ok', 'error']: - ldda.to_history_dataset_association(target_history=sample.history, add_to_history=True) - # Finished - job.state = self.app.model.DeferredJob.states.OK - self.sa_session.add(job) - self.sa_session.flush() - # Update the state of the relevant SampleDataset - new_status = self.app.model.SampleDataset.transfer_status.COMPLETE - self._update_sample_dataset_status(protocol=job.params['protocol'], - sample_id=int(job.params['sample_id']), - result_dict=job.params['result'], - new_status=new_status, - error_msg='') - if sample.datasets and not sample.untransferred_dataset_files: - # Update the state of the sample to the sample's request type's final state. - new_state = sample.request.type.final_sample_state - self._update_sample_state(sample.id, new_state) - # Update the state of the request, if possible - self._update_request_state(sample.request.id) - - def _missing_params(self, params, required_params): - missing_params = [x for x in required_params if x not in params] - if missing_params: - log.error('Job parameters missing required keys: %s' % ', '.join(missing_params)) - return True - return False - - def _update_sample_dataset_status(self, protocol, sample_id, result_dict, new_status, error_msg=None): - # result_dict looks something like: - # {'url': '127.0.0.1/data/filtered_subreads.fa', 'name': 'Filtered reads'} - - # TODO: error checking on valid new_status value - if protocol in ['http', 'https']: - sample_dataset = self.sa_session.query(self.app.model.SampleDataset) \ - .filter(and_(self.app.model.SampleDataset.table.c.sample_id == sample_id, - self.app.model.SampleDataset.table.c.name == result_dict['name'], - self.app.model.SampleDataset.table.c.file_path == result_dict['url'])) \ - .first() - elif protocol in ['scp']: - sample_dataset = self.sa_session.query(self.app.model.SampleDataset).get(int(result_dict['sample_dataset_id'])) - sample_dataset.status = new_status - sample_dataset.error_msg = error_msg - self.sa_session.add(sample_dataset) - self.sa_session.flush() - - def _update_sample_state(self, sample_id, new_state, comment=None): - sample = self.sa_session.query(self.app.model.Sample).get(sample_id) - if comment is None: - comment = 'Sample state set to %s' % str(new_state) - event = self.app.model.SampleEvent(sample, new_state, comment) - self.sa_session.add(event) - self.sa_session.flush() - - def _update_request_state(self, request_id): - request = self.sa_session.query(self.app.model.Request).get(request_id) - # Make sure all the samples of the current request have the same state - common_state = request.samples_have_common_state - if not common_state: - # If the current request state is complete and one of its samples moved from - # the final sample state, then move the request state to In-progress - if request.is_complete: - message = "At least 1 sample state moved from the final sample state, so now the request's state is (%s)" % request.states.SUBMITTED - event = self.app.model.RequestEvent(request, request.states.SUBMITTED, message) - self.sa_session.add(event) - self.sa_session.flush() - else: - request_type_state = request.type.final_sample_state - if common_state.id == request_type_state.id: - # Since all the samples are in the final state, change the request state to 'Complete' - comment = "All samples of this sequencing request are in the final sample state (%s). " % request_type_state.name - state = request.states.COMPLETE - else: - comment = "All samples of this sequencing request are in the (%s) sample state. " % common_state.name - state = request.states.SUBMITTED - event = self.app.model.RequestEvent(request, state, comment) - self.sa_session.add(event) - self.sa_session.flush() - # TODO: handle email notification if it is configured to be sent when the samples are in this state. - - def _execute_workflow(self, sample): - for key, value in sample.workflow['mappings'].items(): - if 'hda' not in value and 'ldda' in value: - # If HDA is already here, it's an external input, we're not copying anything. - ldda = self.sa_session.query(self.app.model.LibraryDatasetDatasetAssociation).get(value['ldda']) - if ldda.dataset.state in ['new', 'upload', 'queued', 'running', 'empty', 'discarded']: - log.error("Cannot import dataset '%s' to user history since its state is '%s'. " % (ldda.name, ldda.dataset.state)) - elif ldda.dataset.state in ['ok', 'error']: - hda = ldda.to_history_dataset_association(target_history=sample.history, add_to_history=True) - sample.workflow['mappings'][key]['hda'] = hda.id - self.sa_session.add(sample) - self.sa_session.flush() - workflow_dict = sample.workflow - import copy - new_wf_dict = copy.deepcopy(workflow_dict) - for key in workflow_dict['mappings']: - if not isinstance(key, int): - new_wf_dict['mappings'][int(key)] = workflow_dict['mappings'][key] - workflow_dict = new_wf_dict - fk_trans = FakeTrans(self.app, history=sample.history, user=sample.request.user) - workflow = self.sa_session.query(self.app.model.Workflow).get(workflow_dict['id']) - if not workflow: - log.error("Workflow mapping failure.") - return - if len(workflow.steps) == 0: - log.error("Workflow cannot be run because it does not have any steps") - return - if workflow.has_cycles: - log.error("Workflow cannot be run because it contains cycles") - return - if workflow.has_errors: - log.error("Workflow cannot be run because of validation errors in some steps") - return - # Build the state for each step - errors = {} - # Build a fake dictionary prior to execution. - # Prepare each step - for step in workflow.steps: - step.upgrade_messages = {} - # Contruct modules - if step.type == 'tool' or step.type is None: - # Restore the tool state for the step - step.module = module_factory.from_workflow_step(fk_trans, step) - # Fix any missing parameters - step.upgrade_messages = step.module.check_and_update_state() - # Any connected input needs to have value DummyDataset (these - # are not persisted so we need to do it every time) - step.module.add_dummy_datasets(connections=step.input_connections) - # Store state with the step - step.state = step.module.state - # Error dict - if step.tool_errors: - errors[step.id] = step.tool_errors - else: - # Non-tool specific stuff? - step.module = module_factory.from_workflow_step(fk_trans, step) - step.state = step.module.get_runtime_state() - # Connections by input name - step.input_connections_by_name = dict((conn.input_name, conn) for conn in step.input_connections) - for step in workflow.steps: - step.upgrade_messages = {} - # Connections by input name - step.input_connections_by_name = \ - dict((conn.input_name, conn) for conn in step.input_connections) - # Extract just the arguments for this step by prefix - step_errors = None - if step.type == 'tool' or step.type is None: - module = module_factory.from_workflow_step(fk_trans, step) - # Fix any missing parameters - step.upgrade_messages = module.check_and_update_state() - # Any connected input needs to have value DummyDataset (these - # are not persisted so we need to do it every time) - module.add_dummy_datasets(connections=step.input_connections) - # Get the tool - tool = module.tool - # Get the state - step.state = state = module.state - if step_errors: - errors[step.id] = state.inputs["__errors__"] = step_errors - # Run each step, connecting outputs to inputs - workflow_invocation = self.app.model.WorkflowInvocation() - workflow_invocation.workflow = workflow - outputs = odict() - for i, step in enumerate(workflow.steps): - job = None - if step.type == 'tool' or step.type is None: - tool = self.app.toolbox.get_tool(step.tool_id) - - def callback(input, prefixed_name, **kwargs): - if isinstance(input, DataToolParameter): - if prefixed_name in step.input_connections_by_name: - conn = step.input_connections_by_name[prefixed_name] - return outputs[conn.output_step.id][conn.output_name] - visit_input_values(tool.inputs, step.state.inputs, callback) - job, out_data = tool.execute(fk_trans, step.state.inputs, history=sample.history) - outputs[step.id] = out_data - for pja in step.post_job_actions: - if pja.action_type in ActionBox.immediate_actions: - ActionBox.execute(self.app, self.sa_session, pja, job, replacement_dict=None) - else: - job.add_post_job_action(pja) - else: - job, out_data = step.module.execute(fk_trans, step.state) - outputs[step.id] = out_data - if step.id in workflow_dict['mappings']: - data = self.sa_session.query(self.app.model.HistoryDatasetAssociation).get(workflow_dict['mappings'][str(step.id)]['hda']) - outputs[step.id]['output'] = data - workflow_invocation_step = self.app.model.WorkflowInvocationStep() - workflow_invocation_step.workflow_invocation = workflow_invocation - workflow_invocation_step.workflow_step = step - workflow_invocation_step.job = job - self.sa_session.add(workflow_invocation) - self.sa_session.flush() diff --git a/lib/galaxy/jobs/deferred/manual_data_transfer.py b/lib/galaxy/jobs/deferred/manual_data_transfer.py deleted file mode 100644 index 2b3abaee68a..00000000000 --- a/lib/galaxy/jobs/deferred/manual_data_transfer.py +++ /dev/null @@ -1,107 +0,0 @@ -""" -Generic module for managing manual data transfer jobs using Galaxy's built-in file browser. -This module can be used by various external services that are configured to transfer data manually. -""" -import logging - -from .data_transfer import DataTransfer - -log = logging.getLogger(__name__) - -__all__ = ('ManualDataTransferPlugin', ) - - -class ManualDataTransferPlugin(DataTransfer): - def __init__(self, app): - super(ManualDataTransferPlugin, self).__init__(app) - - def create_job(self, trans, **kwd): - if 'sample' in kwd and 'sample_datasets' in kwd and 'external_service' in kwd and 'external_service_type' in kwd: - sample = kwd['sample'] - sample_datasets = kwd['sample_datasets'] - external_service = kwd['external_service'] - external_service_type = kwd['external_service_type'] - # TODO: is there a better way to store the protocol? - protocol = next(iter(external_service_type.data_transfer.keys())) - host = external_service.form_values.content['host'] - user_name = external_service.form_values.content['user_name'] - password = external_service.form_values.content['password'] - # TODO: In the future, we may want to implement a way for the user to associate a selected file with one of - # the run outputs configured in the section of the external service config file. The - # following was a first pass at implementing something (the datatype was included in the sample_dataset_dict), - # but without a way for the user to associate stuff it's useless. However, allowing the user this ability may - # open a can of worms, so maybe we shouldn't do it??? - # - # for run_result_file_name, run_result_file_datatype in external_service_type.run_details[ 'results' ].items(): - # # external_service_type.run_details[ 'results' ] looks something like: {'dataset1_name': 'dataset1_datatype'} - # if run_result_file_datatype in external_service.form_values.content: - # datatype = external_service.form_values.content[ run_result_file_datatype ] - # - # When the transfer is automatic (the process used in the SMRT Portal plugin), the datasets and datatypes - # can be matched up to those configured in the settings in the external service type config - # (e.g., pacific_biosciences_smrt_portal.xml). However, that's a bit trickier here since the user is manually - # selecting files for transfer. - sample_datasets_dict = {} - for sample_dataset in sample_datasets: - sample_dataset_id = sample_dataset.id - sample_dataset_dict = dict(sample_id=sample_dataset.sample.id, - name=sample_dataset.name, - file_path=sample_dataset.file_path, - status=sample_dataset.status, - error_msg=sample_dataset.error_msg, - size=sample_dataset.size, - external_service_id=sample_dataset.external_service.id) - sample_datasets_dict[sample_dataset_id] = sample_dataset_dict - params = {'type' : 'init_transfer', - 'sample_id' : sample.id, - 'sample_datasets_dict' : sample_datasets_dict, - 'protocol' : protocol, - 'host' : host, - 'user_name' : user_name, - 'password' : password} - elif 'transfer_job_id' in kwd: - params = {'type' : 'finish_transfer', - 'protocol' : kwd['result']['protocol'], - 'sample_id' : kwd['sample_id'], - 'result' : kwd['result'], - 'transfer_job_id' : kwd['transfer_job_id']} - else: - log.error('No job was created because kwd does not include "samples" and "sample_datasets" or "transfer_job_id".') - return - deferred_job = self.app.model.DeferredJob(state=self.app.model.DeferredJob.states.NEW, - plugin='ManualDataTransferPlugin', - params=params) - self.sa_session.add(deferred_job) - self.sa_session.flush() - log.debug('Created a deferred job in the ManualDataTransferPlugin of type: %s' % params['type']) - # TODO: error reporting to caller (if possible?) - - def check_job(self, job): - if self._missing_params(job.params, ['type']): - return self.job_states.INVALID - if job.params['type'] == 'init_transfer': - if job.params['protocol'] in ['http', 'https']: - raise Exception("Manual data transfer is not yet supported for http(s).") - elif job.params['protocol'] == 'scp': - if self._missing_params(job.params, ['protocol', 'host', 'user_name', 'password', 'sample_id', 'sample_datasets_dict']): - return self.job_states.INVALID - # TODO: what kind of checks do we need here? - return self.job_states.READY - return self.job_states.WAIT - if job.params['type'] == 'finish_transfer': - if self._missing_params(job.params, ['transfer_job_id']): - return self.job_states.INVALID - # Get the TransferJob object and add it to the DeferredJob so we only look it up once. - if not hasattr(job, 'transfer_job'): - job.transfer_job = self.sa_session.query(self.app.model.TransferJob).get(int(job.params['transfer_job_id'])) - state = self.app.transfer_manager.get_state(job.transfer_job) - if not state: - log.error('No state for transfer job id: %s' % job.transfer_job.id) - return self.job_states.WAIT - if state['state'] in self.app.model.TransferJob.terminal_states: - return self.job_states.READY - log.debug("Checked on finish transfer job %s, not done yet." % job.id) - return self.job_states.WAIT - else: - log.error('Unknown job type for ManualDataTransferPlugin: %s' % str(job.params['type'])) - return self.job_states.INVALID diff --git a/lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py b/lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py deleted file mode 100644 index b90f9940bcd..00000000000 --- a/lib/galaxy/jobs/deferred/pacific_biosciences_smrt_portal.py +++ /dev/null @@ -1,131 +0,0 @@ -""" -Module for managing jobs in Pacific Bioscience's SMRT Portal and automatically transferring files -produced by SMRT Portal. -""" -import logging -from string import Template - -import requests - -from .data_transfer import DataTransfer - -log = logging.getLogger(__name__) - -__all__ = ('SMRTPortalPlugin', ) - - -class SMRTPortalPlugin(DataTransfer): - api_path = '/smrtportal/api' - - def __init__(self, app): - super(SMRTPortalPlugin, self).__init__(app) - - def create_job(self, trans, **kwd): - if 'secondary_analysis_job_id' in kwd: - sample = kwd['sample'] - smrt_job_id = kwd['secondary_analysis_job_id'] - external_service = sample.request.type.get_external_service('pacific_biosciences_smrt_portal') - external_service.load_data_transfer_settings(trans) - http_configs = external_service.data_transfer[trans.model.ExternalService.data_transfer_protocol.HTTP] - if not http_configs['automatic_transfer']: - raise Exception("Manual data transfer using http is not yet supported.") - smrt_host = external_service.form_values.content['host'] - external_service_type = external_service.get_external_service_type(trans) - # TODO: is there a better way to store the protocol? - # external_service_type.data_transfer looks somethng like - # {'http': } - protocol = next(iter(external_service_type.data_transfer.keys())) - results = {} - for k, v in external_service.form_values.content.items(): - match = self.dataset_name_re.match(k) or self.dataset_datatype_re.match(k) - if match: - id, field = match.groups() - if id in results: - results[id][field] = v - else: - results[id] = {field : v} - for id, attrs in results.items(): - url_template = external_service_type.run_details['results_urls'].get(id + '_name') - url = Template(url_template).substitute(host=smrt_host, secondary_analysis_job_id=kwd['secondary_analysis_job_id']) - results[id]['url'] = url - if sample.workflow: - # DBTODO Make sure all ds| mappings get the URL of the dataset, for linking to later. - for k, v in sample.workflow['mappings'].items(): - if 'ds|%s' % id in v.values(): - sample.workflow['mappings'][k]['url'] = url - self.sa_session.add(sample) - self.sa_session.flush() - params = {'type' : 'init_transfer', - 'protocol' : protocol, - 'sample_id' : sample.id, - 'results' : results, - 'smrt_host' : smrt_host, - 'smrt_job_id' : smrt_job_id} - # Create a new SampleDataset for each run result dataset - self._associate_untransferred_datasets_with_sample(sample, external_service, results) - elif 'transfer_job_id' in kwd: - params = {'type' : 'finish_transfer', - 'protocol' : kwd['result']['protocol'], - 'sample_id' : kwd['sample_id'], - 'result' : kwd['result'], - 'transfer_job_id' : kwd['transfer_job_id']} - else: - log.error('No job was created because kwd does not include "secondary_analysis_job_id" or "transfer_job_id".') - return - deferred_job = self.app.model.DeferredJob(state=self.app.model.DeferredJob.states.NEW, - plugin='SMRTPortalPlugin', - params=params) - self.sa_session.add(deferred_job) - self.sa_session.flush() - log.debug('Created a deferred job in the SMRTPortalPlugin of type: %s' % params['type']) - # TODO: error reporting to caller (if possible?) - - def check_job(self, job): - if self._missing_params(job.params, ['type']): - return self.job_states.INVALID - if job.params['type'] == 'init_transfer': - if self._missing_params(job.params, ['smrt_host', 'smrt_job_id']): - return self.job_states.INVALID - url = 'http://' + job.params['smrt_host'] + self.api_path + '/Jobs/' + job.params['smrt_job_id'] + '/Status' - r = requests.get(url) - status = r.json() - # TODO: error handling: unexpected json or bad response, bad url, etc. - if status['Code'] == 'Completed': - log.debug("SMRT Portal job '%s' is Completed. Initiating transfer." % job.params['smrt_job_id']) - return self.job_states.READY - return self.job_states.WAIT - if job.params['type'] == 'finish_transfer': - if self._missing_params(job.params, ['transfer_job_id']): - return self.job_states.INVALID - # Get the TransferJob object and add it to the DeferredJob so we only look it up once. - if not hasattr(job, 'transfer_job'): - job.transfer_job = self.sa_session.query(self.app.model.TransferJob).get(int(job.params['transfer_job_id'])) - state = self.app.transfer_manager.get_state(job.transfer_job) - if not state: - log.error('No state for transfer job id: %s' % job.transfer_job.id) - return self.job_states.WAIT - if state['state'] in self.app.model.TransferJob.terminal_states: - return self.job_states.READY - log.debug("Checked on finish transfer job %s, not done yet." % job.id) - return self.job_states.WAIT - else: - log.error('Unknown job type for SMRTPortalPlugin: %s' % str(job.params['type'])) - return self.job_states.INVALID - - def _associate_untransferred_datasets_with_sample(self, sample, external_service, results_dict): - # results_dict looks something like: - # {'dataset2': {'datatype': 'fasta', 'url': '127.0.0.1:8080/data/filtered_subreads.fa', 'name': 'Filtered reads'} } - for key, val in results_dict.items(): - file_path = val['url'] - status = self.app.model.SampleDataset.transfer_status.NOT_STARTED - name = val['name'] - size = 'unknown' - sample_dataset = self.app.model.SampleDataset(sample=sample, - file_path=file_path, - status=status, - name=name, - error_msg='', - size=size, - external_service=external_service) - self.sa_session.add(sample_dataset) - self.sa_session.flush() diff --git a/lib/galaxy/managers/context.py b/lib/galaxy/managers/context.py index 0bb24625b37..f82c6d3af0b 100644 --- a/lib/galaxy/managers/context.py +++ b/lib/galaxy/managers/context.py @@ -98,11 +98,6 @@ class ProvidesAppContext(object): def install_model(self): return self.app.install_model - def request_types(self): - if self.sa_session.query(self.app.model.RequestType).filter_by(deleted=False).count() > 0: - return True - return False - class ProvidesUserContext(object): """ For transaction-like objects to provide Galaxy convience layer for diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py index b771faf3593..a3a48c5c264 100644 --- a/lib/galaxy/model/__init__.py +++ b/lib/galaxy/model/__init__.py @@ -11,7 +11,6 @@ import numbers import operator import os import pwd -import socket import time from datetime import datetime, timedelta from string import Template @@ -32,7 +31,7 @@ from galaxy.model.item_attrs import UsesAnnotations from galaxy.model.util import pgcalc from galaxy.security import get_permitted_actions from galaxy.util import (directory_hash_id, Params, ready_name_for_url, - restore_text, send_mail, unicodify, unique_id) + restore_text, unicodify, unique_id) from galaxy.util.bunch import Bunch from galaxy.util.dictifiable import Dictifiable from galaxy.util.hash_util import new_secure_hash @@ -4415,12 +4414,7 @@ class MetadataFile(StorableObject): class FormDefinition(object, Dictifiable): # The following form_builder classes are supported by the FormDefinition class. supported_field_types = [AddressField, CheckboxField, PasswordField, SelectField, TextArea, TextField, WorkflowField, WorkflowMappingField, HistoryField] - types = Bunch(REQUEST='Sequencing Request Form', - SAMPLE='Sequencing Sample Form', - EXTERNAL_SERVICE='External Service Information Form', - RUN_DETAILS_TEMPLATE='Sample run details template', - LIBRARY_INFO_TEMPLATE='Library information template', - USER_INFO='User Information') + types = Bunch(USER_INFO='User Information') dict_collection_visible_keys = ['id', 'name'] dict_element_visible_keys = ['id', 'name', 'desc', 'form_definition_current_id', 'fields', 'layout'] @@ -4560,497 +4554,6 @@ class FormValues(object): self.content = content -class Request(object, Dictifiable): - states = Bunch(NEW='New', - SUBMITTED='In Progress', - REJECTED='Rejected', - COMPLETE='Complete') - dict_collection_visible_keys = ['id', 'name', 'state'] - - def __init__(self, name=None, desc=None, request_type=None, user=None, form_values=None, notification=None): - self.name = name - self.desc = desc - self.type = request_type - self.values = form_values - self.user = user - self.notification = notification - self.samples_list = [] - - @property - def state(self): - latest_event = self.latest_event - if latest_event: - return latest_event.state - return None - - @property - def latest_event(self): - if self.events: - return self.events[0] - return None - - @property - def samples_have_common_state(self): - """ - Returns the state of this request's samples when they are all - in one common state. Otherwise returns False. - """ - state_for_comparison = self.samples[0].state - if state_for_comparison is None: - for s in self.samples: - if s.state is not None: - return False - for s in self.samples: - if s.state.id != state_for_comparison.id: - return False - return state_for_comparison - - @property - def last_comment(self): - latest_event = self.latest_event - if latest_event: - if latest_event.comment: - return latest_event.comment - return '' - return 'No comment' - - def get_sample(self, sample_name): - for sample in self.samples: - if sample.name == sample_name: - return sample - return None - - @property - def is_unsubmitted(self): - return self.state in [self.states.REJECTED, self.states.NEW] - - @property - def is_rejected(self): - return self.state == self.states.REJECTED - - @property - def is_submitted(self): - return self.state == self.states.SUBMITTED - - @property - def is_new(self): - - return self.state == self.states.NEW - - @property - def is_complete(self): - return self.state == self.states.COMPLETE - - @property - def samples_without_library_destinations(self): - # Return all samples that are not associated with a library - samples = [] - for sample in self.samples: - if not sample.library: - samples.append(sample) - return samples - - @property - def samples_with_bar_code(self): - # Return all samples that have associated bar code - samples = [] - for sample in self.samples: - if sample.bar_code: - samples.append(sample) - return samples - - def send_email_notification(self, trans, common_state, final_state=False): - # Check if an email notification is configured to be sent when the samples - # are in this state - if self.notification and common_state.id not in self.notification['sample_states']: - return - comments = '' - # Send email - if trans.app.config.smtp_server is not None and self.notification and self.notification['email']: - body = """ -Galaxy Sample Tracking Notification -=================================== - -User: %(user)s - -Sequencing request: %(request_name)s -Sequencer configuration: %(request_type)s -Sequencing request state: %(request_state)s - -Number of samples: %(num_samples)s -All samples in state: %(sample_state)s - -""" - values = dict(user=self.user.email, - request_name=self.name, - request_type=self.type.name, - request_state=self.state, - num_samples=str(len(self.samples)), - sample_state=common_state.name, - create_time=self.create_time, - submit_time=self.create_time) - body = body % values - # check if this is the final state of the samples - if final_state: - txt = "Sample Name -> Data Library/Folder\r\n" - for s in self.samples: - if s.library: - library_name = s.library.name - folder_name = s.folder.name - else: - library_name = 'No target data library' - folder_name = 'No target data library folder' - txt = txt + "%s -> %s/%s\r\n" % (s.name, library_name, folder_name) - body = body + txt - to = self.notification['email'] - frm = trans.app.config.email_from - if frm is None: - host = trans.request.host.split(':')[0] - if host in ['localhost', '127.0.0.1', '0.0.0.0']: - host = socket.getfqdn() - frm = 'galaxy-no-reply@' + host - subject = "Galaxy Sample Tracking notification: '%s' sequencing request" % self.name - try: - send_mail(frm, to, subject, body, trans.app.config) - comments = "Email notification sent to %s." % ", ".join(to).strip().strip(',') - except Exception as e: - comments = "Email notification failed. (%s)" % str(e) - # update the request history with the email notification event - elif not trans.app.config.smtp_server: - comments = "Email notification failed as SMTP server not set in config file" - if comments: - event = RequestEvent(self, self.state, comments) - trans.sa_session.add(event) - trans.sa_session.flush() - return comments - - -class RequestEvent(object): - def __init__(self, request=None, request_state=None, comment=''): - self.request = request - self.state = request_state - self.comment = comment - - -class ExternalService(object): - data_transfer_protocol = Bunch(HTTP='http', - HTTPS='https', - SCP='scp') - - def __init__(self, name=None, description=None, external_service_type_id=None, version=None, form_definition_id=None, form_values_id=None, deleted=None): - self.name = name - self.description = description - self.external_service_type_id = external_service_type_id - self.version = version - self.form_definition_id = form_definition_id - self.form_values_id = form_values_id - self.deleted = deleted - self.label = None # Used in the request_type controller's __build_external_service_select_field() method - - def get_external_service_type(self, trans): - return trans.app.external_service_types.all_external_service_types[self.external_service_type_id] - - def load_data_transfer_settings(self, trans): - trans.app.external_service_types.reload(self.external_service_type_id) - self.data_transfer = {} - external_service_type = self.get_external_service_type(trans) - for data_transfer_protocol, data_transfer_obj in external_service_type.data_transfer.items(): - if data_transfer_protocol == self.data_transfer_protocol.SCP: - scp_configs = {} - automatic_transfer = data_transfer_obj.config.get('automatic_transfer', 'false') - scp_configs['automatic_transfer'] = galaxy.util.string_as_bool(automatic_transfer) - scp_configs['host'] = self.form_values.content.get(data_transfer_obj.config.get('host', ''), '') - scp_configs['user_name'] = self.form_values.content.get(data_transfer_obj.config.get('user_name', ''), '') - scp_configs['password'] = self.form_values.content.get(data_transfer_obj.config.get('password', ''), '') - scp_configs['data_location'] = self.form_values.content.get(data_transfer_obj.config.get('data_location', ''), '') - scp_configs['rename_dataset'] = self.form_values.content.get(data_transfer_obj.config.get('rename_dataset', ''), '') - self.data_transfer[self.data_transfer_protocol.SCP] = scp_configs - if data_transfer_protocol == self.data_transfer_protocol.HTTP: - http_configs = {} - automatic_transfer = data_transfer_obj.config.get('automatic_transfer', 'false') - http_configs['automatic_transfer'] = galaxy.util.string_as_bool(automatic_transfer) - self.data_transfer[self.data_transfer_protocol.HTTP] = http_configs - - def populate_actions(self, trans, item, param_dict=None): - return self.get_external_service_type(trans).actions.populate(self, item, param_dict=param_dict) - - -class RequestType(object, Dictifiable): - dict_collection_visible_keys = ['id', 'name', 'desc'] - dict_element_visible_keys = ['id', 'name', 'desc', 'request_form_id', 'sample_form_id'] - rename_dataset_options = Bunch(NO='Do not rename', - SAMPLE_NAME='Preprend sample name', - EXPERIMENT_NAME='Prepend experiment name', - EXPERIMENT_AND_SAMPLE_NAME='Prepend experiment and sample name') - permitted_actions = get_permitted_actions(filter='REQUEST_TYPE') - - def __init__(self, name=None, desc=None, request_form=None, sample_form=None): - self.name = name - self.desc = desc - self.request_form = request_form - self.sample_form = sample_form - - @property - def external_services(self): - external_services = [] - for rtesa in self.external_service_associations: - external_services.append(rtesa.external_service) - return external_services - - def get_external_service(self, external_service_type_id): - for rtesa in self.external_service_associations: - if rtesa.external_service.external_service_type_id == external_service_type_id: - return rtesa.external_service - return None - - def get_external_services_for_manual_data_transfer(self, trans): - '''Returns all external services that use manual data transfer''' - external_services = [] - for rtesa in self.external_service_associations: - external_service = rtesa.external_service - # load data transfer settings - external_service.load_data_transfer_settings(trans) - if external_service.data_transfer: - for transfer_type, transfer_type_settings in external_service.data_transfer.items(): - if not transfer_type_settings['automatic_transfer']: - external_services.append(external_service) - return external_services - - def delete_external_service_associations(self, trans): - '''Deletes all external service associations.''' - flush_needed = False - for rtesa in self.external_service_associations: - trans.sa_session.delete(rtesa) - flush_needed = True - if flush_needed: - trans.sa_session.flush() - - def add_external_service_association(self, trans, external_service): - rtesa = trans.model.RequestTypeExternalServiceAssociation(self, external_service) - trans.sa_session.add(rtesa) - trans.sa_session.flush() - - @property - def final_sample_state(self): - # The states mapper for this object orders ascending - return self.states[-1] - - @property - def run_details(self): - if self.run: - # self.run[0] is [RequestTypeRunAssociation] - return self.run[0] - return None - - def get_template_widgets(self, trans, get_contents=True): - # See if we have any associated templates. The get_contents param - # is passed by callers that are inheriting a template - these are - # usually new samples for which we want to include template fields, - # but not necessarily the contents of the inherited template. - rtra = self.run_details - if rtra: - run = rtra.run - template = run.template - if get_contents: - # See if we have any field contents - info = run.info - if info: - return template.get_widgets(trans.user, contents=info.content) - return template.get_widgets(trans.user) - return [] - - -class RequestTypeExternalServiceAssociation(object): - def __init__(self, request_type, external_service): - self.request_type = request_type - self.external_service = external_service - - -class RequestTypePermissions(object): - def __init__(self, action, request_type, role): - self.action = action - self.request_type = request_type - self.role = role - - -class Sample(object, Dictifiable): - # The following form_builder classes are supported by the Sample class. - supported_field_types = [CheckboxField, SelectField, TextField, WorkflowField, WorkflowMappingField, HistoryField] - bulk_operations = Bunch(CHANGE_STATE='Change state', - SELECT_LIBRARY='Select data library and folder') - dict_collection_visible_keys = ['id', 'name'] - - def __init__(self, name=None, desc=None, request=None, form_values=None, bar_code=None, library=None, folder=None, workflow=None, history=None): - self.name = name - self.desc = desc - self.request = request - self.values = form_values - self.bar_code = bar_code - self.library = library - self.folder = folder - self.history = history - self.workflow = workflow - - @property - def state(self): - latest_event = self.latest_event - if latest_event: - return latest_event.state - return None - - @property - def latest_event(self): - if self.events: - return self.events[0] - return None - - @property - def adding_to_library_dataset_files(self): - adding_to_library_datasets = [] - for dataset in self.datasets: - if dataset.status == SampleDataset.transfer_status.ADD_TO_LIBRARY: - adding_to_library_datasets.append(dataset) - return adding_to_library_datasets - - @property - def inprogress_dataset_files(self): - inprogress_datasets = [] - for dataset in self.datasets: - if dataset.status not in [SampleDataset.transfer_status.NOT_STARTED, SampleDataset.transfer_status.COMPLETE]: - inprogress_datasets.append(dataset) - return inprogress_datasets - - @property - def queued_dataset_files(self): - queued_datasets = [] - for dataset in self.datasets: - if dataset.status == SampleDataset.transfer_status.IN_QUEUE: - queued_datasets.append(dataset) - return queued_datasets - - @property - def transfer_error_dataset_files(self): - transfer_error_datasets = [] - for dataset in self.datasets: - if dataset.status == SampleDataset.transfer_status.ERROR: - transfer_error_datasets.append(dataset) - return transfer_error_datasets - - @property - def transferred_dataset_files(self): - transferred_datasets = [] - for dataset in self.datasets: - if dataset.status == SampleDataset.transfer_status.COMPLETE: - transferred_datasets.append(dataset) - return transferred_datasets - - @property - def transferring_dataset_files(self): - transferring_datasets = [] - for dataset in self.datasets: - if dataset.status == SampleDataset.transfer_status.TRANSFERRING: - transferring_datasets.append(dataset) - return transferring_datasets - - @property - def untransferred_dataset_files(self): - untransferred_datasets = [] - for dataset in self.datasets: - if dataset.status != SampleDataset.transfer_status.COMPLETE: - untransferred_datasets.append(dataset) - return untransferred_datasets - - @property - def run_details(self): - # self.runs is a list of SampleRunAssociations ordered descending on update_time. - if self.runs: - # Always use the latest run details template, self.runs[0] is a SampleRunAssociation - return self.runs[0] - # Inherit this sample's RequestType run details, if one exists. - return self.request.type.run_details - - def get_template_widgets(self, trans, get_contents=True): - # Samples have a one-to-many relationship with run details, so we return the - # widgets for last associated template. The get_contents param will populate - # the widget fields with values from the template inherited from the sample's - # RequestType. - template = None - if self.runs: - # The self.runs mapper orders descending on update_time. - run = self.runs[0].run - template = run.template - if template is None: - # There are no run details associated with this sample, so inherit the - # run details template from the sample's RequestType. - rtra = self.request.type.run_details - if rtra: - run = rtra.run - template = run.template - if template: - if get_contents: - # See if we have any field contents - info = run.info - if info: - return template.get_widgets(trans.user, contents=info.content) - return template.get_widgets(trans.user) - return [] - - def populate_external_services(self, param_dict=None, trans=None): - if self.request and self.request.type: - return [service.populate_actions(item=self, param_dict=param_dict, trans=trans) for service in self.request.type.external_services] - - -class SampleState(object): - def __init__(self, name=None, desc=None, request_type=None): - self.name = name - self.desc = desc - self.request_type = request_type - - -class SampleEvent(object): - def __init__(self, sample=None, sample_state=None, comment=''): - self.sample = sample - self.state = sample_state - self.comment = comment - - -class SampleDataset(object): - transfer_status = Bunch(NOT_STARTED='Not started', - IN_QUEUE='In queue', - TRANSFERRING='Transferring dataset', - ADD_TO_LIBRARY='Adding to data library', - COMPLETE='Complete', - ERROR='Error') - - def __init__(self, sample=None, name=None, file_path=None, status=None, error_msg=None, size=None, external_service=None): - self.sample = sample - self.name = name - self.file_path = file_path - self.status = status - self.error_msg = error_msg - self.size = size - self.external_service = external_service - - -class Run(object): - def __init__(self, form_definition, form_values, subindex=None): - self.template = form_definition - self.info = form_values - self.subindex = subindex - - -class RequestTypeRunAssociation(object): - def __init__(self, request_type, run): - self.request_type = request_type - self.run = run - - -class SampleRunAssociation(object): - def __init__(self, sample, run): - self.sample = sample - self.run = run - - class UserAddress(object): def __init__(self, user=None, desc=None, name=None, institution=None, address=None, city=None, state=None, postal_code=None, @@ -5370,7 +4873,6 @@ class LibraryDatasetCollectionAnnotationAssociation(object): # Item rating classes. - class ItemRatingAssociation(object): def __init__(self, id=None, user=None, item=None, rating=0): self.id = id @@ -5418,7 +4920,7 @@ class LibraryDatasetCollectionRatingAssociation(ItemRatingAssociation): self.dataset_collection = dataset_collection -# Data Manager Classes +# Data manager classes. class DataManagerHistoryAssociation(object): def __init__(self, id=None, history=None, user=None): self.id = id @@ -5431,7 +4933,6 @@ class DataManagerJobAssociation(object): self.id = id self.job = job self.data_manager_id = data_manager_id -# end of Data Manager Classes class UserPreference (object): diff --git a/lib/galaxy/model/mapping.py b/lib/galaxy/model/mapping.py index ad4aec98d3b..22c96af3964 100644 --- a/lib/galaxy/model/mapping.py +++ b/lib/galaxy/model/mapping.py @@ -1013,45 +1013,6 @@ model.FormDefinition.table = Table( Column("type", TrimmedString(255), index=True), Column("layout", JSONType())) -model.ExternalService.table = Table( - "external_service", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("name", TrimmedString(255), nullable=False), - Column("description", TEXT), - Column("external_service_type_id", TrimmedString(255), nullable=False), - Column("version", TrimmedString(255)), - Column("form_definition_id", Integer, ForeignKey("form_definition.id"), index=True), - Column("form_values_id", Integer, ForeignKey("form_values.id"), index=True), - Column("deleted", Boolean, index=True, default=False)) - -model.RequestType.table = Table( - "request_type", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("name", TrimmedString(255), nullable=False), - Column("desc", TEXT), - Column("request_form_id", Integer, ForeignKey("form_definition.id"), index=True), - Column("sample_form_id", Integer, ForeignKey("form_definition.id"), index=True), - Column("deleted", Boolean, index=True, default=False)) - -model.RequestTypeExternalServiceAssociation.table = Table( - "request_type_external_service_association", metadata, - Column("id", Integer, primary_key=True), - Column("request_type_id", Integer, ForeignKey("request_type.id"), index=True), - Column("external_service_id", Integer, ForeignKey("external_service.id"), index=True)) - -model.RequestTypePermissions.table = Table( - "request_type_permissions", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("action", TEXT), - Column("request_type_id", Integer, ForeignKey("request_type.id"), nullable=True, index=True), - Column("role_id", Integer, ForeignKey("role.id"), index=True)) - model.FormValues.table = Table( "form_values", metadata, Column("id", Integer, primary_key=True), @@ -1060,97 +1021,6 @@ model.FormValues.table = Table( Column("form_definition_id", Integer, ForeignKey("form_definition.id"), index=True), Column("content", JSONType())) -model.Request.table = Table( - "request", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("name", TrimmedString(255), nullable=False), - Column("desc", TEXT), - Column("notification", JSONType()), - Column("form_values_id", Integer, ForeignKey("form_values.id"), index=True), - Column("request_type_id", Integer, ForeignKey("request_type.id"), index=True), - Column("user_id", Integer, ForeignKey("galaxy_user.id"), index=True), - Column("deleted", Boolean, index=True, default=False)) - -model.RequestEvent.table = Table( - "request_event", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("request_id", Integer, ForeignKey("request.id"), index=True), - Column("state", TrimmedString(255), index=True), - Column("comment", TEXT)) - -model.Sample.table = Table( - "sample", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("name", TrimmedString(255), nullable=False), - Column("desc", TEXT), - Column("form_values_id", Integer, ForeignKey("form_values.id"), index=True), - Column("request_id", Integer, ForeignKey("request.id"), index=True), - Column("bar_code", TrimmedString(255), index=True), - Column("library_id", Integer, ForeignKey("library.id"), index=True), - Column("folder_id", Integer, ForeignKey("library_folder.id"), index=True), - Column("deleted", Boolean, index=True, default=False), - Column("workflow", JSONType, nullable=True), - Column("history_id", Integer, ForeignKey("history.id"), nullable=True)) - -model.SampleState.table = Table( - "sample_state", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("name", TrimmedString(255), nullable=False), - Column("desc", TEXT), - Column("request_type_id", Integer, ForeignKey("request_type.id"), index=True)) - -model.SampleEvent.table = Table( - "sample_event", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("sample_id", Integer, ForeignKey("sample.id"), index=True), - Column("sample_state_id", Integer, ForeignKey("sample_state.id"), index=True), - Column("comment", TEXT)) - -model.SampleDataset.table = Table( - "sample_dataset", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("sample_id", Integer, ForeignKey("sample.id"), index=True), - Column("name", TrimmedString(255), nullable=False), - Column("file_path", TEXT), - Column("status", TrimmedString(255), nullable=False), - Column("error_msg", TEXT), - Column("size", TrimmedString(255)), - Column("external_service_id", Integer, ForeignKey("external_service.id"), index=True)) - -model.Run.table = Table( - "run", metadata, - Column("id", Integer, primary_key=True), - Column("create_time", DateTime, default=now), - Column("update_time", DateTime, default=now, onupdate=now), - Column("form_definition_id", Integer, ForeignKey("form_definition.id"), index=True), - Column("form_values_id", Integer, ForeignKey("form_values.id"), index=True), - Column("deleted", Boolean, index=True, default=False), - Column("subindex", TrimmedString(255), index=True)) - -model.RequestTypeRunAssociation.table = Table( - "request_type_run_association", metadata, - Column("id", Integer, primary_key=True), - Column("request_type_id", Integer, ForeignKey("request_type.id"), index=True, nullable=False), - Column("run_id", Integer, ForeignKey("run.id"), index=True, nullable=False)) - -model.SampleRunAssociation.table = Table( - "sample_run_association", metadata, - Column("id", Integer, primary_key=True), - Column("sample_id", Integer, ForeignKey("sample.id"), index=True, nullable=False), - Column("run_id", Integer, ForeignKey("run.id"), index=True, nullable=False)) - model.Page.table = Table( "page", metadata, Column("id", Integer, primary_key=True), @@ -1495,80 +1365,11 @@ def simple_mapping(model, **kwds): mapper(model, model.table, properties=kwds) -mapper(model.Sample, model.Sample.table, properties=dict( - events=relation(model.SampleEvent, - backref="sample", - order_by=desc(model.SampleEvent.table.c.update_time)), - datasets=relation(model.SampleDataset, - backref="sample", - order_by=desc(model.SampleDataset.table.c.update_time)), - values=relation(model.FormValues, - primaryjoin=(model.Sample.table.c.form_values_id == model.FormValues.table.c.id)), - request=relation(model.Request, - primaryjoin=(model.Sample.table.c.request_id == model.Request.table.c.id)), - folder=relation(model.LibraryFolder, - primaryjoin=(model.Sample.table.c.folder_id == model.LibraryFolder.table.c.id)), - library=relation(model.Library, - primaryjoin=(model.Sample.table.c.library_id == model.Library.table.c.id)), - history=relation(model.History, - primaryjoin=(model.Sample.table.c.history_id == model.History.table.c.id)), -)) - mapper(model.FormValues, model.FormValues.table, properties=dict( form_definition=relation(model.FormDefinition, primaryjoin=(model.FormValues.table.c.form_definition_id == model.FormDefinition.table.c.id)) )) -mapper(model.Request, model.Request.table, properties=dict( - values=relation(model.FormValues, - primaryjoin=(model.Request.table.c.form_values_id == model.FormValues.table.c.id)), - type=relation(model.RequestType, - primaryjoin=(model.Request.table.c.request_type_id == model.RequestType.table.c.id)), - user=relation(model.User, - primaryjoin=(model.Request.table.c.user_id == model.User.table.c.id), - backref="requests"), - samples=relation(model.Sample, - primaryjoin=(model.Request.table.c.id == model.Sample.table.c.request_id), - order_by=asc(model.Sample.table.c.id)), - events=relation(model.RequestEvent, - backref="request", - order_by=desc(model.RequestEvent.table.c.update_time)) -)) - -mapper(model.RequestEvent, model.RequestEvent.table, properties=None) - -mapper(model.ExternalService, model.ExternalService.table, properties=dict( - form_definition=relation(model.FormDefinition, - primaryjoin=(model.ExternalService.table.c.form_definition_id == model.FormDefinition.table.c.id)), - form_values=relation(model.FormValues, - primaryjoin=(model.ExternalService.table.c.form_values_id == model.FormValues.table.c.id)) -)) - -mapper(model.RequestType, model.RequestType.table, properties=dict( - states=relation(model.SampleState, - backref="request_type", - primaryjoin=(model.RequestType.table.c.id == model.SampleState.table.c.request_type_id), - order_by=asc(model.SampleState.table.c.update_time)), - request_form=relation(model.FormDefinition, - primaryjoin=(model.RequestType.table.c.request_form_id == model.FormDefinition.table.c.id)), - sample_form=relation(model.FormDefinition, - primaryjoin=(model.RequestType.table.c.sample_form_id == model.FormDefinition.table.c.id)), -)) - -mapper(model.RequestTypeExternalServiceAssociation, model.RequestTypeExternalServiceAssociation.table, properties=dict( - request_type=relation(model.RequestType, - primaryjoin=((model.RequestTypeExternalServiceAssociation.table.c.request_type_id == model.RequestType.table.c.id)), - backref="external_service_associations"), - external_service=relation(model.ExternalService, - primaryjoin=(model.RequestTypeExternalServiceAssociation.table.c.external_service_id == model.ExternalService.table.c.id)) -)) - - -mapper(model.RequestTypePermissions, model.RequestTypePermissions.table, properties=dict( - request_type=relation(model.RequestType, backref="actions"), - role=relation(model.Role, backref="request_type_actions") -)) - mapper(model.FormDefinition, model.FormDefinition.table, properties=dict( current=relation(model.FormDefinitionCurrent, primaryjoin=(model.FormDefinition.table.c.form_definition_current_id == model.FormDefinitionCurrent.table.c.id)) @@ -1584,36 +1385,6 @@ mapper(model.FormDefinitionCurrent, model.FormDefinitionCurrent.table, propertie primaryjoin=(model.FormDefinitionCurrent.table.c.latest_form_id == model.FormDefinition.table.c.id)) )) -mapper(model.SampleEvent, model.SampleEvent.table, properties=dict( - state=relation(model.SampleState, - primaryjoin=(model.SampleEvent.table.c.sample_state_id == model.SampleState.table.c.id)), -)) - -mapper(model.SampleState, model.SampleState.table, properties=None) - -mapper(model.SampleDataset, model.SampleDataset.table, properties=dict( - external_service=relation(model.ExternalService, - primaryjoin=(model.SampleDataset.table.c.external_service_id == model.ExternalService.table.c.id)) -)) - - -mapper(model.SampleRunAssociation, model.SampleRunAssociation.table, properties=dict( - sample=relation(model.Sample, backref="runs", order_by=desc(model.Run.table.c.update_time)), - run=relation(model.Run, backref="samples", order_by=asc(model.Sample.table.c.id)) -)) - -mapper(model.RequestTypeRunAssociation, model.RequestTypeRunAssociation.table, properties=dict( - request_type=relation(model.RequestType, backref="run"), - run=relation(model.Run, backref="request_type") -)) - -mapper(model.Run, model.Run.table, properties=dict( - template=relation(model.FormDefinition, - primaryjoin=(model.Run.table.c.form_definition_id == model.FormDefinition.table.c.id)), - info=relation(model.FormValues, - primaryjoin=(model.Run.table.c.form_values_id == model.FormValues.table.c.id)) -)) - mapper(model.UserAddress, model.UserAddress.table, properties=dict( user=relation(model.User, primaryjoin=(model.UserAddress.table.c.user_id == model.User.table.c.id), diff --git a/lib/galaxy/sample_tracking/__init__.py b/lib/galaxy/sample_tracking/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/lib/galaxy/sample_tracking/data_transfer.py b/lib/galaxy/sample_tracking/data_transfer.py deleted file mode 100644 index f7740722d11..00000000000 --- a/lib/galaxy/sample_tracking/data_transfer.py +++ /dev/null @@ -1,58 +0,0 @@ -class DataTransferFactory(object): - type = None - - def parse(self): - pass - - -class ScpDataTransferFactory(DataTransferFactory): - type = 'scp' - - def __init__(self): - pass - - def parse(self, config_file, elem): - self.config = {} - # TODO: The 'automatic_transfer' setting is for future use. If set to True, we will need to - # ensure the sample has an associated destination data library before it moves to a certain state - # ( e.g., Run started ). - self.config['automatic_transfer'] = elem.get('automatic_transfer') - self.config['host'] = elem.get('host') - self.config['user_name'] = elem.get('user_name') - self.config['password'] = elem.get('password') - self.config['data_location'] = elem.get('data_location') - # 'rename_dataset' is optional and it may not be defined in all external types - # It is only used is AB SOLiD external service type for now - rename_dataset = elem.get('rename_dataset', None) - if rename_dataset: - self.config['rename_dataset'] = rename_dataset - # Validate - for name, value in self.config.items(): - assert value, "'%s' attribute missing in 'data_transfer' element of type 'scp' in external_service_type xml config file: '%s'." % (name, config_file) - - -class HttpDataTransferFactory(DataTransferFactory): - type = 'http' - - def __init__(self): - pass - - def parse(self, config_file, elem): - self.config = {} - self.config['automatic_transfer'] = elem.get('automatic_transfer') - # Validate - for name, value in self.config.items(): - assert value, "'%s' attribute missing in 'data_transfer' element of type 'http' in external_service_type xml config file: '%s'." % (name, config_file) - - -class FtpDataTransferFactory(DataTransferFactory): - type = 'ftp' - - def __init__(self): - pass - - def parse(self, elem): - pass - - -data_transfer_factories = dict([(data_transfer.type, data_transfer()) for data_transfer in [ScpDataTransferFactory, HttpDataTransferFactory, FtpDataTransferFactory]]) diff --git a/lib/galaxy/sample_tracking/external_service_types.py b/lib/galaxy/sample_tracking/external_service_types.py deleted file mode 100644 index 1bd4e50be42..00000000000 --- a/lib/galaxy/sample_tracking/external_service_types.py +++ /dev/null @@ -1,127 +0,0 @@ -import logging -import os - -from galaxy import ( - model, - util -) -from galaxy.external_services.service import ExternalServiceActionsGroup -from galaxy.forms.forms import form_factory -from galaxy.sample_tracking.data_transfer import data_transfer_factories -from galaxy.util.odict import odict - -log = logging.getLogger(__name__) - - -class ExternalServiceTypeNotFoundException(Exception): - pass - - -class ExternalServiceTypesCollection(object): - - def __init__(self, config_filename, root_dir, app): - self.all_external_service_types = odict() - self.root_dir = root_dir - self.app = app - try: - self.load_all(config_filename) - except Exception: - log.exception("ExternalServiceTypesCollection error reading %s", config_filename) - - def load_all(self, config_filename): - self.visible_external_service_types = [] - tree = util.parse_xml(config_filename) - root = tree.getroot() - for elem in root: - try: - if elem.tag == 'external_service_type': - file_path = elem.get("file") - visible = util.string_as_bool(elem.get("visible")) - external_service_type = self.load_external_service_type(os.path.join(self.root_dir, file_path), visible) - self.all_external_service_types[external_service_type.id] = external_service_type - log.debug("Loaded external_service_type: %s %s" % (external_service_type.name, external_service_type.config_version)) - if visible: - self.visible_external_service_types.append(external_service_type.id) - except Exception: - log.exception("error reading external_service_type from path: %s", file_path) - - def load_external_service_type(self, config_file, visible=True): - # Parse XML configuration file and get the root element - tree = util.parse_xml(config_file) - root = tree.getroot() - return ExternalServiceType(config_file, root, visible) - - def reload(self, external_service_type_id): - """ - Attempt to reload the external_service_type identified by 'external_service_type_id', if successful - replace the old external_service_type. - """ - if external_service_type_id not in self.all_external_service_types.keys(): - raise ExternalServiceTypeNotFoundException("No external_service_type with id %s" % external_service_type_id) - old_external_service_type = self.all_external_service_types[external_service_type_id] - new_external_service_type = self.load_external_service_type(old_external_service_type.config_file) - self.all_external_service_types[external_service_type_id] = new_external_service_type - log.debug("Reloaded external_service_type %s" % (external_service_type_id)) - return new_external_service_type - - -class ExternalServiceType(object): - def __init__(self, external_service_type_xml_config, root, visible=True): - self.config_file = external_service_type_xml_config - self.parse(root) - self.visible = visible - root.clear() - - def parse(self, root): - # Get the name - self.name = root.get("name") - if not self.name: - raise Exception("Missing external_service_type 'name'") - # Get the UNIQUE id for the tool - self.id = root.get("id") - if not self.id: - raise Exception("Missing external_service_type 'id'") - self.config_version = root.get("version") - if not self.config_version: - self.config_version = '1.0.0' - self.description = util.xml_text(root, "description") - self.version = util.xml_text(root.find("version")) - # parse the form - self.form_definition = form_factory.from_elem(root.find('form')) - self.parse_data_transfer_settings(root) - self.parse_run_details(root) - # external services actions - self.actions = ExternalServiceActionsGroup.from_elem(root.find('actions'), parent=self) - - def parse_data_transfer_settings(self, root): - self.data_transfer = {} - data_transfer_settings_elem = root.find('data_transfer_settings') - # Currently only data transfer using scp or http is supported. - for data_transfer_elem in data_transfer_settings_elem.findall("data_transfer"): - if data_transfer_elem.get('protocol') == model.ExternalService.data_transfer_protocol.SCP: - scp_data_transfer = data_transfer_factories[model.ExternalService.data_transfer_protocol.SCP] - scp_data_transfer.parse(self.config_file, data_transfer_elem) - self.data_transfer[model.ExternalService.data_transfer_protocol.SCP] = scp_data_transfer - if data_transfer_elem.get('protocol') == model.ExternalService.data_transfer_protocol.HTTP: - http_data_transfer = data_transfer_factories[model.ExternalService.data_transfer_protocol.HTTP] - http_data_transfer.parse(self.config_file, data_transfer_elem) - self.data_transfer[model.ExternalService.data_transfer_protocol.HTTP] = http_data_transfer - - def parse_run_details(self, root): - self.run_details = {} - run_details_elem = root.find('run_details') - if run_details_elem is not None: - results_elem = run_details_elem.find('results') - if results_elem is not None: - # Get the list of resulting datatypes - # TODO: the 'results_urls' attribute is only useful if the transfer protocol is http(s), so check if that is the case. - self.run_details['results'], self.run_details['results_urls'] = self.parse_run_details_results(results_elem) - - def parse_run_details_results(self, root): - datatypes_dict = {} - urls_dict = {} - for datatype_elem in root.findall("dataset"): - name = datatype_elem.get('name') - datatypes_dict[name] = datatype_elem.get('datatype') - urls_dict[name] = datatype_elem.get('url', None) - return datatypes_dict, urls_dict diff --git a/lib/galaxy/sample_tracking/request_types.py b/lib/galaxy/sample_tracking/request_types.py deleted file mode 100644 index 14a54400128..00000000000 --- a/lib/galaxy/sample_tracking/request_types.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -RequestType -""" -from galaxy.model import RequestType -from .sample import sample_state_factory - -RENAME_DATASET_OPTIONS = dict([(f_type.lower(), f_descript) for f_type, f_descript in RequestType.rename_dataset_options.items()]) - - -class RequestTypeFactory(object): - def __init__(self, sample_state_factory, rename_dataset_options): - self.sample_state_factory = sample_state_factory - self.rename_dataset_options = rename_dataset_options - - def new(self, name, request_form, sample_form, external_service, description=None, sample_states=None): - """Return new RequestType.""" - assert name, 'RequestType requires a name' - return RequestType(name=name, desc=description, request_form=request_form, sample_form=sample_form, external_service=external_service) - - def from_elem(self, elem, request_form, sample_form, external_service): - """Return RequestType created from an xml string.""" - name = elem.get('name', '') - description = elem.get('description', '') - rval = self.new(name, request_form, sample_form, external_service=external_service, description=description) - # load states - sample_states_elem = elem.find('sample_states') - if sample_states_elem: - for sample_state_elem in sample_states_elem.findall('state'): - self.sample_state_factory.from_elem(rval, sample_state_elem) # should this be the return value?? - return rval - - -request_type_factory = RequestTypeFactory(sample_state_factory, RENAME_DATASET_OPTIONS) diff --git a/lib/galaxy/sample_tracking/sample.py b/lib/galaxy/sample_tracking/sample.py deleted file mode 100644 index 1b5171eb0c1..00000000000 --- a/lib/galaxy/sample_tracking/sample.py +++ /dev/null @@ -1,26 +0,0 @@ -""" -Sample -""" -from galaxy.model import SampleState - - -class SampleStateFactory(object): - def new(self, request_type, name, description=None): - """ - Return new SampleState. - """ - assert name, 'SampleState requires a name' - if description is None: - description = '' - return SampleState(name=name, desc=description, request_type=request_type) - - def from_elem(self, request_type, elem): - """ - Return SampleState created from an xml string. - """ - name = elem.get('name', None) - description = elem.get('description', None) - return self.new(request_type, name, description=description) - - -sample_state_factory = SampleStateFactory() diff --git a/lib/galaxy/security/__init__.py b/lib/galaxy/security/__init__.py index 97b4aefb1e4..be1a576a112 100644 --- a/lib/galaxy/security/__init__.py +++ b/lib/galaxy/security/__init__.py @@ -30,9 +30,7 @@ class RBACAgent: LIBRARY_ACCESS=Action("access library", "Restrict access to this library to only users having associated role", "restrict"), LIBRARY_ADD=Action("add library item", "Users having associated role can add library items to this library item", "grant"), LIBRARY_MODIFY=Action("modify library item", "Users having associated role can modify this library item", "grant"), - LIBRARY_MANAGE=Action("manage library permissions", "Users having associated role can manage roles associated with permissions on this library item", "grant"), - # Request type permissions - REQUEST_TYPE_ACCESS=Action("access request_type", "Restrict access to this request type to only users having associated role", "restrict") + LIBRARY_MANAGE=Action("manage library permissions", "Users having associated role can manage roles associated with permissions on this library item", "grant") ) def get_action(self, name, default=None): @@ -79,9 +77,6 @@ class RBACAgent: def get_private_user_role(self, user): raise Exception("Unimplemented Method") - def get_accessible_request_types(self, trans, user): - raise Exception("Unimplemented Method") - def user_set_default_permissions(self, user, permissions={}, history=False, dataset=False): raise Exception("Unimplemented Method") @@ -940,27 +935,6 @@ class GalaxyRBACAgent(RBACAgent): permissions[action] = [item_permission.role] return permissions - def get_accessible_request_types(self, trans, user): - """Return all RequestTypes that the received user has permission to access.""" - accessible_request_types = [] - current_user_role_ids = [role.id for role in user.all_roles()] - request_type_access_action = self.permitted_actions.REQUEST_TYPE_ACCESS.action - restricted_request_type_ids = [rtp.request_type_id for rtp in trans.sa_session.query(trans.model.RequestTypePermissions) - .filter(trans.model.RequestTypePermissions.table.c.action == request_type_access_action).distinct()] - accessible_restricted_request_type_ids = [rtp.request_type_id for rtp in trans.sa_session.query(trans.model.RequestTypePermissions) - .filter(and_( - trans.model.RequestTypePermissions.table.c.action == request_type_access_action, - trans.model.RequestTypePermissions.table.c.role_id.in_(current_user_role_ids)))] - # Filter to get libraries accessible by the current user. Get both - # public libraries and restricted libraries accessible by the current user. - for request_type in trans.sa_session.query(trans.model.RequestType) \ - .filter(and_(trans.model.RequestType.table.c.deleted == false(), - (or_(not_(trans.model.RequestType.table.c.id.in_(restricted_request_type_ids)), - trans.model.RequestType.table.c.id.in_(accessible_restricted_request_type_ids))))) \ - .order_by(trans.app.model.RequestType.name): - accessible_request_types.append(request_type) - return accessible_request_types - def copy_dataset_permissions(self, src, dst): if not isinstance(src, self.model.Dataset): src = src.dataset diff --git a/lib/galaxy/web/base/controller.py b/lib/galaxy/web/base/controller.py index 1b610532438..9cc3a9564a7 100644 --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -10,10 +10,7 @@ from paste.httpexceptions import ( HTTPNotImplemented, HTTPRequestRangeNotSatisfiable ) -from six import ( - string_types, - text_type -) +from six import string_types from sqlalchemy import true from galaxy import ( @@ -48,15 +45,8 @@ from galaxy.web import ( ) from galaxy.web.form_builder import ( AddressField, - build_select_field, CheckboxField, - HistoryField, - PasswordField, - SelectField, - TextArea, - TextField, - WorkflowField, - WorkflowMappingField + PasswordField ) from galaxy.workflow.modules import WorkflowModuleInjector @@ -261,7 +251,7 @@ class JSAppLauncher(BaseUIController): #: window-scoped js function to call to start the app (will be passed options, bootstrapped) DEFAULT_ENTRY_FN = "app" #: keys used when serializing current user for bootstrapped data - USER_BOOTSTRAP_KEYS = ('id', 'email', 'username', 'is_admin', 'tags_used', 'requests', + USER_BOOTSTRAP_KEYS = ('id', 'email', 'username', 'is_admin', 'tags_used', 'total_disk_usage', 'nice_total_disk_usage', 'quota_percent', 'preferences') def __init__(self, app): @@ -1299,580 +1289,6 @@ class UsesFormDefinitionsMixin: else: return [fdc.latest_form for fdc in fdc_list if fdc.latest_form.type == form_type] - def get_all_forms_by_type(self, trans, cntrller, form_type): - forms = self.get_all_forms(trans, - filter=dict(deleted=False), - form_type=form_type) - if not forms: - message = "There are no forms on which to base the template, so create a form and then add the template." - return trans.response.send_redirect(web.url_for(controller='forms', - action='create_form_definition', - cntrller=cntrller, - message=message, - status='done', - form_type=form_type)) - return forms - - @web.expose - def add_template(self, trans, cntrller, item_type, form_type, **kwd): - params = util.Params(kwd) - form_id = params.get('form_id', 'none') - message = util.restore_text(params.get('message', '')) - action = '' - status = params.get('status', 'done') - forms = self.get_all_forms_by_type(trans, cntrller, form_type) - # form_type must be one of: RUN_DETAILS_TEMPLATE, LIBRARY_INFO_TEMPLATE - in_library = form_type == trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE - in_sample_tracking = form_type == trans.model.FormDefinition.types.RUN_DETAILS_TEMPLATE - if in_library: - show_deleted = util.string_as_bool(params.get('show_deleted', False)) - use_panels = util.string_as_bool(params.get('use_panels', False)) - library_id = params.get('library_id', None) - folder_id = params.get('folder_id', None) - ldda_id = params.get('ldda_id', None) - is_admin = trans.user_is_admin() and cntrller in ['library_admin', 'requests_admin'] - current_user_roles = trans.get_current_user_roles() - elif in_sample_tracking: - request_type_id = params.get('request_type_id', None) - sample_id = params.get('sample_id', None) - try: - if in_sample_tracking: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - request_type_id=request_type_id, - sample_id=sample_id) - elif in_library: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - is_admin=is_admin) - if not item: - message = "Invalid %s id ( %s ) specified." % (item_desc, str(id)) - if in_sample_tracking: - return trans.response.send_redirect(web.url_for(controller='request_type', - action='browse_request_types', - id=request_type_id, - message=util.sanitize_text(message), - status='error')) - if in_library: - return trans.response.send_redirect(web.url_for(controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - show_deleted=show_deleted, - message=util.sanitize_text(message), - status='error')) - except ValueError: - # At this point, the client has already redirected, so this is just here to prevent the unnecessary traceback - return None - if in_library: - # Make sure the user is authorized to do what they are trying to do. - authorized = True - if not (is_admin or trans.app.security_agent.can_modify_library_item(current_user_roles, item)): - authorized = False - unauthorized = 'modify' - if not (is_admin or trans.app.security_agent.can_access_library_item(current_user_roles, item, trans.user)): - authorized = False - unauthorized = 'access' - if not authorized: - message = "You are not authorized to %s %s '%s'." % (unauthorized, item_desc, item.name) - return trans.response.send_redirect(web.url_for(controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - show_deleted=show_deleted, - message=util.sanitize_text(message), - status='error')) - # If the inheritable checkbox is checked, the param will be in the request - inheritable = CheckboxField.is_checked(params.get('inheritable', '')) - if params.get('add_template_button', False): - if form_id not in [None, 'None', 'none']: - form = trans.sa_session.query(trans.app.model.FormDefinition).get(trans.security.decode_id(form_id)) - form_values = trans.app.model.FormValues(form, {}) - trans.sa_session.add(form_values) - trans.sa_session.flush() - if item_type == 'library': - assoc = trans.model.LibraryInfoAssociation(item, form, form_values, inheritable=inheritable) - elif item_type == 'folder': - assoc = trans.model.LibraryFolderInfoAssociation(item, form, form_values, inheritable=inheritable) - elif item_type == 'ldda': - assoc = trans.model.LibraryDatasetDatasetInfoAssociation(item, form, form_values) - elif item_type in ['request_type', 'sample']: - run = trans.model.Run(form, form_values) - trans.sa_session.add(run) - trans.sa_session.flush() - if item_type == 'request_type': - # Delete current RequestTypeRunAssociation, if one exists. - rtra = item.run_details - if rtra: - trans.sa_session.delete(rtra) - trans.sa_session.flush() - # Add the new RequestTypeRunAssociation. Templates associated with a RequestType - # are automatically inherited to the samples. - assoc = trans.model.RequestTypeRunAssociation(item, run) - elif item_type == 'sample': - assoc = trans.model.SampleRunAssociation(item, run) - trans.sa_session.add(assoc) - trans.sa_session.flush() - message = 'A template based on the form "%s" has been added to this %s.' % (form.name, item_desc) - new_kwd = dict(action=action, - cntrller=cntrller, - message=util.sanitize_text(message), - status='done') - if in_sample_tracking: - new_kwd.update(dict(controller='request_type', - request_type_id=request_type_id, - sample_id=sample_id, - id=id)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - elif in_library: - new_kwd.update(dict(controller='library_common', - use_panels=use_panels, - library_id=library_id, - folder_id=folder_id, - id=id, - show_deleted=show_deleted)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - else: - message = "Select a form on which to base the template." - status = "error" - form_id_select_field = self.build_form_id_select_field(trans, forms, selected_value=kwd.get('form_id', 'none')) - try: - decoded_form_id = trans.security.decode_id(form_id) - except Exception: - decoded_form_id = None - if decoded_form_id: - for form in forms: - if decoded_form_id == form.id: - widgets = form.get_widgets(trans.user) - break - else: - widgets = [] - new_kwd = dict(cntrller=cntrller, - item_name=item.name, - item_desc=item_desc, - item_type=item_type, - form_type=form_type, - widgets=widgets, - form_id_select_field=form_id_select_field, - message=message, - status=status) - if in_sample_tracking: - new_kwd.update(dict(request_type_id=request_type_id, - sample_id=sample_id)) - elif in_library: - new_kwd.update(dict(use_panels=use_panels, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - inheritable_checked=inheritable, - show_deleted=show_deleted)) - return trans.fill_template('/common/select_template.mako', - **new_kwd) - - @web.expose - def edit_template(self, trans, cntrller, item_type, form_type, **kwd): - # Edit the template itself, keeping existing field contents, if any. - params = util.Params(kwd) - message = util.restore_text(params.get('message', '')) - edited = util.string_as_bool(params.get('edited', False)) - action = '' - # form_type must be one of: RUN_DETAILS_TEMPLATE, LIBRARY_INFO_TEMPLATE - in_library = form_type == trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE - in_sample_tracking = form_type == trans.model.FormDefinition.types.RUN_DETAILS_TEMPLATE - if in_library: - show_deleted = util.string_as_bool(params.get('show_deleted', False)) - use_panels = util.string_as_bool(params.get('use_panels', False)) - library_id = params.get('library_id', None) - folder_id = params.get('folder_id', None) - ldda_id = params.get('ldda_id', None) - is_admin = trans.user_is_admin() and cntrller in ['library_admin', 'requests_admin'] - current_user_roles = trans.get_current_user_roles() - elif in_sample_tracking: - request_type_id = params.get('request_type_id', None) - sample_id = params.get('sample_id', None) - try: - if in_library: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - is_admin=is_admin) - elif in_sample_tracking: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - request_type_id=request_type_id, - sample_id=sample_id) - except ValueError: - return None - if in_library: - if not (is_admin or trans.app.security_agent.can_modify_library_item(current_user_roles, item)): - message = "You are not authorized to modify %s '%s'." % (item_desc, item.name) - return trans.response.send_redirect(web.url_for(controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - show_deleted=show_deleted, - message=util.sanitize_text(message), - status='error')) - # An info_association must exist at this point - if in_library: - info_association, inherited = item.get_info_association(restrict=True) - elif in_sample_tracking: - # Here run_details is a RequestTypeRunAssociation - rtra = item.run_details - info_association = rtra.run - template = info_association.template - if edited: - # The form on which the template is based has been edited, so we need to update the - # info_association with the current form - fdc = trans.sa_session.query(trans.app.model.FormDefinitionCurrent).get(template.form_definition_current_id) - info_association.template = fdc.latest_form - trans.sa_session.add(info_association) - trans.sa_session.flush() - message = "The template for this %s has been updated with your changes." % item_desc - new_kwd = dict(action=action, - cntrller=cntrller, - id=id, - message=util.sanitize_text(message), - status='done') - if in_library: - new_kwd.update(dict(controller='library_common', - use_panels=use_panels, - library_id=library_id, - folder_id=folder_id, - show_deleted=show_deleted)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - elif in_sample_tracking: - new_kwd.update(dict(controller='request_type', - request_type_id=request_type_id, - sample_id=sample_id)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - # "template" is a FormDefinition, so since we're changing it, we need to use the latest version of it. - vars = dict(id=trans.security.encode_id(template.form_definition_current_id), - response_redirect=web.url_for(controller='request_type', - action='edit_template', - cntrller=cntrller, - item_type=item_type, - form_type=form_type, - edited=True, - **kwd)) - return trans.response.send_redirect(web.url_for(controller='forms', action='edit_form_definition', **vars)) - - @web.expose - def edit_template_info(self, trans, cntrller, item_type, form_type, **kwd): - # Edit the contents of the template fields without altering the template itself. - params = util.Params(kwd) - # form_type must be one of: RUN_DETAILS_TEMPLATE, LIBRARY_INFO_TEMPLATE - in_library = form_type == trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE - in_sample_tracking = form_type == trans.model.FormDefinition.types.RUN_DETAILS_TEMPLATE - if in_library: - library_id = params.get('library_id', None) - folder_id = params.get('folder_id', None) - ldda_id = params.get('ldda_id', None) - show_deleted = util.string_as_bool(params.get('show_deleted', False)) - use_panels = util.string_as_bool(params.get('use_panels', False)) - is_admin = (trans.user_is_admin() and cntrller == 'library_admin') - current_user_roles = trans.get_current_user_roles() - elif in_sample_tracking: - request_type_id = params.get('request_type_id', None) - sample_id = params.get('sample_id', None) - sample = trans.sa_session.query(trans.model.Sample).get(trans.security.decode_id(sample_id)) - message = util.restore_text(params.get('message', '')) - try: - if in_library: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - is_admin=is_admin) - elif in_sample_tracking: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - request_type_id=request_type_id, - sample_id=sample_id) - except ValueError: - if cntrller == 'api': - trans.response.status = 400 - return None - return None - if in_library: - if not (is_admin or trans.app.security_agent.can_modify_library_item(current_user_roles, item)): - message = "You are not authorized to modify %s '%s'." % (item_desc, item.name) - if cntrller == 'api': - trans.response.status = 400 - return message - return trans.response.send_redirect(web.url_for(controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - show_deleted=show_deleted, - message=util.sanitize_text(message), - status='error')) - # We need the type of each template field widget - widgets = item.get_template_widgets(trans) - # The list of widgets may include an AddressField which we need to save if it is new - for widget_dict in widgets: - widget = widget_dict['widget'] - if isinstance(widget, AddressField): - value = util.restore_text(params.get(widget.name, '')) - if value == 'new': - if params.get('edit_info_button', False): - if self.field_param_values_ok(widget.name, 'AddressField', **kwd): - # Save the new address - address = trans.app.model.UserAddress(user=trans.user) - self.save_widget_field(trans, address, widget.name, **kwd) - widget.value = str(address.id) - else: - message = 'Required fields are missing contents.' - if cntrller == 'api': - trans.response.status = 400 - return message - new_kwd = dict(action=action, - id=id, - message=util.sanitize_text(message), - status='error') - if in_library: - new_kwd.update(dict(controller='library_common', - cntrller=cntrller, - use_panels=use_panels, - library_id=library_id, - folder_id=folder_id, - show_deleted=show_deleted)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - if in_sample_tracking: - new_kwd.update(dict(controller='request_type', - request_type_id=request_type_id, - sample_id=sample_id)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - else: - # Form was submitted via refresh_on_change - widget.value = 'new' - elif value == text_type('none'): - widget.value = '' - else: - widget.value = value - elif isinstance(widget, CheckboxField): - # We need to check the value from kwd since util.Params would have munged the list if - # the checkbox is checked. - value = kwd.get(widget.name, '') - if CheckboxField.is_checked(value): - widget.value = 'true' - else: - widget.value = util.restore_text(params.get(widget.name, '')) - # Save updated template field contents - field_contents = self.clean_field_contents(widgets, **kwd) - if field_contents: - if in_library: - # In in a library, since information templates are inherited, the template fields can be displayed - # on the information page for a folder or ldda when it has no info_association object. If the user - # has added field contents on an inherited template via a parent's info_association, we'll need to - # create a new form_values and info_association for the current object. The value for the returned - # inherited variable is not applicable at this level. - info_association, inherited = item.get_info_association(restrict=True) - elif in_sample_tracking: - assoc = item.run_details - if item_type == 'request_type' and assoc: - # If we're dealing with a RequestType, assoc will be a ReuqestTypeRunAssociation. - info_association = assoc.run - elif item_type == 'sample' and assoc: - # If we're dealing with a Sample, assoc will be a SampleRunAssociation if the - # Sample has one. If the Sample does not have a SampleRunAssociation, assoc will - # be the Sample's RequestType RequestTypeRunAssociation, in which case we need to - # create a SampleRunAssociation using the inherited template from the RequestType. - if isinstance(assoc, trans.model.RequestTypeRunAssociation): - form_definition = assoc.run.template - new_form_values = trans.model.FormValues(form_definition, {}) - trans.sa_session.add(new_form_values) - trans.sa_session.flush() - new_run = trans.model.Run(form_definition, new_form_values) - trans.sa_session.add(new_run) - trans.sa_session.flush() - sra = trans.model.SampleRunAssociation(item, new_run) - trans.sa_session.add(sra) - trans.sa_session.flush() - info_association = sra.run - else: - info_association = assoc.run - else: - info_association = None - if info_association: - template = info_association.template - info = info_association.info - form_values = trans.sa_session.query(trans.app.model.FormValues).get(info.id) - # Update existing content only if it has changed - flush_required = False - for field_contents_key, field_contents_value in field_contents.items(): - if field_contents_key in form_values.content: - if form_values.content[field_contents_key] != field_contents_value: - flush_required = True - form_values.content[field_contents_key] = field_contents_value - else: - flush_required = True - form_values.content[field_contents_key] = field_contents_value - if flush_required: - trans.sa_session.add(form_values) - trans.sa_session.flush() - else: - if in_library: - # Inherit the next available info_association so we can get the template - info_association, inherited = item.get_info_association() - template = info_association.template - # Create a new FormValues object - form_values = trans.app.model.FormValues(template, field_contents) - trans.sa_session.add(form_values) - trans.sa_session.flush() - # Create a new info_association between the current library item and form_values - if item_type == 'folder': - # A LibraryFolder is a special case because if it inherited the template from its parent, - # we want to set inheritable to True for its info_association. This allows for the default - # inheritance to be False for each level in the Library hierarchy unless we're creating a new - # level in the hierarchy, in which case we'll inherit the "inheritable" setting from the parent - # level. - info_association = trans.app.model.LibraryFolderInfoAssociation(item, template, form_values, inheritable=inherited) - trans.sa_session.add(info_association) - trans.sa_session.flush() - elif item_type == 'ldda': - info_association = trans.app.model.LibraryDatasetDatasetInfoAssociation(item, template, form_values) - trans.sa_session.add(info_association) - trans.sa_session.flush() - message = 'The information has been updated.' - if cntrller == 'api': - return 200, message - new_kwd = dict(action=action, - cntrller=cntrller, - id=id, - message=util.sanitize_text(message), - status='done') - if in_library: - new_kwd.update(dict(controller='library_common', - use_panels=use_panels, - library_id=library_id, - folder_id=folder_id, - show_deleted=show_deleted)) - if in_sample_tracking: - new_kwd.update(dict(controller='requests_common', - cntrller='requests_admin', - id=trans.security.encode_id(sample.id), - sample_id=sample_id)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - - @web.expose - def delete_template(self, trans, cntrller, item_type, form_type, **kwd): - params = util.Params(kwd) - # form_type must be one of: RUN_DETAILS_TEMPLATE, LIBRARY_INFO_TEMPLATE - in_library = form_type == trans.model.FormDefinition.types.LIBRARY_INFO_TEMPLATE - in_sample_tracking = form_type == trans.model.FormDefinition.types.RUN_DETAILS_TEMPLATE - if in_library: - is_admin = (trans.user_is_admin() and cntrller == 'library_admin') - current_user_roles = trans.get_current_user_roles() - show_deleted = util.string_as_bool(params.get('show_deleted', False)) - use_panels = util.string_as_bool(params.get('use_panels', False)) - library_id = params.get('library_id', None) - folder_id = params.get('folder_id', None) - ldda_id = params.get('ldda_id', None) - elif in_sample_tracking: - request_type_id = params.get('request_type_id', None) - sample_id = params.get('sample_id', None) - message = util.restore_text(params.get('message', '')) - try: - if in_library: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - library_id=library_id, - folder_id=folder_id, - ldda_id=ldda_id, - is_admin=is_admin) - elif in_sample_tracking: - item, item_desc, action, id = self.get_item_and_stuff(trans, - item_type=item_type, - request_type_id=request_type_id, - sample_id=sample_id) - except ValueError: - return None - if in_library: - if not (is_admin or trans.app.security_agent.can_modify_library_item(current_user_roles, item)): - message = "You are not authorized to modify %s '%s'." % (item_desc, item.name) - return trans.response.send_redirect(web.url_for(controller='library_common', - action='browse_library', - cntrller=cntrller, - id=library_id, - show_deleted=show_deleted, - message=util.sanitize_text(message), - status='error')) - if in_library: - info_association, inherited = item.get_info_association() - elif in_sample_tracking: - info_association = item.run_details - if not info_association: - message = "There is no template for this %s" % item_type - else: - if in_library: - info_association.deleted = True - trans.sa_session.add(info_association) - trans.sa_session.flush() - elif in_sample_tracking: - trans.sa_session.delete(info_association) - trans.sa_session.flush() - message = 'The template for this %s has been deleted.' % item_type - new_kwd = dict(action=action, - cntrller=cntrller, - id=id, - message=util.sanitize_text(message), - status='done') - if in_library: - new_kwd.update(dict(controller='library_common', - use_panels=use_panels, - library_id=library_id, - folder_id=folder_id, - show_deleted=show_deleted)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - if in_sample_tracking: - new_kwd.update(dict(controller='request_type', - request_type_id=request_type_id, - sample_id=sample_id)) - return trans.response.send_redirect(web.url_for(**new_kwd)) - - def widget_fields_have_contents(self, widgets): - # Return True if any of the fields in widgets contain contents, widgets is a list of dictionaries that looks something like: - # [{'widget': , 'helptext': 'Field 0 help (Optional)', 'label': 'Field 0'}] - for field in widgets: - if (isinstance(field['widget'], TextArea) or isinstance(field['widget'], TextField)) and field['widget'].value: - return True - if isinstance(field['widget'], SelectField) and field['widget'].options: - for option_label, option_value, selected in field['widget'].options: - if selected: - return True - if isinstance(field['widget'], CheckboxField) and field['widget'].checked: - return True - if isinstance(field['widget'], WorkflowField) and str(field['widget'].value).lower() not in ['none']: - return True - if isinstance(field['widget'], WorkflowMappingField) and str(field['widget'].value).lower() not in ['none']: - return True - if isinstance(field['widget'], HistoryField) and str(field['widget'].value).lower() not in ['none']: - return True - if isinstance(field['widget'], AddressField) and str(field['widget'].value).lower() not in ['none']: - return True - return False - - def clean_field_contents(self, widgets, **kwd): - field_contents = {} - for widget_dict in widgets: - widget = widget_dict['widget'] - value = kwd.get(widget.name, '') - if isinstance(widget, CheckboxField): - # CheckboxField values are lists if the checkbox is checked - value = str(widget.is_checked(value)).lower() - elif isinstance(widget, AddressField): - # If the address was new, is has already been saved and widget.value is the new address.id - value = widget.value - field_contents[widget.name] = util.restore_text(value) - return field_contents - def field_param_values_ok(self, widget_name, widget_type, **kwd): # Make sure required fields have contents, etc params = util.Params(kwd) @@ -1935,114 +1351,6 @@ class UsesFormDefinitionsMixin: values[field_name] = field_value return values - def populate_widgets_from_kwd(self, trans, widgets, **kwd): - # A form submitted via refresh_on_change requires us to populate the widgets with the contents of - # the form fields the user may have entered so that when the form refreshes the contents are retained. - params = util.Params(kwd) - populated_widgets = [] - for widget_dict in widgets: - widget = widget_dict['widget'] - if params.get(widget.name, False): - # The form included a field whose contents should be used to set the - # value of the current widget (widget.name is the name set by the - # user when they defined the FormDefinition). - if isinstance(widget, AddressField): - value = util.restore_text(params.get(widget.name, '')) - if value == 'none': - value = '' - widget.value = value - widget_dict['widget'] = widget - # Populate the AddressField params with the form field contents - widget_params_dict = {} - for field_name, label, help_text in widget.fields(): - form_param_name = '%s_%s' % (widget.name, field_name) - widget_params_dict[form_param_name] = util.restore_text(params.get(form_param_name, '')) - widget.params = widget_params_dict - elif isinstance(widget, CheckboxField): - # Check the value from kwd since util.Params would have - # stringify'd the list if the checkbox is checked. - value = kwd.get(widget.name, '') - if CheckboxField.is_checked(value): - widget.value = 'true' - widget_dict['widget'] = widget - elif isinstance(widget, SelectField): - # Ensure the selected option remains selected. - value = util.restore_text(params.get(widget.name, '')) - processed_options = [] - for option_label, option_value, option_selected in widget.options: - selected = value == option_value - processed_options.append((option_label, option_value, selected)) - widget.options = processed_options - else: - widget.value = util.restore_text(params.get(widget.name, '')) - widget_dict['widget'] = widget - populated_widgets.append(widget_dict) - return populated_widgets - - def get_item_and_stuff(self, trans, item_type, **kwd): - # Return an item, description, action and an id based on the item_type. Valid item_types are - # library, folder, ldda, request_type, sample. - if item_type == 'library': - library_id = kwd.get('library_id', None) - id = library_id - try: - item = trans.sa_session.query(trans.app.model.Library).get(trans.security.decode_id(library_id)) - except Exception: - item = None - item_desc = 'data library' - action = 'library_info' - elif item_type == 'folder': - folder_id = kwd.get('folder_id', None) - id = folder_id - try: - item = trans.sa_session.query(trans.app.model.LibraryFolder).get(trans.security.decode_id(folder_id)) - except Exception: - item = None - item_desc = 'folder' - action = 'folder_info' - elif item_type == 'ldda': - ldda_id = kwd.get('ldda_id', None) - id = ldda_id - try: - item = trans.sa_session.query(trans.app.model.LibraryDatasetDatasetAssociation).get(trans.security.decode_id(ldda_id)) - except Exception: - item = None - item_desc = 'dataset' - action = 'ldda_edit_info' - elif item_type == 'request_type': - request_type_id = kwd.get('request_type_id', None) - id = request_type_id - try: - item = trans.sa_session.query(trans.app.model.RequestType).get(trans.security.decode_id(request_type_id)) - except Exception: - item = None - item_desc = 'request type' - action = 'view_editable_request_type' - elif item_type == 'sample': - sample_id = kwd.get('sample_id', None) - id = sample_id - try: - item = trans.sa_session.query(trans.app.model.Sample).get(trans.security.decode_id(sample_id)) - except Exception: - item = None - item_desc = 'sample' - action = 'view_sample' - else: - item = None - # message = "Invalid item type ( %s )" % str( item_type ) - item_desc = None - action = None - id = None - return item, item_desc, action, id - - def build_form_id_select_field(self, trans, forms, selected_value='none'): - return build_select_field(trans, - objs=forms, - label_attr='name', - select_field_name='form_id', - selected_value=selected_value, - refresh_on_change=True) - class SharableMixin: """ Mixin for a controller that manages an item that can be shared. """ diff --git a/lib/galaxy/webapps/galaxy/controllers/admin.py b/lib/galaxy/webapps/galaxy/controllers/admin.py index c73f93d4cf9..cc72def5d57 100644 --- a/lib/galaxy/webapps/galaxy/controllers/admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin.py @@ -5,7 +5,7 @@ from datetime import datetime, timedelta from string import punctuation as PUNCTUATION import six -from sqlalchemy import and_, false, func, or_ +from sqlalchemy import and_, false, or_ import galaxy.queue_worker from galaxy import ( @@ -1477,15 +1477,6 @@ class AdminGalaxy(controller.JSAppLauncher, AdminActions, UsesQuotaMixin, QuotaP message = 'Usage has changed by %s to %s.' % (nice_size(new - current), nice_size(new)) return (message, 'done') - @web.expose - @web.require_admin - def name_autocomplete_data(self, trans, q=None, limit=None, timestamp=None): - """Return autocomplete data for user emails""" - ac_data = "" - for user in trans.sa_session.query(trans.app.model.User).filter_by(deleted=False).filter(func.lower(trans.app.model.User.email).like(q.lower() + "%")): - ac_data = ac_data + user.email + "\n" - return ac_data - @web.expose_api @web.require_admin def manage_roles_and_groups_for_user(self, trans, payload=None, **kwd): diff --git a/lib/galaxy/webapps/galaxy/controllers/root.py b/lib/galaxy/webapps/galaxy/controllers/root.py index 660f081d535..7dbb88015f5 100644 --- a/lib/galaxy/webapps/galaxy/controllers/root.py +++ b/lib/galaxy/webapps/galaxy/controllers/root.py @@ -49,7 +49,6 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): def _get_extended_config(self, trans): app = trans.app - user_requests = bool(trans.user and (trans.user.requests or app.security_agent.get_accessible_request_types(trans, trans.user))) config = { 'active_view' : 'analysis', 'enable_cloud_launch' : app.config.get_bool('enable_cloud_launch', False), @@ -58,8 +57,6 @@ class RootController(controller.JSAppLauncher, UsesAnnotations): 'toolbox_in_panel' : app.toolbox.to_dict(trans), 'message_box_visible' : app.config.message_box_visible, 'show_inactivity_warning' : app.config.user_activation_on and trans.user and not trans.user.active, - # TODO: move to user - 'user_requests' : user_requests } # TODO: move to user diff --git a/templates/webapps/galaxy/external_services/generic_jquery_grid.mako b/templates/webapps/galaxy/external_services/generic_jquery_grid.mako deleted file mode 100644 index 8be21f96b3e..00000000000 --- a/templates/webapps/galaxy/external_services/generic_jquery_grid.mako +++ /dev/null @@ -1,59 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="json_common.mako" import="display_item" /> - -<%def name="title()">${param_dict['service_instance'].name}: ${action.label} - -<%def name="display_json_grid_result( headers, rows )"> - %for row in rows: - %for name in headers: -
- - ${display_item( row.get( name ) )} -
-
- %endfor - %endfor - - -<% - #HACK!!!! need to use better method of displaying jqGrid here, needs to allow paging as optionally available. - if 'Rows' in result: #paged - records = result['Records'] - total = result['Total'] - rows = result['Rows'] - page = result['Page'] - else: - rows = result - records = None - total = None - page = None - headers = rows[0].keys() -%> - -
-
${action.label} of ${param_dict['service_instance'].name} (${param_dict['service'].name}) on ${param_dict['item'].name}
-
- %if records: -
- - ${records} -
-
- %endif - %if total: -
- - ${total} -
-
- %endif - %if page: -
- - ${page} -
-
- %endif - ${display_json_grid_result( headers, rows )} -
-
diff --git a/templates/webapps/galaxy/external_services/generic_json.mako b/templates/webapps/galaxy/external_services/generic_json.mako deleted file mode 100644 index 1b9da4da3e8..00000000000 --- a/templates/webapps/galaxy/external_services/generic_json.mako +++ /dev/null @@ -1,11 +0,0 @@ -<%inherit file="/base.mako"/> -<%namespace file="json_common.mako" import="display_item" /> - -<%def name="title()">${action.label} of ${param_dict['service_instance'].name} (${param_dict['service'].name}) on ${param_dict['item'].name} - -
-
${action.label} of ${param_dict['service_instance'].name} (${param_dict['service'].name}) on ${param_dict['item'].name}
-
- ${display_item( result )} -
-
diff --git a/templates/webapps/galaxy/external_services/json_common.mako b/templates/webapps/galaxy/external_services/json_common.mako deleted file mode 100644 index 23401521ebe..00000000000 --- a/templates/webapps/galaxy/external_services/json_common.mako +++ /dev/null @@ -1,28 +0,0 @@ - -<%def name="display_dict( result_dict )"> - %for key, value in result_dict.items(): -
- - ${display_item( value )} -
-
- %endfor - - -<%def name="display_list( items )"> -
    - %for item in items: -
  • ${display_item( item ) }
  • - %endfor -
- - -<%def name="display_item( item )"> - %if isinstance( item, ( list, tuple ) ): - ${display_list( item )} - %elif isinstance( item, dict ): - ${display_dict( item )} - %else: - ${item} - %endif - diff --git a/templates/webapps/galaxy/galaxy.masthead.mako b/templates/webapps/galaxy/galaxy.masthead.mako index 3dbd6fd1e4d..4265001f55b 100644 --- a/templates/webapps/galaxy/galaxy.masthead.mako +++ b/templates/webapps/galaxy/galaxy.masthead.mako @@ -30,7 +30,6 @@ 'ftp_upload_dir' : app.config.get("ftp_upload_dir", None), 'ftp_upload_site' : app.config.get("ftp_upload_site", None), 'datatypes_disable_auto' : app.config.get_bool("datatypes_disable_auto", False), - 'user_requests' : bool( trans.user and ( trans.user.requests or app.security_agent.get_accessible_request_types( trans, trans.user ) ) ), 'user_json' : get_user_dict() } %>