Allow reloading External Display applications without restarting Galaxy.

This commit is contained in:
Daniel Blankenberg
2015-02-04 16:12:03 -05:00
parent 0bcfe09fa2
commit 0ed4ee779b
5 changed files with 127 additions and 12 deletions
@@ -167,23 +167,21 @@ class PopulatedDisplayApplicationLink( object ):
class DisplayApplication( object ):
@classmethod
def from_file( cls, filename, datatypes_registry ):
return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry )
return cls.from_elem( parse_xml( filename ).getroot(), datatypes_registry, filename=filename )
@classmethod
def from_elem( cls, elem, datatypes_registry ):
def from_elem( cls, elem, datatypes_registry, filename=None ):
att_dict = cls._get_attributes_from_elem( elem )
rval = DisplayApplication( att_dict['id'], att_dict['name'], datatypes_registry, att_dict['version'], filename=filename, elem=elem )
rval._load_links_from_elem( elem )
return rval
@classmethod
def _get_attributes_from_elem( cls, elem ):
display_id = elem.get( 'id', None )
assert display_id, "ID tag is required for a Display Application"
name = elem.get( 'name', display_id )
version = elem.get( 'version', None )
rval = DisplayApplication( display_id, name, datatypes_registry, version )
for link_elem in elem.findall( 'link' ):
link = DisplayApplicationLink.from_elem( link_elem, rval )
if link:
rval.links[ link.id ] = link
for dynamic_links in elem.findall( 'dynamic_links' ):
for link in DynamicDisplayApplicationBuilder( dynamic_links, rval, datatypes_registry.build_sites ):
rval.links[ link.id ] = link
return rval
def __init__( self, display_id, name, datatypes_registry, version = None ):
return dict( id=display_id, name=name, version=version )
def __init__( self, display_id, name, datatypes_registry, version = None, filename=None, elem=None ):
self.id = display_id
self.name = name
self.datatypes_registry = datatypes_registry
@@ -191,6 +189,16 @@ class DisplayApplication( object ):
version = "1.0.0"
self.version = version
self.links = odict()
self._filename = filename
self._elem = elem
def _load_links_from_elem( self, elem ):
for link_elem in elem.findall( 'link' ):
link = DisplayApplicationLink.from_elem( link_elem, self )
if link:
self.links[ link.id ] = link
for dynamic_links in elem.findall( 'dynamic_links' ):
for link in DynamicDisplayApplicationBuilder( dynamic_links, self, self.datatypes_registry.build_sites ):
self.links[ link.id ] = link
def get_link( self, link_name, data, dataset_hash, user_hash, trans, app_kwds ):
#returns a link object with data knowledge to generate links
return PopulatedDisplayApplicationLink( self.links[ link_name ], data, dataset_hash, user_hash, trans, app_kwds )
@@ -200,3 +208,23 @@ class DisplayApplication( object ):
if link_value.filter_by_dataset( data, trans ):
filtered.links[link_name] = link_value
return filtered
def reload( self ):
if self._filename:
elem = parse_xml( self._filename ).getroot()
elif self._elem:
elem = self._elem
else:
raise Exception( "Unable to reload DisplayApplication %s." % ( self.name ) )
# All toolshed-specific attributes added by e.g the registry will remain
attr_dict = self._get_attributes_from_elem( elem )
# We will not allow changing the id at this time (we'll need to fix several mappings upstream to handle this case)
assert attr_dict.get( 'id' ) == self.id, ValueError( "You cannot reload a Display application where the ID has changed. You will need to restart the server instead." )
# clear old links
for key in self.links.keys():
del self.links[key]
# Set new attributes
for key, value in attr_dict.iteritems():
setattr( self, key, value )
# Load new links
self._load_links_from_elem( elem )
return self
+20
View File
@@ -621,6 +621,26 @@ class Registry( object ):
self.log.debug( "Adding inherited display application '%s' to datatype '%s'" % ( display_app.id, extension ) )
d_type1.add_display_application( display_app )
def reload_display_applications( self, display_application_ids=None ):
"""
Reloads display applications: by id, or all if no ids provided
Returns tuple( [reloaded_ids], [failed_ids] )
"""
if not display_application_ids:
display_application_ids = self.display_applications.keys()
elif not isinstance( display_application_ids, list ):
display_application_ids = [ display_application_ids ]
reloaded = []
failed = []
for display_application_id in display_application_ids:
try:
self.display_applications[ display_application_id ].reload()
reloaded.append( display_application_id )
except Exception, e:
self.log.debug( 'Requested to reload display application "%s", but failed: %s.', display_application_id, e )
failed.append( display_application_id )
return ( reloaded, failed )
def load_external_metadata_tool( self, toolbox ):
"""Adds a tool which is used to set external metadata"""
# We need to be able to add a job to the queue to set metadata. The queue will currently only accept jobs with an associated
@@ -883,3 +883,21 @@ class AdminGalaxy( BaseUIController, Admin, AdminActions, UsesQuotaMixin, QuotaP
message = escape( galaxy.util.restore_text( kwd.get( 'message', '' ) ) )
status = galaxy.util.restore_text( kwd.get( 'status', 'done' ) )
return trans.fill_template( 'admin/view_data_tables_registry.mako', message=message, status=status )
@web.expose
@web.require_admin
def display_applications( self, trans, **kwd ):
return trans.fill_template( 'admin/view_display_applications.mako', display_applications=trans.app.datatypes_registry.display_applications )
@web.expose
@web.require_admin
def reload_display_application( self, trans, **kwd ):
reloaded, failed = trans.app.datatypes_registry.reload_display_applications( kwd.get( 'id' ) )
if not reloaded and failed:
return trans.show_error_message( 'Unable to reload any of the %i requested display applications ("%s").' % ( len( failed ), '", "'.join( failed ) ) )
if failed:
return trans.show_warn_message( 'Reloaded %i display applications ("%s"), but failed to reload %i display applications ("%s").'
% ( len( reloaded ), '", "'.join( reloaded ), len( failed ), '", "'.join( failed ) ) )
if not reloaded:
return trans.show_warn_message( 'You need to request at least one display application to reload.' )
return trans.show_ok_message( 'Reloaded %i requested display applications ("%s").' % ( len( reloaded ), '", "'.join( reloaded ) ) )
@@ -75,6 +75,7 @@
<div class="toolSectionBg">
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='view_datatypes_registry' )}" target="galaxy_main">View data types registry</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='view_tool_data_tables' )}" target="galaxy_main">View data tables registry</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='display_applications' )}" target="galaxy_main">View display applications</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='tool_versions' )}" target="galaxy_main">View tool lineage</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='package_tool' )}" target="galaxy_main">Download tool tarball</a></div>
<div class="toolTitle"><a href="${h.url_for( controller='admin', action='reload_tool' )}" target="galaxy_main">Reload a tool's configuration</a></div>
@@ -0,0 +1,48 @@
<%inherit file="/base.mako"/>
<%namespace file="/message.mako" import="render_msg" />
%if message:
${render_msg( message, status )}
%endif
<div class="toolForm">
<div class="toolFormTitle">There are currently ${len( display_applications )} <a class="icon-btn" href="${ h.url_for( controller='admin', action='reload_display_application' ) }" title="Reload all display applications" data-placement="bottom">
<span class="fa fa-refresh"></span>
</a> display applications loaded.</div>
<div class="toolFormBody">
<table class="manage-table colored" border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<th bgcolor="#D8D8D8">Reload</th>
<th bgcolor="#D8D8D8">Name</th>
<th bgcolor="#D8D8D8">ID</th>
<th bgcolor="#D8D8D8">Version</th>
<th bgcolor="#D8D8D8">Links</th>
<th bgcolor="#D8D8D8">Filename</th>
</tr>
<% ctr = 0 %>
%for display_app in display_applications.values():
%if ctr % 2 == 1:
<tr class="odd_row">
%else:
<tr class="tr">
%endif
<td>
<a class="icon-btn" href="${ h.url_for( controller='admin', action='reload_display_application', id=display_app.id ) }" title="Reload ${ display_app.name | h } display application" data-placement="bottom">
<span class="fa fa-refresh"></span>
</a>
</td>
<td>${ display_app.name | h }</td>
<td>${ display_app.id | h }</td>
<td>${ display_app.version | h }</td>
<td><ul>
%for link in display_app.links.values():
<li>${ link.name | h }</li>
%endfor
</ul></td>
<td>${ display_app._filename | h }</td>
</tr>
<% ctr += 1 %>
%endfor
</table>
</div>
</div>