def sync_database_with_file_system(self, app, tool_shed_repository, tool_dependency_name, tool_dependency_version, tool_dependency_install_dir, tool_dependency_type='package'): """ The installation directory defined by the received tool_dependency_install_dir exists, so check for the presence of INSTALLATION_LOG. If the files exists, we'll assume the tool dependency is installed, but not necessarily successfully (it could be in an error state on disk. However, we can justifiably assume here that no matter the state, an associated database record will exist. """ # This method should be reached very rarely. It implies that either the Galaxy environment # became corrupted (i.e., the database records for installed tool dependencies is not synchronized # with tool dependencies on disk) or the Tool Shed's install and test framework is running. The Tool # Shed's install and test framework installs repositories in 2 stages, those of type tool_dependency_definition # followed by those containing valid tools and tool functional test components. log.debug("Synchronizing the database with the file system...") try: log.debug( "The value of app.config.running_functional_tests is: %s" % str(app.config.running_functional_tests)) except Exception: pass sa_session = app.install_model.context can_install_tool_dependency = False tool_dependency = \ tool_dependency_util.get_tool_dependency_by_name_version_type_repository(app, tool_shed_repository, tool_dependency_name, tool_dependency_version, tool_dependency_type) if tool_dependency.status == app.install_model.ToolDependency.installation_status.INSTALLING: # The tool dependency is in an Installing state, so we don't want to do anything to it. If the tool # dependency is being installed by someone else, we don't want to interfere with that. This assumes # the installation by "someone else" is not hung in an Installing state, which is a weakness if that # "someone else" never repaired it. log.debug( 'Skipping installation of tool dependency %s version %s because it has a status of %s' % (str(tool_dependency.name), str( tool_dependency.version), str(tool_dependency.status))) else: # We have a pre-existing installation directory on the file system, but our associated database record is # in a state that allowed us to arrive here. At this point, we'll inspect the installation directory to # see if we have a "proper installation" and if so, synchronize the database record rather than reinstalling # the dependency if we're "running_functional_tests". If we're not "running_functional_tests, we'll set # the tool dependency's installation status to ERROR. tool_dependency_installation_directory_contents = os.listdir( tool_dependency_install_dir) if INSTALLATION_LOG in tool_dependency_installation_directory_contents: # Since this tool dependency's installation directory contains an installation log, we consider it to be # installed. In some cases the record may be missing from the database due to some activity outside of # the control of the Tool Shed. Since a new record was created for it and we don't know the state of the # files on disk, we will set it to an error state (unless we are running Tool Shed functional tests - see # below). log.debug( 'Skipping installation of tool dependency %s version %s because it is installed in %s' % (str(tool_dependency.name), str(tool_dependency.version), str(tool_dependency_install_dir))) if app.config.running_functional_tests: # If we are running functional tests, the state will be set to Installed because previously compiled # tool dependencies are not deleted by default, from the "install and test" framework.. tool_dependency.status = app.install_model.ToolDependency.installation_status.INSTALLED else: error_message = 'The installation directory for this tool dependency had contents but the database had no record. ' error_message += 'The installation log may show this tool dependency to be correctly installed, but due to the ' error_message += 'missing database record it is now being set to Error.' tool_dependency.status = app.install_model.ToolDependency.installation_status.ERROR tool_dependency.error_message = error_message else: error_message = '\nInstallation path %s for tool dependency %s version %s exists, but the expected file %s' % \ (str(tool_dependency_install_dir), str(tool_dependency_name), str(tool_dependency_version), str(INSTALLATION_LOG)) error_message += ' is missing. This indicates an installation error so the tool dependency is being' error_message += ' prepared for re-installation.' log.error(error_message) tool_dependency.status = app.install_model.ToolDependency.installation_status.NEVER_INSTALLED remove_dir(tool_dependency_install_dir) can_install_tool_dependency = True sa_session.add(tool_dependency) sa_session.flush() try: log.debug( "Returning from sync_database_with_file_system with tool_dependency %s, can_install_tool_dependency %s." % (str(tool_dependency.name), str(can_install_tool_dependency))) except Exception as e: log.debug(str(e)) return tool_dependency, can_install_tool_dependency
def create_tool_dependency_with_initialized_env_sh_file( self, dependent_install_dir, tool_shed_repository, required_repository, package_name, package_version, tool_dependencies_config): """ Create or get a tool_dependency record that is defined by the received package_name and package_version. An env.sh file will be created for the tool_dependency in the received dependent_install_dir. """ # The received required_repository refers to a tool_shed_repository record that is defined as a complex # repository dependency for this tool_dependency. The required_repository may or may not be currently # installed (it doesn't matter). If it is installed, it is associated with a tool_dependency that has # an env.sh file that this new tool_dependency must be able to locate and "source". If it is not installed, # we can still determine where that env.sh file will be, so we'll initialize this new tool_dependency's env.sh # file in either case. If the required repository ends up with an installation error, this new tool # dependency will still be fine because its containing repository will be defined as missing dependencies. tool_dependencies = [] if not os.path.exists(dependent_install_dir): os.makedirs(dependent_install_dir) required_tool_dependency_env_file_path = None if tool_dependencies_config: required_td_tree, error_message = parse_xml( tool_dependencies_config) if required_td_tree: required_td_root = required_td_tree.getroot() for required_td_elem in required_td_root: # Find the appropriate package name and version. if required_td_elem.tag == 'package': # <package name="bwa" version="0.5.9"> required_td_package_name = required_td_elem.get( 'name', None) required_td_package_version = required_td_elem.get( 'version', None) # Check the database to see if we have a record for the required tool dependency (we may not which is ok). If we # find a record, we need to see if it is in an error state and if so handle it appropriately. required_tool_dependency = \ tool_dependency_util.get_tool_dependency_by_name_version_type_repository(self.app, required_repository, required_td_package_name, required_td_package_version, 'package') if required_td_package_name == package_name and required_td_package_version == package_version: # Get or create a database tool_dependency record with which the installed package on disk will be associated. tool_dependency = \ tool_dependency_util.create_or_update_tool_dependency(app=self.app, tool_shed_repository=tool_shed_repository, name=package_name, version=package_version, type='package', status=self.app.install_model.ToolDependency.installation_status.NEVER_INSTALLED, set_status=True) # Create an env.sh file for the tool_dependency whose first line will source the env.sh file located in # the path defined by required_tool_dependency_env_file_path. It doesn't matter if the required env.sh # file currently exists.. required_tool_dependency_env_file_path = \ self.get_required_repository_package_env_sh_path(package_name, package_version, required_repository) env_file_builder = EnvFileBuilder( tool_dependency.installation_directory( self.app)) env_file_builder.append_line( action="source", value=required_tool_dependency_env_file_path) return_code = env_file_builder.return_code if return_code: error_message = 'Error defining env.sh file for package %s, return_code: %s' % \ (str(package_name), str(return_code)) tool_dependency = \ tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency=tool_dependency, status=self.app.install_model.ToolDependency.installation_status.ERROR, error_message=error_message) elif required_tool_dependency is not None and required_tool_dependency.in_error_state: error_message = "This tool dependency's required tool dependency %s version %s has status %s." % \ (str(required_tool_dependency.name), str(required_tool_dependency.version), str(required_tool_dependency.status)) tool_dependency = \ tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency=tool_dependency, status=self.app.install_model.ToolDependency.installation_status.ERROR, error_message=error_message) else: tool_dependency = \ tool_dependency_util.set_tool_dependency_attributes(self.app, tool_dependency=tool_dependency, status=self.app.install_model.ToolDependency.installation_status.INSTALLED) tool_dependencies.append(tool_dependency) return tool_dependencies