def reject_request( self, trans, **kwd ): params = util.Params( kwd ) request_id = params.get( 'id', '' ) status = params.get( 'status', 'done' ) message = params.get( 'message', 'done' ) if params.get( 'cancel_reject_button', False ): return trans.response.send_redirect( web.url_for( controller='requests_common', action='view_request', cntrller='requests_admin', id=request_id ) ) try: request = trans.sa_session.query( trans.model.Request ).get( trans.security.decode_id( request_id ) ) except: return invalid_id_redirect( trans, 'requests_admin', request_id ) # Validate comment = util.restore_text( params.get( 'comment', '' ) ) if not comment: status = 'error' message = 'A reason for rejecting the request is required.' return trans.fill_template( '/admin/requests/reject.mako', cntrller='requests_admin', request=request, status=status, message=message ) # Create an event with state 'Rejected' for this request event_comment = "Sequencing request marked rejected by %s. Reason: %s " % ( trans.user.email, comment ) event = trans.model.RequestEvent( request, request.states.REJECTED, event_comment ) trans.sa_session.add( event ) trans.sa_session.flush() message = 'Sequencing request (%s) has been rejected.' % request.name return trans.response.send_redirect( web.url_for( controller='requests_admin', action='browse_requests', status=status, message=message, **kwd ) )
def create_form_definition( self, trans, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) self.__imported_from_file = False if params.get( 'create_form_button', False ): form_definition, message = self.save_form_definition( trans, form_definition_current_id=None, **kwd ) if not form_definition: return trans.response.send_redirect( web.url_for( controller='forms', action='create_form_definition', message=message, status='error', name=util.restore_text( params.get( 'name', '' ) ), description=util.restore_text( params.get( 'description', '' ) ) )) if self.__imported_from_file: return trans.response.send_redirect( web.url_for( controller='forms', action='edit_form_definition', id=trans.security.encode_id( form_definition.current.id )) ) else: return trans.response.send_redirect( web.url_for( controller='forms', action='edit_form_definition', id=trans.security.encode_id( form_definition.current.id ), add_field_button='Add field', name=form_definition.name, description=form_definition.desc, form_type_select_field=form_definition.type ) ) inputs = [ ( 'Name', TextField( 'name', 40, util.restore_text( params.get( 'name', '' ) ) ) ), ( 'Description', TextField( 'description', 40, util.restore_text( params.get( 'description', '' ) ) ) ), ( 'Type', self.__build_form_types_widget( trans, selected=params.get( 'form_type', 'none' ) ) ), ( 'Import from csv file (Optional)', FileField( 'file_data', 40, '' ) ) ] return trans.fill_template( '/admin/forms/create_form.mako', inputs=inputs, message=message, status=status )
def specified_date_handler( self, trans, **kwd ): # We add params to the keyword dict in this method in order to rename the param # with an "f-" prefix, simulating filtering by clicking a search link. We have # to take this approach because the "-" character is illegal in HTTP requests. if 'f-specified_date' in kwd and 'specified_date' not in kwd: # The user clicked a State link in the Advanced Search box, so 'specified_date' # will have been eliminated. pass elif 'specified_date' not in kwd: kwd[ 'f-specified_date' ] = 'All' else: kwd[ 'f-specified_date' ] = kwd[ 'specified_date' ] if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "workflow_per_month": # The received id is the stored_workflow id. return trans.response.send_redirect( web.url_for( controller='workflows', action='workflow_per_month', **kwd ) ) elif operation == "user_per_month": stored_workflow_id = kwd.get( 'id', None ) workflow = get_workflow( trans, stored_workflow_id ) if workflow.user: kwd[ 'email' ] = workflow.user.email else: kwd[ 'email' ] = None # For anonymous users ( shouldn't happen with workflows ) return trans.response.send_redirect( web.url_for( controller='workflows', action='user_per_month', **kwd ) ) return self.specified_date_list_grid( trans, **kwd )
def specified_date_handler(self, trans, **kwd): # We add params to the keyword dict in this method in order to rename the param # with an "f-" prefix, simulating filtering by clicking a search link. We have # to take this approach because the "-" character is illegal in HTTP requests. if 'f-specified_date' in kwd and 'specified_date' not in kwd: # The user clicked a State link in the Advanced Search box, so 'specified_date' # will have been eliminated. pass elif 'specified_date' not in kwd: kwd['f-specified_date'] = 'All' else: kwd['f-specified_date'] = kwd['specified_date'] if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "workflow_per_month": # The received id is the stored_workflow id. return trans.response.send_redirect( web.url_for(controller='workflows', action='workflow_per_month', **kwd)) elif operation == "user_per_month": stored_workflow_id = kwd.get('id', None) workflow = get_workflow(trans, stored_workflow_id) if workflow.user: kwd['email'] = workflow.user.email else: kwd['email'] = None # For anonymous users ( shouldn't happen with workflows ) return trans.response.send_redirect( web.url_for(controller='workflows', action='user_per_month', **kwd)) return self.specified_date_list_grid(trans, **kwd)
def create_form_definition(self, trans, **kwd): params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') self.__imported_from_file = False if params.get('create_form_button', False): form_definition, message = self.save_form_definition(trans, form_definition_current_id=None, **kwd) if not form_definition: return trans.response.send_redirect(web.url_for(controller='forms', action='create_form_definition', message=message, status='error', name=util.restore_text(params.get('name', '')), description=util.restore_text(params.get('description', '')))) if self.__imported_from_file: return trans.response.send_redirect(web.url_for(controller='forms', action='edit_form_definition', id=trans.security.encode_id(form_definition.current.id))) else: return trans.response.send_redirect(web.url_for(controller='forms', action='edit_form_definition', id=trans.security.encode_id(form_definition.current.id), add_field_button='Add field', name=form_definition.name, description=form_definition.desc, form_type_select_field=form_definition.type)) inputs = [('Name', TextField('name', 40, util.restore_text(params.get('name', '')))), ('Description', TextField('description', 40, util.restore_text(params.get('description', '')))), ('Type', self.__build_form_types_widget(trans, selected=params.get('form_type', 'none'))), ('Import from csv file (Optional)', FileField('file_data', 40, ''))] return trans.fill_template('/admin/forms/create_form.mako', inputs=inputs, message=message, status=status)
def browse_request_types(self, trans, **kwd): if 'operation' in kwd: operation = kwd['operation'].lower() obj_id = kwd.get('id', None) if operation == "view_form_definition": return self.view_form_definition(trans, **kwd) elif operation == "view_request_type": return self.view_request_type(trans, **kwd) elif operation == "use run details template": return trans.response.send_redirect( web.url_for(controller='requests_admin', action='add_template', cntrller='requests_admin', item_type='request_type', form_type=trans.model.FormDefinition.types. RUN_DETAILS_TEMPLATE, request_type_id=obj_id)) elif operation == "edit request type": return self.view_editable_request_type(trans, **kwd) elif operation == "delete": return self.delete_request_type(trans, **kwd) elif operation == "undelete": return self.undelete_request_type(trans, **kwd) elif operation == "edit permissions": return self.request_type_permissions(trans, **kwd) elif operation == "view_external_service": return trans.response.send_redirect( web.url_for(controller='external_service', action='view_external_service', **kwd)) # Render the grid view return self.request_type_grid(trans, **kwd)
def browse_request_types(self, trans, **kwd): if 'operation' in kwd: operation = kwd['operation'].lower() obj_id = kwd.get('id', None) if operation == "view_form_definition": return self.view_form_definition(trans, **kwd) elif operation == "view_request_type": return self.view_request_type(trans, **kwd) elif operation == "use run details template": return trans.response.send_redirect(web.url_for(controller='requests_admin', action='add_template', cntrller='requests_admin', item_type='request_type', form_type=trans.model.FormDefinition.types.RUN_DETAILS_TEMPLATE, request_type_id=obj_id)) elif operation == "edit request type": return self.view_editable_request_type(trans, **kwd) elif operation == "delete": return self.delete_request_type(trans, **kwd) elif operation == "undelete": return self.undelete_request_type(trans, **kwd) elif operation == "edit permissions": return self.request_type_permissions(trans, **kwd) elif operation == "view_external_service": return trans.response.send_redirect(web.url_for(controller='external_service', action='view_external_service', **kwd)) # Render the grid view return self.request_type_grid(trans, **kwd)
def specified_date_handler(self, trans, **kwd): # We add params to the keyword dict in this method in order to rename the param # with an "f-" prefix, simulating filtering by clicking a search link. We have # to take this approach because the "-" character is illegal in HTTP requests. kwd['sort_id'] = 'default' kwd['order'] = 'default' if 'f-specified_date' in kwd and 'specified_date' not in kwd: # The user clicked a State link in the Advanced Search box, so 'specified_date' # will have been eliminated. pass elif 'specified_date' not in kwd: kwd['f-specified_date'] = 'All' else: kwd['f-specified_date'] = kwd['specified_date'] if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "job_info": return trans.response.send_redirect( web.url_for(controller='jobs', action='job_info', **kwd)) elif operation == "tool_for_month": kwd['f-tool_id'] = kwd['tool_id'] elif operation == "tool_per_month": # The received id is the job id, so we need to get the job's tool_id. job_id = kwd.get('id', None) job = get_job(trans, job_id) kwd['tool_id'] = job.tool_id return trans.response.send_redirect( web.url_for(controller='jobs', action='tool_per_month', **kwd)) elif operation == "user_for_month": kwd['f-email'] = util.restore_text(kwd['email']) elif operation == "user_per_month": # The received id is the job id, so we need to get the id of the user # that submitted the job. job_id = kwd.get('id', None) job = get_job(trans, job_id) if job.user: kwd['email'] = job.user.email else: kwd['email'] = None # For anonymous users return trans.response.send_redirect( web.url_for(controller='jobs', action='user_per_month', **kwd)) elif operation == "specified_date_in_error": kwd['f-state'] = 'error' elif operation == "unfinished": kwd['f-state'] = 'Unfinished' elif operation == "specified_tool_in_error": kwd['f-state'] = 'error' kwd['f-tool_id'] = kwd['tool_id'] return self.specified_date_list_grid(trans, **kwd)
def specified_date_handler( self, trans, **kwd ): # We add params to the keyword dict in this method in order to rename the param # with an "f-" prefix, simulating filtering by clicking a search link. We have # to take this approach because the "-" character is illegal in HTTP requests. kwd[ 'sort_id' ] = 'default' kwd[ 'order' ] = 'default' if 'f-specified_date' in kwd and 'specified_date' not in kwd: # The user clicked a State link in the Advanced Search box, so 'specified_date' # will have been eliminated. pass elif 'specified_date' not in kwd: kwd[ 'f-specified_date' ] = 'All' else: kwd[ 'f-specified_date' ] = kwd[ 'specified_date' ] if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "job_info": return trans.response.send_redirect( web.url_for( controller='jobs', action='job_info', **kwd ) ) elif operation == "tool_for_month": kwd[ 'f-tool_id' ] = kwd[ 'tool_id' ] elif operation == "tool_per_month": # The received id is the job id, so we need to get the job's tool_id. job_id = kwd.get( 'id', None ) job = get_job( trans, job_id ) kwd[ 'tool_id' ] = job.tool_id return trans.response.send_redirect( web.url_for( controller='jobs', action='tool_per_month', **kwd ) ) elif operation == "user_for_month": kwd[ 'f-email' ] = util.restore_text( kwd[ 'email' ] ) elif operation == "user_per_month": # The received id is the job id, so we need to get the id of the user # that submitted the job. job_id = kwd.get( 'id', None ) job = get_job( trans, job_id ) if job.user: kwd[ 'email' ] = job.user.email else: kwd[ 'email' ] = None # For anonymous users return trans.response.send_redirect( web.url_for( controller='jobs', action='user_per_month', **kwd ) ) elif operation == "specified_date_in_error": kwd[ 'f-state' ] = 'error' elif operation == "unfinished": kwd[ 'f-state' ] = 'Unfinished' elif operation == "specified_tool_in_error": kwd[ 'f-state' ] = 'error' kwd[ 'f-tool_id' ] = kwd[ 'tool_id' ] return self.specified_date_list_grid( trans, **kwd )
def edit_external_service_form_definition( self, trans, **kwd ): util.Params( kwd ) external_service_id = kwd.get( 'id', None ) try: external_service = trans.sa_session.query( trans.model.ExternalService ).get( trans.security.decode_id( external_service_id ) ) except: return invalid_id_redirect( trans, 'external_service', external_service_id, 'external_service', action='browse_external_services' ) vars = dict( id=trans.security.encode_id( external_service.form_definition.form_definition_current_id ), response_redirect=web.url_for( controller='external_service', action='update_external_service_form_definition', **kwd ) ) return trans.response.send_redirect( web.url_for( controller='forms', action='edit_form_definition', **vars ) )
def reload_external_service_types(self, trans, **kwd): params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') external_service_type_id = params.get('external_service_type_id', 'none') if params.get('reload_external_service_type_button', False): new_external_service_type = trans.app.external_service_types.reload( external_service_type_id) status = 'done' message = 'Reloaded external service type: %s' % new_external_service_type.name external_service_type_select_field = self.__build_external_service_type_select_field( trans, external_service_type_id, refresh_on_change=False, visible_external_service_types_only=False) if not trans.app.external_service_types.visible_external_service_types: message = 'There are no visible external service types in the external service types config file.' status = 'error' return trans.response.send_redirect( web.url_for(controller='external_service', action='browse_external_services', message=message, status=status)) return trans.fill_template( '/admin/external_service/reload_external_service_types.mako', external_service_type_select_field= external_service_type_select_field, message=message, status=status)
def undelete_external_service(self, trans, **kwd): external_service_id = kwd.get('id', '') external_service_id_list = util.listify(external_service_id) for external_service_id in external_service_id_list: try: external_service = trans.sa_session.query( trans.model.ExternalService).get( trans.security.decode_id(external_service_id)) except: return invalid_id_redirect(trans, 'external_service', external_service_id, 'external_service', action='browse_external_services') external_service.deleted = False trans.sa_session.add(external_service) trans.sa_session.flush() status = 'done' message = '%i external services have been undeleted' % len( external_service_id_list) return trans.response.send_redirect( web.url_for(controller='external_service', action='browse_external_services', message=message, status=status))
def undelete_request_type(self, trans, **kwd): request_type_id = kwd.get('id', '') request_type_id_list = util.listify(request_type_id) for request_type_id in request_type_id_list: try: request_type = trans.sa_session.query( trans.model.RequestType).get( trans.security.decode_id(request_type_id)) except: return invalid_id_redirect(trans, 'request_type', request_type_id, 'request type', action='browse_request_types') request_type.deleted = False trans.sa_session.add(request_type) trans.sa_session.flush() status = 'done' message = '%i request types have been undeleted' % len( request_type_id_list) return trans.response.send_redirect( web.url_for(controller='request_type', action='browse_request_types', message=message, status=status))
def undelete_form_definition(self, trans, **kwd): id_list = util.listify(kwd['id']) for id in id_list: try: form_definition_current = trans.sa_session.query(trans.app.model.FormDefinitionCurrent).get(trans.security.decode_id(id)) except: return trans.response.send_redirect(web.url_for(controller='forms', action='browse_form_definitions', message='Invalid form', status='error')) form_definition_current.deleted = False trans.sa_session.add(form_definition_current) trans.sa_session.flush() return trans.response.send_redirect(web.url_for(controller='forms', action='browse_form_definitions', message='%i forms have been undeleted.' % len(id_list), status='done'))
def create_external_service(self, trans, **kwd): params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') external_service_type_id = params.get('external_service_type_id', 'none') widgets = self.__build_external_service_widgets(trans, external_service=None, **kwd) external_service_type = None error = False if not trans.app.external_service_types.visible_external_service_types: error = True message = 'There are no visible external_service types in the external_service types config file' elif params.get('create_external_service_button', False): if external_service_type_id == 'none': error = True message = 'Provide an external_service_type_id to create a new external service.' else: self.__save_external_service(trans, **kwd) message = 'The external_service has been created.' return trans.response.send_redirect( web.url_for(controller='external_service', action='browse_external_services', message=message, status=status)) elif external_service_type_id != 'none': # Form submission via refresh_on_change trans.app.external_service_types.reload(external_service_type_id) external_service_type = self.get_external_service_type( trans, external_service_type_id) widgets.extend( external_service_type.form_definition.get_widgets( trans.user, **kwd)) if error: return trans.response.send_redirect( web.url_for(controller='external_service', action='browse_external_services', message=message, status='error')) return trans.fill_template( '/admin/external_service/create_external_service.mako', widgets=widgets, message=message, status=status, external_service_type=external_service_type)
def undelete_form_definition( self, trans, **kwd ): id_list = util.listify( kwd['id'] ) for id in id_list: try: form_definition_current = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(id) ) except: return trans.response.send_redirect( web.url_for( controller='forms', action='browse_form_definitions', message='Invalid form', status='error' ) ) form_definition_current.deleted = False trans.sa_session.add( form_definition_current ) trans.sa_session.flush() return trans.response.send_redirect( web.url_for( controller='forms', action='browse_form_definitions', message='%i forms have been undeleted.' % len(id_list), status='done') )
def get_external_service_type(self, trans, external_service_type_id, action='browse_external_services'): try: return trans.app.external_service_types.all_external_service_types[ external_service_type_id ] except KeyError: message = 'Error in loading external service type: %s' % external_service_type_id return trans.response.send_redirect( web.url_for( controller='external_service', action=action, message=message, status='error' ) )
def browse_requests(self, trans, **kwd): if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "edit": return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_basic_request_info', cntrller='requests_admin', **kwd)) if operation == "add_samples": return trans.response.send_redirect( web.url_for(controller='requests_common', action='add_samples', cntrller='requests_admin', **kwd)) if operation == "edit_samples": return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_samples', cntrller='requests_admin', **kwd)) if operation == "view_request": return trans.response.send_redirect( web.url_for(controller='requests_common', action='view_request', cntrller='requests_admin', **kwd)) if operation == "view_request_history": return trans.response.send_redirect( web.url_for(controller='requests_common', action='view_request_history', cntrller='requests_admin', **kwd)) if operation == "reject": return self.reject_request(trans, **kwd) if operation == "view_type": return trans.response.send_redirect( web.url_for(controller='request_type', action='view_request_type', **kwd)) if operation == "delete": return trans.response.send_redirect( web.url_for(controller='requests_common', action='delete_request', cntrller='requests_admin', **kwd)) if operation == "undelete": return trans.response.send_redirect( web.url_for(controller='requests_common', action='undelete_request', cntrller='requests_admin', **kwd)) # Render the list view return self.request_grid(trans, **kwd)
def rename_datasets( self, trans, **kwd ): # This method is called from the DataTransferGrid when a user is renaming 1 or more # SampleDatasets. params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) sample_id = kwd.get( 'sample_id', None ) try: sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( sample_id ) ) except: return invalid_id_redirect( trans, 'requests_admin', sample_id, 'sample' ) # id_list is list of SampleDataset ids, which is a subset of all # of the SampleDatasets associated with the Sample. The user may # or may not have selected all of the SampleDatasets for renaming. id_list = util.listify( kwd.get( 'id_list', [] ) ) # Get all of the SampleDatasets sample_datasets = [] for sample_dataset_id in id_list: sample_dataset = trans.sa_session.query( trans.app.model.SampleDataset ).get( trans.security.decode_id( sample_dataset_id ) ) sample_datasets.append( sample_dataset ) if params.get( 'rename_datasets_button', False ): incorrect_dataset_names = [] for sample_dataset in sample_datasets: encoded_id = trans.security.encode_id( sample_dataset.id ) selected_option = util.restore_text( params.get( 'rename_datasets_for_sample_%s' % encoded_id, '' ) ) new_name = util.restore_text( params.get( 'new_name_%s' % encoded_id, '' ) ) if not new_name: incorrect_dataset_names.append( sample_dataset.name ) continue new_name = util.sanitize_for_filename( new_name ) if selected_option == 'none': sample_dataset.name = new_name else: sample_dataset.name = '%s_%s' % ( selected_option, new_name ) trans.sa_session.add( sample_dataset ) trans.sa_session.flush() if len( sample_datasets ) == len( incorrect_dataset_names ): status = 'error' message = 'All datasets renamed incorrectly.' elif len( incorrect_dataset_names ): status = 'done' message = 'Changes saved successfully. The following datasets were renamed incorrectly: %s.' % str( incorrect_dataset_names ) else: message = 'Changes saved successfully.' return trans.fill_template( '/admin/requests/rename_datasets.mako', sample=sample, id_list=id_list, message=message, status=status ) return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', sample_id=sample_id ) )
def view_latest_form_definition(self, trans, **kwd): '''Displays the layout of the latest version of the form definition''' form_definition_current_id = kwd.get('id', None) try: form_definition_current = trans.sa_session.query(trans.app.model.FormDefinitionCurrent) \ .get(trans.security.decode_id(form_definition_current_id)) except: return trans.response.send_redirect(web.url_for(controller='forms', action='browse_form_definitions', message='Invalid form', status='error')) return trans.fill_template('/admin/forms/view_form_definition.mako', form_definition=form_definition_current.latest_form)
def view_latest_form_definition( self, trans, **kwd ): '''Displays the layout of the latest version of the form definition''' form_definition_current_id = kwd.get( 'id', None ) try: form_definition_current = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ) \ .get( trans.security.decode_id( form_definition_current_id ) ) except: return trans.response.send_redirect( web.url_for( controller='forms', action='browse_form_definitions', message='Invalid form', status='error' ) ) return trans.fill_template( '/admin/forms/view_form_definition.mako', form_definition=form_definition_current.latest_form )
def __get_files(self, trans, request, external_service, folder_path): # Retrieves the filenames to be transferred from the remote host. ok = True external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] if not scp_configs['host'] or not scp_configs[ 'user_name'] or not scp_configs['password']: status = 'error' message = "Error in external service login information." ok = False def print_ticks(d): pass cmd = 'ssh %s@%s "ls -p \'%s\'"' % (scp_configs['user_name'], scp_configs['host'], folder_path) # Handle the authentication message if keys are not set - the message is # something like: "Are you sure you want to continue connecting (yes/no)." if pexpect is not None: output = pexpect.run(cmd, events={ '\(yes\/no\)\.*': 'yes\r\n', '.ssword:*': scp_configs['password'] + '\r\n', pexpect.TIMEOUT: print_ticks }, timeout=10) if 'No such file or directory' in output: status = 'error' message = "No folder named (%s) exists on the external service." % folder_path ok = False else: status = 'error' message = PEXPECT_IMPORT_MESSAGE ok = False if ok: if 'assword:' in output: # Eliminate the output created using ssh from the tree output_as_list = output.splitlines()[1:] else: output_as_list = output.splitlines() return output_as_list return trans.response.send_redirect( web.url_for(controller='requests_admin', action='select_datasets_to_transfer', request_id=trans.security.encode_id(request.id), external_service_id=trans.security.encode_id( external_service.id), status=status, message=message))
def create_request_type(self, trans, **kwd): params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') rt_info_widgets, rt_states_widgets = self.__get_populated_request_type_widgets( trans, **kwd) external_service_select_fields_list = [] # get all the external services selected till now external_services_list = self.__get_external_services(trans, **kwd) for index, external_service in enumerate(external_services_list): external_service_select_field = self.__build_external_service_select_field( trans, 'external_service_id_%i' % index, external_service) external_service_select_fields_list.append( external_service_select_field) if params.get('add_state_button', False): # Append a new tuple to the set of states which will result in # empty state name and description TextFields being displayed on # the form. rt_states_widgets.append(("", "")) elif params.get('remove_state_button', False): index = int(params.get('remove_state_button', '').split(" ")[2]) del rt_states_widgets[index - 1] elif params.get('add_external_service_button', False): # create a new one external_service_select_field = self.__build_external_service_select_field( trans, 'external_service_id_%i' % len(external_services_list)) external_service_select_fields_list.append( external_service_select_field) elif params.get('create_request_type_button', False): self.__save_request_type(trans, action='create_request_type', **kwd) message = 'The request type has been created.' return trans.response.send_redirect( web.url_for(controller='request_type', action='browse_request_types', message=message, status=status)) # A request_type requires at least one possible sample state so that # it can be used to create a sequencing request if not len(rt_states_widgets): rt_states_widgets.append(("New", "First sample state")) return trans.fill_template( '/admin/request_type/create_request_type.mako', rt_info_widgets=rt_info_widgets, rt_states_widgets=rt_states_widgets, external_service_select_fields_list= external_service_select_fields_list, message=message, status=status)
def get_external_service_type(self, trans, external_service_type_id, action='browse_external_services'): try: return trans.app.external_service_types.all_external_service_types[ external_service_type_id] except KeyError: message = 'Error in loading external service type: %s' % external_service_type_id return trans.response.send_redirect( web.url_for(controller='external_service', action=action, message=message, status='error'))
def edit_external_service_form_definition(self, trans, **kwd): util.Params(kwd) external_service_id = kwd.get('id', None) try: external_service = trans.sa_session.query( trans.model.ExternalService).get( trans.security.decode_id(external_service_id)) except: return invalid_id_redirect(trans, 'external_service', external_service_id, 'external_service', action='browse_external_services') vars = dict(id=trans.security.encode_id( external_service.form_definition.form_definition_current_id), response_redirect=web.url_for( controller='external_service', action='update_external_service_form_definition', **kwd)) return trans.response.send_redirect( web.url_for(controller='forms', action='edit_form_definition', **vars))
def create_external_service( self, trans, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) external_service_type_id = params.get( 'external_service_type_id', 'none' ) widgets = self.__build_external_service_widgets( trans, external_service=None, **kwd ) external_service_type = None error = False if not trans.app.external_service_types.visible_external_service_types: error = True message = 'There are no visible external_service types in the external_service types config file' elif params.get( 'create_external_service_button', False ): if external_service_type_id == 'none': error = True message = 'Provide an external_service_type_id to create a new external service.' else: self.__save_external_service( trans, **kwd ) message = 'The external_service has been created.' return trans.response.send_redirect( web.url_for( controller='external_service', action='browse_external_services', message=message, status=status ) ) elif external_service_type_id != 'none': # Form submission via refresh_on_change trans.app.external_service_types.reload( external_service_type_id ) external_service_type = self.get_external_service_type( trans, external_service_type_id ) widgets.extend( external_service_type.form_definition.get_widgets( trans.user, **kwd ) ) if error: return trans.response.send_redirect( web.url_for( controller='external_service', action='browse_external_services', message=message, status='error' ) ) return trans.fill_template( '/admin/external_service/create_external_service.mako', widgets=widgets, message=message, status=status, external_service_type=external_service_type )
def __import_fields(self, trans, csv_file, form_type): ''' "company","name of the company", "True", "required", "TextField",, "due date","turnaround time", "True", "optional", "SelectField","24 hours, 1 week, 1 month" ''' import csv fields = [] layouts = set() try: reader = csv.reader(csv_file.file) index = 1 for row in reader: if len(row) < 7: # ignore bogus rows continue options = row[5].split(',') if len(row) >= 8: fields.append({ 'name': '%i_field_name' % index, 'label': row[0], 'helptext': row[1], 'visible': row[2], 'required': row[3], 'type': row[4], 'selectlist': options, 'layout': row[6], 'default': row[7] }) layouts.add(row[6]) else: fields.append({ 'name': '%i_field_name' % index, 'label': row[0], 'helptext': row[1], 'visible': row[2], 'required': row[3], 'type': row[4], 'selectlist': options, 'default': row[6] }) index = index + 1 except: return trans.response.send_redirect( web.url_for(controller='forms', action='create_form', status='error', message='Error in importing <b>%s</b> file' % csv_file.file)) self.__imported_from_file = True return fields, list(layouts)
def browse_requests( self, trans, **kwd ): if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "edit": return trans.response.send_redirect( web.url_for( controller='requests_common', action='edit_basic_request_info', cntrller='requests_admin', **kwd ) ) if operation == "add_samples": return trans.response.send_redirect( web.url_for( controller='requests_common', action='add_samples', cntrller='requests_admin', **kwd ) ) if operation == "edit_samples": return trans.response.send_redirect( web.url_for( controller='requests_common', action='edit_samples', cntrller='requests_admin', **kwd ) ) if operation == "view_request": return trans.response.send_redirect( web.url_for( controller='requests_common', action='view_request', cntrller='requests_admin', **kwd ) ) if operation == "view_request_history": return trans.response.send_redirect( web.url_for( controller='requests_common', action='view_request_history', cntrller='requests_admin', **kwd ) ) if operation == "reject": return self.reject_request( trans, **kwd ) if operation == "view_type": return trans.response.send_redirect( web.url_for( controller='request_type', action='view_request_type', **kwd ) ) if operation == "delete": return trans.response.send_redirect( web.url_for( controller='requests_common', action='delete_request', cntrller='requests_admin', **kwd ) ) if operation == "undelete": return trans.response.send_redirect( web.url_for( controller='requests_common', action='undelete_request', cntrller='requests_admin', **kwd ) ) # Render the list view return self.request_grid( trans, **kwd )
def delete_external_service( self, trans, **kwd ): external_service_id = kwd.get( 'id', '' ) external_service_id_list = util.listify( external_service_id ) for external_service_id in external_service_id_list: try: external_service = trans.sa_session.query( trans.model.ExternalService ).get( trans.security.decode_id( external_service_id ) ) except: return invalid_id_redirect( trans, 'external_service', external_service_id, 'external_service', action='browse_external_services' ) external_service.deleted = True trans.sa_session.add( external_service ) trans.sa_session.flush() message = '%i external services has been deleted' % len( external_service_id_list ) return trans.response.send_redirect( web.url_for( controller='external_service', action='browse_external_services', message=message, status='done' ) )
def delete_request_type(self, trans, **kwd): request_type_id = kwd.get('id', '') request_type_id_list = util.listify(request_type_id) for request_type_id in request_type_id_list: try: request_type = trans.sa_session.query(trans.model.RequestType).get(trans.security.decode_id(request_type_id)) except: return invalid_id_redirect(trans, 'request_type', request_type_id, 'request type', action='browse_request_types') request_type.deleted = True trans.sa_session.add(request_type) trans.sa_session.flush() message = '%i request types has been deleted' % len(request_type_id_list) return trans.response.send_redirect(web.url_for(controller='request_type', action='browse_request_types', message=message, status='done'))
def update_external_service_form_definition( self, trans, **kwd ): util.Params( kwd ) external_service_id = kwd.get( 'id', None ) try: external_service = trans.sa_session.query( trans.model.ExternalService ).get( trans.security.decode_id( external_service_id ) ) except: return invalid_id_redirect( trans, 'external_service', external_service_id, 'external_service', action='browse_external_services' ) external_service.form_definition = external_service.form_definition.current.latest_form trans.sa_session.add( external_service ) trans.sa_session.flush() message = "The form definition for the '%s' external service has been updated with your changes." % external_service.name return trans.response.send_redirect( web.url_for( controller='external_service', action='edit_external_service', message=message, status='done', **kwd ) )
def browse_form_definitions(self, trans, **kwd): if 'operation' in kwd: operation = kwd['operation'].lower() if not kwd.get('id', None): return trans.response.send_redirect(web.url_for(controller='forms', action='browse_form_definitions', status='error', message="Invalid form ID")) if operation == "view_latest_form_definition": return self.view_latest_form_definition(trans, **kwd) elif operation == "delete": return self.delete_form_definition(trans, **kwd) elif operation == "undelete": return self.undelete_form_definition(trans, **kwd) elif operation == "edit": return self.edit_form_definition(trans, **kwd) return self.forms_grid(trans, **kwd)
def initiate_data_transfer(self, trans, sample_id, sample_datasets=[], sample_dataset_id=''): # Initiate the transfer of the datasets from the external service to the target Galaxy data library. # The admin user must have LIBRARY_ADD permission for the target library and folder try: sample = trans.sa_session.query(trans.model.Sample).get(trans.security.decode_id(sample_id)) except: return invalid_id_redirect(trans, 'requests_admin', sample_id, 'sample') message = "" status = "done" # Make sure the current admin user has LIBRARY_ADD permission on the target data library and folder. self.__ensure_library_add_permission(trans, sample.library, sample.folder) if sample_dataset_id and not sample_datasets: # Either a list of SampleDataset objects or a comma-separated string of # encoded SampleDataset ids can be received. If the latter, parse the # sample_dataset_id string to build the list of sample_datasets. id_list = util.listify(sample_dataset_id) for sample_dataset_id in id_list: sample_dataset = trans.sa_session.query(trans.model.SampleDataset).get(trans.security.decode_id(sample_dataset_id)) sample_datasets.append(sample_dataset) if trans.app.config.enable_beta_job_managers: # For now, assume that all SampleDatasets use the same external service ( this may not be optimal ). if sample_datasets: external_service_type_id = sample_datasets[0].external_service.external_service_type_id # Here external_service_type_id will be something like '454_life_sciences' external_service = sample.request.type.get_external_service(external_service_type_id) external_service_type = external_service.get_external_service_type(trans) external_service.load_data_transfer_settings(trans) # For now only scp is supported. scp_configs = external_service.data_transfer[trans.model.ExternalService.data_transfer_protocol.SCP] if not scp_configs['automatic_transfer']: deferred_plugin = 'ManualDataTransferPlugin' else: raise Exception("Automatic data transfer using scp is not yet supported.") trans.app.job_manager.deferred_job_queue.plugins[deferred_plugin].create_job(trans, sample=sample, sample_datasets=sample_datasets, external_service=external_service, external_service_type=external_service_type) else: message = "Message queue transfer is no longer supported, please set enable_beta_job_managers = True in galaxy.ini" status = "error" return trans.response.send_redirect(web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id(sample.id), message=message, status=status))
def initiate_data_transfer( self, trans, sample_id, sample_datasets=[], sample_dataset_id='' ): # Initiate the transfer of the datasets from the external service to the target Galaxy data library. # The admin user must have LIBRARY_ADD permission for the target library and folder try: sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( sample_id ) ) except: return invalid_id_redirect( trans, 'requests_admin', sample_id, 'sample' ) message = "" status = "done" # Make sure the current admin user has LIBRARY_ADD permission on the target data library and folder. self.__ensure_library_add_permission( trans, sample.library, sample.folder ) if sample_dataset_id and not sample_datasets: # Either a list of SampleDataset objects or a comma-separated string of # encoded SampleDataset ids can be received. If the latter, parse the # sample_dataset_id string to build the list of sample_datasets. id_list = util.listify( sample_dataset_id ) for sample_dataset_id in id_list: sample_dataset = trans.sa_session.query( trans.model.SampleDataset ).get( trans.security.decode_id( sample_dataset_id ) ) sample_datasets.append( sample_dataset ) if trans.app.config.enable_beta_job_managers: # For now, assume that all SampleDatasets use the same external service ( this may not be optimal ). if sample_datasets: external_service_type_id = sample_datasets[0].external_service.external_service_type_id # Here external_service_type_id will be something like '454_life_sciences' external_service = sample.request.type.get_external_service( external_service_type_id ) external_service_type = external_service.get_external_service_type( trans ) external_service.load_data_transfer_settings( trans ) # For now only scp is supported. scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP ] if not scp_configs[ 'automatic_transfer' ]: deferred_plugin = 'ManualDataTransferPlugin' else: raise Exception( "Automatic data transfer using scp is not yet supported." ) trans.app.job_manager.deferred_job_queue.plugins[ deferred_plugin ].create_job( trans, sample=sample, sample_datasets=sample_datasets, external_service=external_service, external_service_type=external_service_type ) else: message = "Message queue transfer is no longer supported, please set enable_beta_job_managers = True in galaxy.ini" status = "error" return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id( sample.id ), message=message, status=status ) )
def browse_form_definitions( self, trans, **kwd ): if 'operation' in kwd: operation = kwd['operation'].lower() if not kwd.get( 'id', None ): return trans.response.send_redirect( web.url_for( controller='forms', action='browse_form_definitions', status='error', message="Invalid form ID") ) if operation == "view_latest_form_definition": return self.view_latest_form_definition( trans, **kwd ) elif operation == "delete": return self.delete_form_definition( trans, **kwd ) elif operation == "undelete": return self.undelete_form_definition( trans, **kwd ) elif operation == "edit": return self.edit_form_definition( trans, **kwd ) return self.forms_grid( trans, **kwd )
def __import_fields( self, trans, csv_file, form_type ): ''' "company","name of the company", "True", "required", "TextField",, "due date","turnaround time", "True", "optional", "SelectField","24 hours, 1 week, 1 month" ''' import csv fields = [] layouts = set() try: reader = csv.reader(csv_file.file) index = 1 for row in reader: if len(row) < 7: # ignore bogus rows continue options = row[5].split(',') if len(row) >= 8: fields.append( { 'name': '%i_field_name' % index, 'label': row[0], 'helptext': row[1], 'visible': row[2], 'required': row[3], 'type': row[4], 'selectlist': options, 'layout': row[6], 'default': row[7] } ) layouts.add(row[6]) else: fields.append( { 'name': '%i_field_name' % index, 'label': row[0], 'helptext': row[1], 'visible': row[2], 'required': row[3], 'type': row[4], 'selectlist': options, 'default': row[6] } ) index = index + 1 except: return trans.response.send_redirect( web.url_for( controller='forms', action='create_form', status='error', message='Error in importing <b>%s</b> file' % csv_file.file)) self.__imported_from_file = True return fields, list(layouts)
def create_request_type(self, trans, **kwd): params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') rt_info_widgets, rt_states_widgets = self.__get_populated_request_type_widgets(trans, **kwd) external_service_select_fields_list = [] # get all the external services selected till now external_services_list = self.__get_external_services(trans, **kwd) for index, external_service in enumerate(external_services_list): external_service_select_field = self.__build_external_service_select_field(trans, 'external_service_id_%i' % index, external_service) external_service_select_fields_list.append(external_service_select_field) if params.get('add_state_button', False): # Append a new tuple to the set of states which will result in # empty state name and description TextFields being displayed on # the form. rt_states_widgets.append(("", "")) elif params.get('remove_state_button', False): index = int(params.get('remove_state_button', '').split(" ")[2]) del rt_states_widgets[index - 1] elif params.get('add_external_service_button', False): # create a new one external_service_select_field = self.__build_external_service_select_field(trans, 'external_service_id_%i' % len(external_services_list)) external_service_select_fields_list.append(external_service_select_field) elif params.get('create_request_type_button', False): self.__save_request_type(trans, action='create_request_type', **kwd) message = 'The request type has been created.' return trans.response.send_redirect(web.url_for(controller='request_type', action='browse_request_types', message=message, status=status)) # A request_type requires at least one possible sample state so that # it can be used to create a sequencing request if not len(rt_states_widgets): rt_states_widgets.append(("New", "First sample state")) return trans.fill_template('/admin/request_type/create_request_type.mako', rt_info_widgets=rt_info_widgets, rt_states_widgets=rt_states_widgets, external_service_select_fields_list=external_service_select_fields_list, message=message, status=status)
def __get_files( self, trans, request, external_service, folder_path ): # Retrieves the filenames to be transferred from the remote host. ok = True external_service.load_data_transfer_settings( trans ) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP ] if not scp_configs[ 'host' ] or not scp_configs[ 'user_name' ] or not scp_configs[ 'password' ]: status = 'error' message = "Error in external service login information." ok = False def print_ticks( d ): pass cmd = 'ssh %s@%s "ls -p \'%s\'"' % ( scp_configs[ 'user_name' ], scp_configs[ 'host' ], folder_path ) # Handle the authentication message if keys are not set - the message is # something like: "Are you sure you want to continue connecting (yes/no)." if pexpect is not None: output = pexpect.run( cmd, events={ '\(yes\/no\)\.*' : 'yes\r\n', '.ssword:*' : scp_configs[ 'password' ] + '\r\n', pexpect.TIMEOUT : print_ticks }, timeout=10 ) if 'No such file or directory' in output: status = 'error' message = "No folder named (%s) exists on the external service." % folder_path ok = False else: status = 'error' message = PEXPECT_IMPORT_MESSAGE ok = False if ok: if 'assword:' in output: # Eliminate the output created using ssh from the tree output_as_list = output.splitlines()[ 1: ] else: output_as_list = output.splitlines() return output_as_list return trans.response.send_redirect( web.url_for( controller='requests_admin', action='select_datasets_to_transfer', request_id=trans.security.encode_id( request.id ), external_service_id=trans.security.encode_id( external_service.id ), status=status, message=message ) )
def update_external_service_form_definition(self, trans, **kwd): util.Params(kwd) external_service_id = kwd.get('id', None) try: external_service = trans.sa_session.query( trans.model.ExternalService).get( trans.security.decode_id(external_service_id)) except: return invalid_id_redirect(trans, 'external_service', external_service_id, 'external_service', action='browse_external_services') external_service.form_definition = external_service.form_definition.current.latest_form trans.sa_session.add(external_service) trans.sa_session.flush() message = "The form definition for the '%s' external service has been updated with your changes." % external_service.name return trans.response.send_redirect( web.url_for(controller='external_service', action='edit_external_service', message=message, status='done', **kwd))
def reload_external_service_types( self, trans, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) external_service_type_id = params.get( 'external_service_type_id', 'none' ) if params.get( 'reload_external_service_type_button', False ): new_external_service_type = trans.app.external_service_types.reload( external_service_type_id ) status = 'done' message = 'Reloaded external service type: %s' % new_external_service_type.name external_service_type_select_field = self.__build_external_service_type_select_field( trans, external_service_type_id, refresh_on_change=False, visible_external_service_types_only=False ) if not trans.app.external_service_types.visible_external_service_types: message = 'There are no visible external service types in the external service types config file.' status = 'error' return trans.response.send_redirect( web.url_for( controller='external_service', action='browse_external_services', message=message, status=status ) ) return trans.fill_template( '/admin/external_service/reload_external_service_types.mako', external_service_type_select_field=external_service_type_select_field, message=message, status=status )
def manage_datasets(self, trans, **kwd): def handle_error(**kwd): kwd['status'] = 'error' return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', **kwd)) params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') # When this method is called due to a grid operation, the sample ID # will be in the param 'id'. But when this method is called via a # redirect from another method, the ID will be in 'sample_id'. So, # check for 'id' if 'sample_id' is not provided. sample_id = params.get('sample_id', None) if sample_id is None: sample_id = params.get('id', None) try: sample = trans.sa_session.query(trans.model.Sample).get( trans.security.decode_id(sample_id)) except: return invalid_id_redirect(trans, 'requests_admin', sample_id, 'sample') if 'operation' in kwd: operation = kwd['operation'].lower() sample_dataset_id = params.get('id', None) if not sample_dataset_id: message = 'Select at least 1 dataset to %s.' % operation kwd['message'] = message del kwd['operation'] handle_error(**kwd) id_list = util.listify(sample_dataset_id) selected_sample_datasets = [] for sample_dataset_id in id_list: try: sample_dataset = trans.sa_session.query( trans.model.SampleDataset).get( trans.security.decode_id(sample_dataset_id)) except: return invalid_id_redirect(trans, 'requests_admin', sample_dataset_id, 'sample dataset') selected_sample_datasets.append(sample_dataset) if operation == "view": return trans.fill_template( '/admin/requests/view_sample_dataset.mako', cntrller='requests_admin', sample_dataset=selected_sample_datasets[0]) elif operation == "delete": not_deleted = [] for sample_dataset in selected_sample_datasets: # Make sure the dataset has been transferred before deleting it. if sample_dataset in sample_dataset.sample.untransferred_dataset_files: # Save the sample dataset sample = sample_dataset.sample trans.sa_session.delete(sample_dataset) trans.sa_session.flush() else: not_deleted.append(sample_dataset.name) message = '%i datasets have been deleted.' % (len(id_list) - len(not_deleted)) if not_deleted: status = 'warning' message = message + ' %s could not be deleted because their transfer status is not "Not Started". ' % str( not_deleted) return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id(sample.id), status=status, message=message)) elif operation == "rename": # If one of the selected sample datasets is in the NOT_STARTED state, # then display an error message. A NOT_STARTED state implies the dataset # has not yet been transferred. no_datasets_transferred = True for selected_sample_dataset in selected_sample_datasets: if selected_sample_dataset in selected_sample_dataset.sample.untransferred_dataset_files: no_datasets_transferred = False break if no_datasets_transferred: status = 'error' message = 'A dataset can be renamed only if it has been transferred.' return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id( selected_sample_datasets[0].sample.id), status=status, message=message)) return trans.fill_template( '/admin/requests/rename_datasets.mako', sample=selected_sample_datasets[0].sample, id_list=id_list) elif operation == "transfer": self.initiate_data_transfer( trans, trans.security.encode_id( selected_sample_datasets[0].sample.id), sample_datasets=selected_sample_datasets) elif operation == "view_external_service": return trans.response.send_redirect( web.url_for(controller='external_service', action='view_external_service', **kwd)) # Render the grid view request_id = trans.security.encode_id(sample.request.id) library_id = trans.security.encode_id(sample.library.id) self.datatx_grid.title = 'Manage "%s" datasets' % sample.name self.datatx_grid.global_actions = [ grids.GridAction( "Browse target data library", dict(controller='library_common', action='browse_library', cntrller='library_admin', id=library_id)), grids.GridAction( "Browse this request", dict(controller='requests_common', action='view_request', cntrller='requests_admin', id=request_id)) ] return self.datatx_grid(trans, **kwd)
class RequestsAdmin(BaseUIController, UsesFormDefinitionsMixin): request_grid = AdminRequestsGrid() datatx_grid = DataTransferGrid() @web.expose @web.require_admin def index(self, trans): return trans.fill_template("/admin/requests/index.mako") @web.expose @web.require_admin def browse_requests(self, trans, **kwd): if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "edit": return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_basic_request_info', cntrller='requests_admin', **kwd)) if operation == "add_samples": return trans.response.send_redirect( web.url_for(controller='requests_common', action='add_samples', cntrller='requests_admin', **kwd)) if operation == "edit_samples": return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_samples', cntrller='requests_admin', **kwd)) if operation == "view_request": return trans.response.send_redirect( web.url_for(controller='requests_common', action='view_request', cntrller='requests_admin', **kwd)) if operation == "view_request_history": return trans.response.send_redirect( web.url_for(controller='requests_common', action='view_request_history', cntrller='requests_admin', **kwd)) if operation == "reject": return self.reject_request(trans, **kwd) if operation == "view_type": return trans.response.send_redirect( web.url_for(controller='request_type', action='view_request_type', **kwd)) if operation == "delete": return trans.response.send_redirect( web.url_for(controller='requests_common', action='delete_request', cntrller='requests_admin', **kwd)) if operation == "undelete": return trans.response.send_redirect( web.url_for(controller='requests_common', action='undelete_request', cntrller='requests_admin', **kwd)) # Render the list view return self.request_grid(trans, **kwd) @web.expose @web.require_admin def reject_request(self, trans, **kwd): params = util.Params(kwd) request_id = params.get('id', '') status = params.get('status', 'done') message = params.get('message', 'done') if params.get('cancel_reject_button', False): return trans.response.send_redirect( web.url_for(controller='requests_common', action='view_request', cntrller='requests_admin', id=request_id)) try: request = trans.sa_session.query(trans.model.Request).get( trans.security.decode_id(request_id)) except: return invalid_id_redirect(trans, 'requests_admin', request_id) # Validate comment = util.restore_text(params.get('comment', '')) if not comment: status = 'error' message = 'A reason for rejecting the request is required.' return trans.fill_template('/admin/requests/reject.mako', cntrller='requests_admin', request=request, status=status, message=message) # Create an event with state 'Rejected' for this request event_comment = "Sequencing request marked rejected by %s. Reason: %s " % ( trans.user.email, comment) event = trans.model.RequestEvent(request, request.states.REJECTED, event_comment) trans.sa_session.add(event) trans.sa_session.flush() message = 'Sequencing request (%s) has been rejected.' % request.name return trans.response.send_redirect( web.url_for(controller='requests_admin', action='browse_requests', status=status, message=message, **kwd)) # Data transfer from sequencer/external_service @web.expose @web.require_admin def manage_datasets(self, trans, **kwd): def handle_error(**kwd): kwd['status'] = 'error' return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', **kwd)) params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') # When this method is called due to a grid operation, the sample ID # will be in the param 'id'. But when this method is called via a # redirect from another method, the ID will be in 'sample_id'. So, # check for 'id' if 'sample_id' is not provided. sample_id = params.get('sample_id', None) if sample_id is None: sample_id = params.get('id', None) try: sample = trans.sa_session.query(trans.model.Sample).get( trans.security.decode_id(sample_id)) except: return invalid_id_redirect(trans, 'requests_admin', sample_id, 'sample') if 'operation' in kwd: operation = kwd['operation'].lower() sample_dataset_id = params.get('id', None) if not sample_dataset_id: message = 'Select at least 1 dataset to %s.' % operation kwd['message'] = message del kwd['operation'] handle_error(**kwd) id_list = util.listify(sample_dataset_id) selected_sample_datasets = [] for sample_dataset_id in id_list: try: sample_dataset = trans.sa_session.query( trans.model.SampleDataset).get( trans.security.decode_id(sample_dataset_id)) except: return invalid_id_redirect(trans, 'requests_admin', sample_dataset_id, 'sample dataset') selected_sample_datasets.append(sample_dataset) if operation == "view": return trans.fill_template( '/admin/requests/view_sample_dataset.mako', cntrller='requests_admin', sample_dataset=selected_sample_datasets[0]) elif operation == "delete": not_deleted = [] for sample_dataset in selected_sample_datasets: # Make sure the dataset has been transferred before deleting it. if sample_dataset in sample_dataset.sample.untransferred_dataset_files: # Save the sample dataset sample = sample_dataset.sample trans.sa_session.delete(sample_dataset) trans.sa_session.flush() else: not_deleted.append(sample_dataset.name) message = '%i datasets have been deleted.' % (len(id_list) - len(not_deleted)) if not_deleted: status = 'warning' message = message + ' %s could not be deleted because their transfer status is not "Not Started". ' % str( not_deleted) return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id(sample.id), status=status, message=message)) elif operation == "rename": # If one of the selected sample datasets is in the NOT_STARTED state, # then display an error message. A NOT_STARTED state implies the dataset # has not yet been transferred. no_datasets_transferred = True for selected_sample_dataset in selected_sample_datasets: if selected_sample_dataset in selected_sample_dataset.sample.untransferred_dataset_files: no_datasets_transferred = False break if no_datasets_transferred: status = 'error' message = 'A dataset can be renamed only if it has been transferred.' return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id( selected_sample_datasets[0].sample.id), status=status, message=message)) return trans.fill_template( '/admin/requests/rename_datasets.mako', sample=selected_sample_datasets[0].sample, id_list=id_list) elif operation == "transfer": self.initiate_data_transfer( trans, trans.security.encode_id( selected_sample_datasets[0].sample.id), sample_datasets=selected_sample_datasets) elif operation == "view_external_service": return trans.response.send_redirect( web.url_for(controller='external_service', action='view_external_service', **kwd)) # Render the grid view request_id = trans.security.encode_id(sample.request.id) library_id = trans.security.encode_id(sample.library.id) self.datatx_grid.title = 'Manage "%s" datasets' % sample.name self.datatx_grid.global_actions = [ grids.GridAction( "Browse target data library", dict(controller='library_common', action='browse_library', cntrller='library_admin', id=library_id)), grids.GridAction( "Browse this request", dict(controller='requests_common', action='view_request', cntrller='requests_admin', id=request_id)) ] return self.datatx_grid(trans, **kwd) @web.expose @web.require_admin def rename_datasets(self, trans, **kwd): # This method is called from the DataTransferGrid when a user is renaming 1 or more # SampleDatasets. params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') sample_id = kwd.get('sample_id', None) try: sample = trans.sa_session.query(trans.model.Sample).get( trans.security.decode_id(sample_id)) except: return invalid_id_redirect(trans, 'requests_admin', sample_id, 'sample') # id_list is list of SampleDataset ids, which is a subset of all # of the SampleDatasets associated with the Sample. The user may # or may not have selected all of the SampleDatasets for renaming. id_list = util.listify(kwd.get('id_list', [])) # Get all of the SampleDatasets sample_datasets = [] for sample_dataset_id in id_list: sample_dataset = trans.sa_session.query( trans.app.model.SampleDataset).get( trans.security.decode_id(sample_dataset_id)) sample_datasets.append(sample_dataset) if params.get('rename_datasets_button', False): incorrect_dataset_names = [] for sample_dataset in sample_datasets: encoded_id = trans.security.encode_id(sample_dataset.id) selected_option = util.restore_text( params.get('rename_datasets_for_sample_%s' % encoded_id, '')) new_name = util.restore_text( params.get('new_name_%s' % encoded_id, '')) if not new_name: incorrect_dataset_names.append(sample_dataset.name) continue new_name = util.sanitize_for_filename(new_name) if selected_option == 'none': sample_dataset.name = new_name else: sample_dataset.name = '%s_%s' % (selected_option, new_name) trans.sa_session.add(sample_dataset) trans.sa_session.flush() if len(sample_datasets) == len(incorrect_dataset_names): status = 'error' message = 'All datasets renamed incorrectly.' elif len(incorrect_dataset_names): status = 'done' message = 'Changes saved successfully. The following datasets were renamed incorrectly: %s.' % str( incorrect_dataset_names) else: message = 'Changes saved successfully.' return trans.fill_template('/admin/requests/rename_datasets.mako', sample=sample, id_list=id_list, message=message, status=status) return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=sample_id)) @web.expose @web.require_admin def select_datasets_to_transfer(self, trans, **kwd): params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') request_id = kwd.get('request_id', None) external_service_id = kwd.get('external_service_id', None) request = trans.sa_session.query(trans.model.Request).get( trans.security.decode_id(request_id)) external_service = trans.sa_session.query( trans.model.ExternalService).get( trans.security.decode_id(external_service_id)) # Load the data transfer settings external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] selected_datasets_to_transfer = util.restore_text( params.get('selected_datasets_to_transfer', '')) if selected_datasets_to_transfer: selected_datasets_to_transfer = selected_datasets_to_transfer.split( ',') else: selected_datasets_to_transfer = [] sample_id = kwd.get('sample_id', 'none') sample_id_select_field = self.__build_sample_id_select_field( trans, request, sample_id) if sample_id != 'none': sample = trans.sa_session.query(trans.model.Sample).get( trans.security.decode_id(sample_id)) else: sample = None # The __get_files() method redirects here with a status of 'error' and a message if there # was a problem retrieving the files. if params.get('select_datasets_to_transfer_button', False): # Get the sample that was sequenced to produce these datasets. if sample_id == 'none': del kwd['select_datasets_to_transfer_button'] message = 'Select the sample that was sequenced to produce the datasets you want to transfer.' kwd['message'] = message kwd['status'] = 'error' return trans.response.send_redirect( web.url_for(controller='requests_admin', action='select_datasets_to_transfer', **kwd)) if not sample.library: # Display an error if a sample has been selected that # has not yet been associated with a destination library. message = 'Select a target data library and folder for the sample before selecting the datasets.' status = 'error' return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_samples', cntrller='requests_admin', id=trans.security.encode_id(request.id), status=status, message=message)) # Save the sample datasets sample_dataset_file_names = self.__create_sample_datasets( trans, sample, selected_datasets_to_transfer, external_service) if sample_dataset_file_names: message = 'Datasets (%s) have been selected for sample (%s)' % \ ( str( sample_dataset_file_names )[1:-1].replace( "'", "" ), sample.name ) return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', request_id=request_id, sample_id=sample_id, message=message, status=status)) return trans.fill_template( '/admin/requests/select_datasets_to_transfer.mako', cntrller='requests_admin', request=request, external_service=external_service, scp_configs=scp_configs, sample=sample, sample_id_select_field=sample_id_select_field, status=status, message=message) @web.json def get_file_details(self, trans, request_id, external_service_id, folder_path): def print_ticks(d): # pexpect timeout method pass # Avoid caching trans.response.headers['Pragma'] = 'no-cache' trans.response.headers['Expires'] = '0' if pexpect is None: return PEXPECT_IMPORT_MESSAGE external_service = trans.sa_session.query( trans.model.ExternalService).get( trans.security.decode_id(external_service_id)) external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] cmd = 'ssh %s@%s "ls -oghp \'%s\'"' % ( scp_configs['user_name'], scp_configs['host'], folder_path) # Handle the authentication message if ssh keys are not set - the message is # something like: "Are you sure you want to continue connecting (yes/no)." output = pexpect.run(cmd, events={ '\(yes\/no\)\.*': 'yes\r\n', '.ssword:*': scp_configs['password'] + '\r\n', pexpect.TIMEOUT: print_ticks }, timeout=10) for password_str in ['Password:\r\n', 'password:\r\n']: # Eliminate the output created using ssh from the tree if password_str in output: output = output.replace(password_str, '') return unicode(output.replace('\r\n', '<br/>')) @web.json def open_folder(self, trans, request_id, external_service_id, key): # Avoid caching trans.response.headers['Pragma'] = 'no-cache' trans.response.headers['Expires'] = '0' request = trans.sa_session.query(trans.model.Request).get( trans.security.decode_id(request_id)) external_service = trans.sa_session.query( trans.model.ExternalService).get( trans.security.decode_id(external_service_id)) folder_path = key files_list = self.__get_files(trans, request, external_service, folder_path) folder_contents = [] for filename in files_list: is_folder = False if filename and filename[-1] == os.sep: is_folder = True if filename: full_path = os.path.join(folder_path, filename) node = { "title": filename, "isFolder": is_folder, "isLazy": is_folder, "tooltip": full_path, "key": full_path } folder_contents.append(node) return folder_contents def __get_files(self, trans, request, external_service, folder_path): # Retrieves the filenames to be transferred from the remote host. ok = True external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] if not scp_configs['host'] or not scp_configs[ 'user_name'] or not scp_configs['password']: status = 'error' message = "Error in external service login information." ok = False def print_ticks(d): pass cmd = 'ssh %s@%s "ls -p \'%s\'"' % (scp_configs['user_name'], scp_configs['host'], folder_path) # Handle the authentication message if keys are not set - the message is # something like: "Are you sure you want to continue connecting (yes/no)." if pexpect is not None: output = pexpect.run(cmd, events={ '\(yes\/no\)\.*': 'yes\r\n', '.ssword:*': scp_configs['password'] + '\r\n', pexpect.TIMEOUT: print_ticks }, timeout=10) if 'No such file or directory' in output: status = 'error' message = "No folder named (%s) exists on the external service." % folder_path ok = False else: status = 'error' message = PEXPECT_IMPORT_MESSAGE ok = False if ok: if 'assword:' in output: # Eliminate the output created using ssh from the tree output_as_list = output.splitlines()[1:] else: output_as_list = output.splitlines() return output_as_list return trans.response.send_redirect( web.url_for(controller='requests_admin', action='select_datasets_to_transfer', request_id=trans.security.encode_id(request.id), external_service_id=trans.security.encode_id( external_service.id), status=status, message=message)) def __create_sample_datasets(self, trans, sample, selected_datasets_to_transfer, external_service): external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] sample_dataset_file_names = [] if selected_datasets_to_transfer: for filepath in selected_datasets_to_transfer: # FIXME: handle folder selection - ignore folders for now if filepath[-1] != os.sep: name = self.__rename_dataset(sample, filepath.split('/')[-1], scp_configs) status = trans.app.model.SampleDataset.transfer_status.NOT_STARTED size = sample.get_untransferred_dataset_size( filepath, scp_configs) sample_dataset = trans.model.SampleDataset( sample=sample, file_path=filepath, status=status, name=name, error_msg='', size=size, external_service=external_service) trans.sa_session.add(sample_dataset) trans.sa_session.flush() sample_dataset_file_names.append(str(sample_dataset.name)) return sample_dataset_file_names def __rename_dataset(self, sample, filepath, scp_configs): name = filepath.split('/')[-1] options = sample.request.type.rename_dataset_options option = scp_configs.get('rename_dataset', options.NO) if option == options.SAMPLE_NAME: new_name = sample.name + '_' + name if option == options.EXPERIMENT_AND_SAMPLE_NAME: new_name = sample.request.name + '_' + sample.name + '_' + name if option == options.EXPERIMENT_NAME: new_name = sample.request.name + '_' + name else: new_name = name return util.sanitize_for_filename(new_name) def __ensure_library_add_permission(self, trans, target_library, target_folder): """ Ensures the current admin user has ADD_LIBRARY permission on the target data library and folder. """ current_user_roles = trans.user.all_roles() current_user_private_role = trans.app.security_agent.get_private_user_role( trans.user) flush_needed = False if not trans.app.security_agent.can_add_library_item( current_user_roles, target_library): lp = trans.model.LibraryPermissions( trans.app.security_agent.permitted_actions.LIBRARY_ADD.action, target_library, current_user_private_role) trans.sa_session.add(lp) flush_needed = True if not trans.app.security_agent.can_add_library_item( current_user_roles, target_folder): lfp = trans.model.LibraryFolderPermissions( trans.app.security_agent.permitted_actions.LIBRARY_ADD.action, target_folder, current_user_private_role) trans.sa_session.add(lfp) flush_needed = True if flush_needed: trans.sa_session.flush() def __create_data_transfer_messages(self, trans, sample, selected_sample_datasets): """ Creates the xml messages to send to the rabbitmq server. It returns a dictionary of messages keyed by the external service used to transfer the datasets """ # Create the xml message based on the following template xml = \ ''' <data_transfer> <galaxy_host>%(GALAXY_HOST)s</galaxy_host> <api_key>%(API_KEY)s</api_key> <data_host>%(DATA_HOST)s</data_host> <data_user>%(DATA_USER)s</data_user> <data_password>%(DATA_PASSWORD)s</data_password> <request_id>%(REQUEST_ID)s</request_id> <sample_id>%(SAMPLE_ID)s</sample_id> <library_id>%(LIBRARY_ID)s</library_id> <folder_id>%(FOLDER_ID)s</folder_id> %(DATASETS)s </data_transfer>''' dataset_xml = \ '''<dataset> <dataset_id>%(ID)s</dataset_id> <name>%(NAME)s</name> <file>%(FILE)s</file> </dataset>''' # Here we group all the sample_datasets by the external service used to transfer them. # The idea is to bundle up the sample_datasets which uses the same external service and # send a single AMQP message to the galaxy_listener dataset_elements = {} for sample_dataset in selected_sample_datasets: external_service = sample_dataset.external_service if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.NOT_STARTED: if external_service not in dataset_elements: dataset_elements[external_service] = '' dataset_elements[external_service] += dataset_xml % dict( ID=str(sample_dataset.id), NAME=sample_dataset.name, FILE=sample_dataset.file_path) # update the dataset transfer status sample_dataset.status = trans.app.model.SampleDataset.transfer_status.IN_QUEUE trans.sa_session.add(sample_dataset) trans.sa_session.flush() # Finally prepend the external service info to the sets of sample datasets messages = [] for external_service, dataset_elem in dataset_elements.items(): external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] # Check data transfer settings err_msg = self.__validate_data_transfer_settings( trans, sample.request.type, scp_configs) if err_msg: return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id(sample.id), status='error', message=err_msg)) message = xml % dict(GALAXY_HOST=trans.request.host, API_KEY=trans.user.api_keys[0].key, DATA_HOST=scp_configs['host'], DATA_USER=scp_configs['user_name'], DATA_PASSWORD=scp_configs['password'], REQUEST_ID=str(sample.request.id), SAMPLE_ID=str(sample.id), LIBRARY_ID=str(sample.library.id), FOLDER_ID=str(sample.folder.id), DATASETS=dataset_elem) messages.append(message.replace('\n', '').replace('\r', '')) return messages def __validate_data_transfer_settings(self, trans, request_type, scp_configs): err_msg = '' # check the external service login info if not scp_configs.get( 'host', '' ) or \ not scp_configs.get( 'user_name', '' ) or \ not scp_configs.get( 'password', '' ): err_msg += "Error in external service login information. " if not trans.user.api_keys: err_msg += "Set your API Key in your User Preferences to transfer datasets. " # Check if library_import_dir is set if not trans.app.config.library_import_dir: err_msg = "'The library_import_dir' setting is not correctly set in the Galaxy config file. " # Check the RabbitMQ server settings in the config file for k, v in trans.app.config.amqp.items(): if not v: err_msg += 'Set RabbitMQ server settings in the "galaxy_amqp" section of the Galaxy config file, specifically "%s" is not set.' % k break return err_msg @web.expose @web.require_admin def initiate_data_transfer(self, trans, sample_id, sample_datasets=[], sample_dataset_id=''): # Initiate the transfer of the datasets from the external service to the target Galaxy data library. # The admin user must have LIBRARY_ADD permission for the target library and folder try: sample = trans.sa_session.query(trans.model.Sample).get( trans.security.decode_id(sample_id)) except: return invalid_id_redirect(trans, 'requests_admin', sample_id, 'sample') message = "" status = "done" # Make sure the current admin user has LIBRARY_ADD permission on the target data library and folder. self.__ensure_library_add_permission(trans, sample.library, sample.folder) if sample_dataset_id and not sample_datasets: # Either a list of SampleDataset objects or a comma-separated string of # encoded SampleDataset ids can be received. If the latter, parse the # sample_dataset_id string to build the list of sample_datasets. id_list = util.listify(sample_dataset_id) for sample_dataset_id in id_list: sample_dataset = trans.sa_session.query( trans.model.SampleDataset).get( trans.security.decode_id(sample_dataset_id)) sample_datasets.append(sample_dataset) if trans.app.config.enable_beta_job_managers: # For now, assume that all SampleDatasets use the same external service ( this may not be optimal ). if sample_datasets: external_service_type_id = sample_datasets[ 0].external_service.external_service_type_id # Here external_service_type_id will be something like '454_life_sciences' external_service = sample.request.type.get_external_service( external_service_type_id) external_service_type = external_service.get_external_service_type( trans) external_service.load_data_transfer_settings(trans) # For now only scp is supported. scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] if not scp_configs['automatic_transfer']: deferred_plugin = 'ManualDataTransferPlugin' else: raise Exception( "Automatic data transfer using scp is not yet supported." ) trans.app.job_manager.deferred_job_queue.plugins[ deferred_plugin].create_job( trans, sample=sample, sample_datasets=sample_datasets, external_service=external_service, external_service_type=external_service_type) else: # TODO: Using RabbitMq for now, but eliminate this entire block when we replace RabbitMq with Galaxy's # own messaging engine. We're holding off on using the new way to transfer files manually until we # implement a Galaxy-proprietary messaging engine because the deferred job plugins currently perform # constant db hits to check for deferred jobs that are not in a finished state. # Create the message messages = self.__create_data_transfer_messages( trans, sample, sample_datasets) # Send the messages for rmq_msg in messages: try: conn = amqp.Connection( host=trans.app.config.amqp['host'] + ":" + trans.app.config.amqp['port'], userid=trans.app.config.amqp['userid'], password=trans.app.config.amqp['password'], virtual_host=trans.app.config.amqp['virtual_host']) chan = conn.channel() msg = amqp.Message( rmq_msg, content_type='text/plain', application_headers={'msg_type': 'data_transfer'}) msg.properties["delivery_mode"] = 2 chan.basic_publish( msg, exchange=trans.app.config.amqp['exchange'], routing_key=trans.app.config.amqp['routing_key']) chan.close() conn.close() except Exception, e: message = "Error sending the data transfer message to the Galaxy AMQP message queue:<br/>%s" % str( e) status = "error" if not message: message = "%i datasets have been queued for transfer from the external service." % len( sample_datasets) status = "done" return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id(sample.id), message=message, status=status))
def manage_datasets( self, trans, **kwd ): def handle_error( **kwd ): kwd[ 'status' ] = 'error' return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', **kwd ) ) params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) # When this method is called due to a grid operation, the sample ID # will be in the param 'id'. But when this method is called via a # redirect from another method, the ID will be in 'sample_id'. So, # check for 'id' if 'sample_id' is not provided. sample_id = params.get( 'sample_id', None ) if sample_id is None: sample_id = params.get( 'id', None ) try: sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( sample_id ) ) except: return invalid_id_redirect( trans, 'requests_admin', sample_id, 'sample' ) if 'operation' in kwd: operation = kwd[ 'operation' ].lower() sample_dataset_id = params.get( 'id', None ) if not sample_dataset_id: message = 'Select at least 1 dataset to %s.' % operation kwd[ 'message' ] = message del kwd[ 'operation' ] handle_error( **kwd ) id_list = util.listify( sample_dataset_id ) selected_sample_datasets = [] for sample_dataset_id in id_list: try: sample_dataset = trans.sa_session.query( trans.model.SampleDataset ).get( trans.security.decode_id( sample_dataset_id ) ) except: return invalid_id_redirect( trans, 'requests_admin', sample_dataset_id, 'sample dataset' ) selected_sample_datasets.append( sample_dataset ) if operation == "view": return trans.fill_template( '/admin/requests/view_sample_dataset.mako', cntrller='requests_admin', sample_dataset=selected_sample_datasets[0] ) elif operation == "delete": not_deleted = [] for sample_dataset in selected_sample_datasets: # Make sure the dataset has been transferred before deleting it. if sample_dataset in sample_dataset.sample.untransferred_dataset_files: # Save the sample dataset sample = sample_dataset.sample trans.sa_session.delete( sample_dataset ) trans.sa_session.flush() else: not_deleted.append( sample_dataset.name ) message = '%i datasets have been deleted.' % ( len( id_list ) - len( not_deleted ) ) if not_deleted: status = 'warning' message = message + ' %s could not be deleted because their transfer status is not "Not Started". ' % str( not_deleted ) return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id( sample.id ), status=status, message=message ) ) elif operation == "rename": # If one of the selected sample datasets is in the NOT_STARTED state, # then display an error message. A NOT_STARTED state implies the dataset # has not yet been transferred. no_datasets_transferred = True for selected_sample_dataset in selected_sample_datasets: if selected_sample_dataset in selected_sample_dataset.sample.untransferred_dataset_files: no_datasets_transferred = False break if no_datasets_transferred: status = 'error' message = 'A dataset can be renamed only if it has been transferred.' return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id( selected_sample_datasets[0].sample.id ), status=status, message=message ) ) return trans.fill_template( '/admin/requests/rename_datasets.mako', sample=selected_sample_datasets[0].sample, id_list=id_list ) elif operation == "transfer": self.initiate_data_transfer( trans, trans.security.encode_id( selected_sample_datasets[0].sample.id ), sample_datasets=selected_sample_datasets ) elif operation == "view_external_service": return trans.response.send_redirect( web.url_for( controller='external_service', action='view_external_service', **kwd ) ) # Render the grid view request_id = trans.security.encode_id( sample.request.id ) library_id = trans.security.encode_id( sample.library.id ) self.datatx_grid.title = 'Manage "%s" datasets' % sample.name self.datatx_grid.global_actions = [ grids.GridAction( "Browse target data library", dict( controller='library_common', action='browse_library', cntrller='library_admin', id=library_id ) ), grids.GridAction( "Browse this request", dict( controller='requests_common', action='view_request', cntrller='requests_admin', id=request_id ) ) ] return self.datatx_grid( trans, **kwd )
def handle_error( **kwd ): kwd[ 'status' ] = 'error' return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', **kwd ) )
def select_datasets_to_transfer( self, trans, **kwd ): params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) request_id = kwd.get( 'request_id', None ) external_service_id = kwd.get( 'external_service_id', None ) request = trans.sa_session.query( trans.model.Request ).get( trans.security.decode_id( request_id ) ) external_service = trans.sa_session.query( trans.model.ExternalService ).get( trans.security.decode_id( external_service_id ) ) # Load the data transfer settings external_service.load_data_transfer_settings( trans ) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP ] selected_datasets_to_transfer = util.restore_text( params.get( 'selected_datasets_to_transfer', '' ) ) if selected_datasets_to_transfer: selected_datasets_to_transfer = selected_datasets_to_transfer.split(',') else: selected_datasets_to_transfer = [] sample_id = kwd.get( 'sample_id', 'none' ) sample_id_select_field = self.__build_sample_id_select_field( trans, request, sample_id ) if sample_id != 'none': sample = trans.sa_session.query( trans.model.Sample ).get( trans.security.decode_id( sample_id ) ) else: sample = None # The __get_files() method redirects here with a status of 'error' and a message if there # was a problem retrieving the files. if params.get( 'select_datasets_to_transfer_button', False ): # Get the sample that was sequenced to produce these datasets. if sample_id == 'none': del kwd[ 'select_datasets_to_transfer_button' ] message = 'Select the sample that was sequenced to produce the datasets you want to transfer.' kwd[ 'message' ] = message kwd[ 'status' ] = 'error' return trans.response.send_redirect( web.url_for( controller='requests_admin', action='select_datasets_to_transfer', **kwd ) ) if not sample.library: # Display an error if a sample has been selected that # has not yet been associated with a destination library. message = 'Select a target data library and folder for the sample before selecting the datasets.' status = 'error' return trans.response.send_redirect( web.url_for( controller='requests_common', action='edit_samples', cntrller='requests_admin', id=trans.security.encode_id( request.id ), status=status, message=message ) ) # Save the sample datasets sample_dataset_file_names = self.__create_sample_datasets( trans, sample, selected_datasets_to_transfer, external_service ) if sample_dataset_file_names: message = 'Datasets (%s) have been selected for sample (%s)' % \ ( str( sample_dataset_file_names )[1:-1].replace( "'", "" ), sample.name ) return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', request_id=request_id, sample_id=sample_id, message=message, status=status ) ) return trans.fill_template( '/admin/requests/select_datasets_to_transfer.mako', cntrller='requests_admin', request=request, external_service=external_service, scp_configs=scp_configs, sample=sample, sample_id_select_field=sample_id_select_field, status=status, message=message )
def browse_requests(self, trans, **kwd): if "operation" in kwd: operation = kwd["operation"].lower() if operation == "edit": return trans.response.send_redirect( web.url_for( controller="requests_common", action="edit_basic_request_info", cntrller="requests", **kwd ) ) if operation == "add_samples": return trans.response.send_redirect( web.url_for(controller="requests_common", action="add_samples", cntrller="requests", **kwd) ) if operation == "edit_samples": return trans.response.send_redirect( web.url_for(controller="requests_common", action="edit_samples", cntrller="requests", **kwd) ) if operation == "view_request": return trans.response.send_redirect( web.url_for(controller="requests_common", action="view_request", cntrller="requests", **kwd) ) if operation == "delete": return trans.response.send_redirect( web.url_for(controller="requests_common", action="delete_request", cntrller="requests", **kwd) ) if operation == "undelete": return trans.response.send_redirect( web.url_for(controller="requests_common", action="undelete_request", cntrller="requests", **kwd) ) if operation == "view_request_history": return trans.response.send_redirect( web.url_for(controller="requests_common", action="view_request_history", cntrller="requests", **kwd) ) # If there are requests that have been rejected, show a message as a reminder to the user rejected = 0 for request in ( trans.sa_session.query(trans.app.model.Request) .filter(trans.app.model.Request.table.c.deleted == false()) .filter(trans.app.model.Request.table.c.user_id == trans.user.id) ): if request.is_rejected: rejected = rejected + 1 if rejected: status = "warning" message = ( "%d requests (highlighted in red) were rejected. Click on the request name for details." % rejected ) kwd["status"] = status kwd["message"] = message # Allow the user to create a new request only if they have permission to access a request type. accessible_request_types = trans.app.security_agent.get_accessible_request_types(trans, trans.user) if accessible_request_types: self.request_grid.global_actions = [ grids.GridAction( "Create new request", dict(controller="requests_common", action="create_request", cntrller="requests"), ) ] else: self.request_grid.global_actions = [] # Render the list view return self.request_grid(trans, **kwd)
def browse_requests(self, trans, **kwd): if 'operation' in kwd: operation = kwd['operation'].lower() if operation == "edit": return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_basic_request_info', cntrller='requests', **kwd)) if operation == "add_samples": return trans.response.send_redirect( web.url_for(controller='requests_common', action='add_samples', cntrller='requests', **kwd)) if operation == "edit_samples": return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_samples', cntrller='requests', **kwd)) if operation == "view_request": return trans.response.send_redirect( web.url_for(controller='requests_common', action='view_request', cntrller='requests', **kwd)) if operation == "delete": return trans.response.send_redirect( web.url_for(controller='requests_common', action='delete_request', cntrller='requests', **kwd)) if operation == "undelete": return trans.response.send_redirect( web.url_for(controller='requests_common', action='undelete_request', cntrller='requests', **kwd)) if operation == "view_request_history": return trans.response.send_redirect( web.url_for(controller='requests_common', action='view_request_history', cntrller='requests', **kwd)) # If there are requests that have been rejected, show a message as a reminder to the user rejected = 0 for request in trans.sa_session.query( trans.app.model.Request ) \ .filter( trans.app.model.Request.table.c.deleted == false() ) \ .filter( trans.app.model.Request.table.c.user_id == trans.user.id ): if request.is_rejected: rejected = rejected + 1 if rejected: status = 'warning' message = "%d requests (highlighted in red) were rejected. Click on the request name for details." % rejected kwd['status'] = status kwd['message'] = message # Allow the user to create a new request only if they have permission to access a request type. accessible_request_types = trans.app.security_agent.get_accessible_request_types( trans, trans.user) if accessible_request_types: self.request_grid.global_actions = [ grids.GridAction( "Create new request", dict(controller='requests_common', action='create_request', cntrller='requests')) ] else: self.request_grid.global_actions = [] # Render the list view return self.request_grid(trans, **kwd)
def handle_error(**kwd): kwd['status'] = 'error' return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', **kwd))
def __create_data_transfer_messages( self, trans, sample, selected_sample_datasets ): """ Creates the xml messages to send to the rabbitmq server. It returns a dictionary of messages keyed by the external service used to transfer the datasets """ # Create the xml message based on the following template xml = \ ''' <data_transfer> <galaxy_host>%(GALAXY_HOST)s</galaxy_host> <api_key>%(API_KEY)s</api_key> <data_host>%(DATA_HOST)s</data_host> <data_user>%(DATA_USER)s</data_user> <data_password>%(DATA_PASSWORD)s</data_password> <request_id>%(REQUEST_ID)s</request_id> <sample_id>%(SAMPLE_ID)s</sample_id> <library_id>%(LIBRARY_ID)s</library_id> <folder_id>%(FOLDER_ID)s</folder_id> %(DATASETS)s </data_transfer>''' dataset_xml = \ '''<dataset> <dataset_id>%(ID)s</dataset_id> <name>%(NAME)s</name> <file>%(FILE)s</file> </dataset>''' # Here we group all the sample_datasets by the external service used to transfer them. # The idea is to bundle up the sample_datasets which uses the same external service and # send a single AMQP message to the galaxy_listener dataset_elements = {} for sample_dataset in selected_sample_datasets: external_service = sample_dataset.external_service if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.NOT_STARTED: if external_service not in dataset_elements: dataset_elements[ external_service ] = '' dataset_elements[ external_service ] += dataset_xml % dict( ID=str( sample_dataset.id ), NAME=sample_dataset.name, FILE=sample_dataset.file_path ) # update the dataset transfer status sample_dataset.status = trans.app.model.SampleDataset.transfer_status.IN_QUEUE trans.sa_session.add( sample_dataset ) trans.sa_session.flush() # Finally prepend the external service info to the sets of sample datasets messages = [] for external_service, dataset_elem in dataset_elements.items(): external_service.load_data_transfer_settings( trans ) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP ] # Check data transfer settings err_msg = self.__validate_data_transfer_settings( trans, sample.request.type, scp_configs ) if err_msg: return trans.response.send_redirect( web.url_for( controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id( sample.id ), status='error', message=err_msg ) ) message = xml % dict( GALAXY_HOST=trans.request.host, API_KEY=trans.user.api_keys[0].key, DATA_HOST=scp_configs[ 'host' ], DATA_USER=scp_configs[ 'user_name' ], DATA_PASSWORD=scp_configs[ 'password' ], REQUEST_ID=str( sample.request.id ), SAMPLE_ID=str( sample.id ), LIBRARY_ID=str( sample.library.id ), FOLDER_ID=str( sample.folder.id ), DATASETS=dataset_elem ) messages.append( message.replace( '\n', '' ).replace( '\r', '' ) ) return messages
def __save_request_type(self, trans, action, **kwd): # Here we save a newly created request_type or save changed # attributes of an existing request_type. params = util.Params(kwd) request_type_id = params.get('id', None) name = util.restore_text(params.get('name', '')) desc = util.restore_text(params.get('desc', '')) request_form_id = params.get('request_form_id', 'none') sample_form_id = params.get('sample_form_id', 'none') # validate if not name or request_form_id == 'none' or sample_form_id == 'none': message = 'Enter the name, request form, sample form and at least one sample state associated with this request type.' return trans.response.send_redirect( web.url_for(controller='request_type', action=action, message=message, status='error')) try: request_form = trans.sa_session.query( trans.model.FormDefinition).get( trans.security.decode_id(request_form_id)) except: return invalid_id_redirect(trans, 'request_type', request_type_id, 'form definition', action='browse_request_types') try: sample_form = trans.sa_session.query( trans.model.FormDefinition).get( trans.security.decode_id(sample_form_id)) except: return invalid_id_redirect(trans, 'request_type', request_type_id, 'form definition', action='browse_request_types') if request_type_id: # We're saving changed attributes of an existing request_type. request_type = trans.sa_session.query(trans.model.RequestType).get( trans.security.decode_id(request_type_id)) request_type.name = name request_type.desc = desc request_type.request_form = request_form request_type.sample_form = sample_form for sample_state in request_type.states: sample_state_id = trans.security.encode_id(sample_state.id) name = util.restore_text( params.get('state_name_%s' % sample_state_id, '')) desc = util.restore_text( params.get('state_desc_%s' % sample_state_id, '')) sample_state.name = name sample_state.desc = desc trans.sa_session.add(sample_state) trans.sa_session.flush() trans.sa_session.add(request_type) trans.sa_session.flush() else: # We're saving a newly created request_type request_type = trans.model.RequestType(name=name, desc=desc, request_form=request_form, sample_form=sample_form) trans.sa_session.add(request_type) trans.sa_session.flush() i = 0 while True: if 'state_name_%i' % i in kwd: name = util.restore_text( params.get('state_name_%i' % i, '')) desc = util.restore_text( params.get('state_desc_%i' % i, '')) sample_state = trans.model.SampleState( name, desc, request_type) trans.sa_session.add(sample_state) trans.sa_session.flush() i += 1 else: break # delete existing associations request_type.delete_external_service_associations(trans) # save the external services associated with this request_type external_services_list = self.__get_external_services(trans, **kwd) for external_service in external_services_list: request_type.add_external_service_association( trans, external_service) return request_type
def edit_form_definition(self, trans, response_redirect=None, **kwd): ''' This callback method is for handling form editing. The value of response_redirect should be an URL that is defined by the caller. This allows for redirecting as desired when the form changes have been saved. For an example of how this works, see the edit_template() method in the base controller. ''' params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') try: form_definition_current = trans.sa_session.query( trans.app.model.FormDefinitionCurrent).get( trans.security.decode_id(kwd['id'])) except: return trans.response.send_redirect( web.url_for(controller='forms', action='browse_form_definitions', message='Invalid form', status='error')) form_definition = form_definition_current.latest_form # TODO: eliminate the need for this refresh param. if params.get('refresh', False): # Refresh current_form = self.get_current_form(trans, **kwd) else: # Show the saved form for editing current_form = self.get_saved_form(form_definition) # Save changes if params.get('save_changes_button', False): new_form_definition, message = self.save_form_definition( trans, form_definition_current_id=form_definition. form_definition_current.id, **kwd) # if validation error encountered while saving the form, show the # unsaved form, with the error message if not new_form_definition: status = 'error' else: # everything went fine. form saved successfully. Show the saved form or redirect # to response_redirect if appropriate. if response_redirect: return trans.response.send_redirect(response_redirect) form_definition = new_form_definition current_form = self.get_saved_form(form_definition) message = "The form '%s' has been updated with the changes." % form_definition.name # Add a layout grid elif params.get('add_layout_grid_button', False): current_form['layout'].append('') # Delete a layout grid elif params.get('remove_layout_grid_button', False): index = int(kwd['remove_layout_grid_button'].split(' ')[2]) - 1 del current_form['layout'][index] # Add a field elif params.get('add_field_button', False): field_index = len(current_form['fields']) + 1 self.empty_field['name'] = '%i_field_name' % field_index self.empty_field['label'] = 'Field label %i' % field_index current_form['fields'].append(self.empty_field) # Delete a field elif params.get('remove_button', False): # find the index of the field to be removed from the remove button label index = int(kwd['remove_button'].split(' ')[2]) - 1 del current_form['fields'][index] # Add SelectField option elif 'Add' in kwd.values(): current_form, status, message = self.__add_select_field_option( trans=trans, current_form=current_form, **kwd) # Remove SelectField option elif 'Remove' in kwd.values(): current_form, status, message = self.__remove_select_field_option( trans=trans, current_form=current_form, **kwd) return self.show_editable_form_definition( trans=trans, form_definition=form_definition, current_form=current_form, message=message, status=status, response_redirect=response_redirect, **kwd)
def select_datasets_to_transfer(self, trans, **kwd): params = util.Params(kwd) message = util.restore_text(params.get('message', '')) status = params.get('status', 'done') request_id = kwd.get('request_id', None) external_service_id = kwd.get('external_service_id', None) request = trans.sa_session.query(trans.model.Request).get( trans.security.decode_id(request_id)) external_service = trans.sa_session.query( trans.model.ExternalService).get( trans.security.decode_id(external_service_id)) # Load the data transfer settings external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] selected_datasets_to_transfer = util.restore_text( params.get('selected_datasets_to_transfer', '')) if selected_datasets_to_transfer: selected_datasets_to_transfer = selected_datasets_to_transfer.split( ',') else: selected_datasets_to_transfer = [] sample_id = kwd.get('sample_id', 'none') sample_id_select_field = self.__build_sample_id_select_field( trans, request, sample_id) if sample_id != 'none': sample = trans.sa_session.query(trans.model.Sample).get( trans.security.decode_id(sample_id)) else: sample = None # The __get_files() method redirects here with a status of 'error' and a message if there # was a problem retrieving the files. if params.get('select_datasets_to_transfer_button', False): # Get the sample that was sequenced to produce these datasets. if sample_id == 'none': del kwd['select_datasets_to_transfer_button'] message = 'Select the sample that was sequenced to produce the datasets you want to transfer.' kwd['message'] = message kwd['status'] = 'error' return trans.response.send_redirect( web.url_for(controller='requests_admin', action='select_datasets_to_transfer', **kwd)) if not sample.library: # Display an error if a sample has been selected that # has not yet been associated with a destination library. message = 'Select a target data library and folder for the sample before selecting the datasets.' status = 'error' return trans.response.send_redirect( web.url_for(controller='requests_common', action='edit_samples', cntrller='requests_admin', id=trans.security.encode_id(request.id), status=status, message=message)) # Save the sample datasets sample_dataset_file_names = self.__create_sample_datasets( trans, sample, selected_datasets_to_transfer, external_service) if sample_dataset_file_names: message = 'Datasets (%s) have been selected for sample (%s)' % \ ( str( sample_dataset_file_names )[1:-1].replace( "'", "" ), sample.name ) return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', request_id=request_id, sample_id=sample_id, message=message, status=status)) return trans.fill_template( '/admin/requests/select_datasets_to_transfer.mako', cntrller='requests_admin', request=request, external_service=external_service, scp_configs=scp_configs, sample=sample, sample_id_select_field=sample_id_select_field, status=status, message=message)
def __save_request_type(self, trans, action, **kwd): # Here we save a newly created request_type or save changed # attributes of an existing request_type. params = util.Params(kwd) request_type_id = params.get('id', None) name = util.restore_text(params.get('name', '')) desc = util.restore_text(params.get('desc', '')) request_form_id = params.get('request_form_id', 'none') sample_form_id = params.get('sample_form_id', 'none') # validate if not name or request_form_id == 'none' or sample_form_id == 'none': message = 'Enter the name, request form, sample form and at least one sample state associated with this request type.' return trans.response.send_redirect(web.url_for(controller='request_type', action=action, message=message, status='error')) try: request_form = trans.sa_session.query(trans.model.FormDefinition).get(trans.security.decode_id(request_form_id)) except: return invalid_id_redirect(trans, 'request_type', request_type_id, 'form definition', action='browse_request_types') try: sample_form = trans.sa_session.query(trans.model.FormDefinition).get(trans.security.decode_id(sample_form_id)) except: return invalid_id_redirect(trans, 'request_type', request_type_id, 'form definition', action='browse_request_types') if request_type_id: # We're saving changed attributes of an existing request_type. request_type = trans.sa_session.query(trans.model.RequestType).get(trans.security.decode_id(request_type_id)) request_type.name = name request_type.desc = desc request_type.request_form = request_form request_type.sample_form = sample_form for sample_state in request_type.states: sample_state_id = trans.security.encode_id(sample_state.id) name = util.restore_text(params.get('state_name_%s' % sample_state_id, '')) desc = util.restore_text(params.get('state_desc_%s' % sample_state_id, '')) sample_state.name = name sample_state.desc = desc trans.sa_session.add(sample_state) trans.sa_session.flush() trans.sa_session.add(request_type) trans.sa_session.flush() else: # We're saving a newly created request_type request_type = trans.model.RequestType(name=name, desc=desc, request_form=request_form, sample_form=sample_form) trans.sa_session.add(request_type) trans.sa_session.flush() i = 0 while True: if 'state_name_%i' % i in kwd: name = util.restore_text(params.get('state_name_%i' % i, '')) desc = util.restore_text(params.get('state_desc_%i' % i, '')) sample_state = trans.model.SampleState(name, desc, request_type) trans.sa_session.add(sample_state) trans.sa_session.flush() i += 1 else: break # delete existing associations request_type.delete_external_service_associations(trans) # save the external services associated with this request_type external_services_list = self.__get_external_services(trans, **kwd) for external_service in external_services_list: request_type.add_external_service_association(trans, external_service) return request_type
def __create_data_transfer_messages(self, trans, sample, selected_sample_datasets): """ Creates the xml messages to send to the rabbitmq server. It returns a dictionary of messages keyed by the external service used to transfer the datasets """ # Create the xml message based on the following template xml = \ ''' <data_transfer> <galaxy_host>%(GALAXY_HOST)s</galaxy_host> <api_key>%(API_KEY)s</api_key> <data_host>%(DATA_HOST)s</data_host> <data_user>%(DATA_USER)s</data_user> <data_password>%(DATA_PASSWORD)s</data_password> <request_id>%(REQUEST_ID)s</request_id> <sample_id>%(SAMPLE_ID)s</sample_id> <library_id>%(LIBRARY_ID)s</library_id> <folder_id>%(FOLDER_ID)s</folder_id> %(DATASETS)s </data_transfer>''' dataset_xml = \ '''<dataset> <dataset_id>%(ID)s</dataset_id> <name>%(NAME)s</name> <file>%(FILE)s</file> </dataset>''' # Here we group all the sample_datasets by the external service used to transfer them. # The idea is to bundle up the sample_datasets which uses the same external service and # send a single AMQP message to the galaxy_listener dataset_elements = {} for sample_dataset in selected_sample_datasets: external_service = sample_dataset.external_service if sample_dataset.status == trans.app.model.SampleDataset.transfer_status.NOT_STARTED: if external_service not in dataset_elements: dataset_elements[external_service] = '' dataset_elements[external_service] += dataset_xml % dict( ID=str(sample_dataset.id), NAME=sample_dataset.name, FILE=sample_dataset.file_path) # update the dataset transfer status sample_dataset.status = trans.app.model.SampleDataset.transfer_status.IN_QUEUE trans.sa_session.add(sample_dataset) trans.sa_session.flush() # Finally prepend the external service info to the sets of sample datasets messages = [] for external_service, dataset_elem in dataset_elements.items(): external_service.load_data_transfer_settings(trans) scp_configs = external_service.data_transfer[ trans.model.ExternalService.data_transfer_protocol.SCP] # Check data transfer settings err_msg = self.__validate_data_transfer_settings( trans, sample.request.type, scp_configs) if err_msg: return trans.response.send_redirect( web.url_for(controller='requests_admin', action='manage_datasets', sample_id=trans.security.encode_id(sample.id), status='error', message=err_msg)) message = xml % dict(GALAXY_HOST=trans.request.host, API_KEY=trans.user.api_keys[0].key, DATA_HOST=scp_configs['host'], DATA_USER=scp_configs['user_name'], DATA_PASSWORD=scp_configs['password'], REQUEST_ID=str(sample.request.id), SAMPLE_ID=str(sample.id), LIBRARY_ID=str(sample.library.id), FOLDER_ID=str(sample.folder.id), DATASETS=dataset_elem) messages.append(message.replace('\n', '').replace('\r', '')) return messages
def edit_form_definition( self, trans, response_redirect=None, **kwd ): ''' This callback method is for handling form editing. The value of response_redirect should be an URL that is defined by the caller. This allows for redirecting as desired when the form changes have been saved. For an example of how this works, see the edit_template() method in the base controller. ''' params = util.Params( kwd ) message = util.restore_text( params.get( 'message', '' ) ) status = params.get( 'status', 'done' ) try: form_definition_current = trans.sa_session.query( trans.app.model.FormDefinitionCurrent ).get( trans.security.decode_id(kwd['id']) ) except: return trans.response.send_redirect( web.url_for( controller='forms', action='browse_form_definitions', message='Invalid form', status='error' ) ) form_definition = form_definition_current.latest_form # TODO: eliminate the need for this refresh param. if params.get( 'refresh', False ): # Refresh current_form = self.get_current_form( trans, **kwd ) else: # Show the saved form for editing current_form = self.get_saved_form( form_definition ) # Save changes if params.get( 'save_changes_button', False ): new_form_definition, message = self.save_form_definition( trans, form_definition_current_id=form_definition.form_definition_current.id, **kwd ) # if validation error encountered while saving the form, show the # unsaved form, with the error message if not new_form_definition: status = 'error' else: # everything went fine. form saved successfully. Show the saved form or redirect # to response_redirect if appropriate. if response_redirect: return trans.response.send_redirect( response_redirect ) form_definition = new_form_definition current_form = self.get_saved_form( form_definition ) message = "The form '%s' has been updated with the changes." % form_definition.name # Add a layout grid elif params.get( 'add_layout_grid_button', False ): current_form[ 'layout' ].append( '' ) # Delete a layout grid elif params.get( 'remove_layout_grid_button', False ): index = int( kwd[ 'remove_layout_grid_button' ].split( ' ' )[2] ) - 1 del current_form[ 'layout' ][index] # Add a field elif params.get( 'add_field_button', False ): field_index = len( current_form[ 'fields' ] ) + 1 self.empty_field[ 'name' ] = '%i_field_name' % field_index self.empty_field[ 'label' ] = 'Field label %i' % field_index current_form[ 'fields' ].append( self.empty_field ) # Delete a field elif params.get( 'remove_button', False ): # find the index of the field to be removed from the remove button label index = int( kwd[ 'remove_button' ].split( ' ' )[2] ) - 1 del current_form[ 'fields' ][ index ] # Add SelectField option elif 'Add' in kwd.values(): current_form, status, message = self.__add_select_field_option( trans=trans, current_form=current_form, **kwd) # Remove SelectField option elif 'Remove' in kwd.values(): current_form, status, message = self.__remove_select_field_option( trans=trans, current_form=current_form, **kwd) return self.show_editable_form_definition( trans=trans, form_definition=form_definition, current_form=current_form, message=message, status=status, response_redirect=response_redirect, **kwd )