def downloadPlugin(url, plugin=None, zipFile=None): """download a plugin, extract and install it""" if not plugin: from iondb.rundb import models plugin = models.Plugin.objects.create(name='Unknown', version='Unknown', status={}) plugin.status["installStatus"] = "downloading" #normalise the URL url = urlparse.urlsplit(url).geturl() if not zipFile: if url.endswith(".xml"): status = downloadPluginZeroInstall(url, plugin, logger=logger) logger.error("xml") # logfile else: status = downloadPluginArchive(url, plugin, logger=logger) logger.error("zip") # logfile if not status: # FIXME - Errors! installStatus = plugin.status.get('installStatus', 'Unknown') result = plugin.status.get('result', 'unknown') msg = "Plugin install '%s', Result: '%s'" % (installStatus, result) logger.error(msg) # logfile from iondb.rundb import models models.Message.error(msg) # UI message return False else: # Extract zipfile scratch_path = os.path.join(settings.PLUGIN_PATH, "scratch") zip_file = os.path.join(scratch_path, zipFile) plugin.status["installStatus"] = "extracting zip" try: ret = unzipPlugin(zip_file) except: logger.exception("Failed to unzip Plugin: '%s'", zip_file) finally: #remove the zip file os.unlink(zip_file) plugin.name = ret['plugin'] plugin.path = ret['path'] plugin.status["installStatus"] = "installing from zip" # Now that it has been downloaded, # convert pre-plugin into real db plugin object try: from iondb.plugins.manager import pluginmanager (new_plugin, updated) = pluginmanager.install(plugin.name, plugin.path) except ValueError: logger.exception( "Plugin rejected by installer. Check syntax and content.") return None # Copy over download status messages and url new_plugin.status = plugin.status if plugin.url: new_plugin.url = plugin.url new_plugin.save() logger.info( "Successfully downloaded and installed plugin %s v%s from '%s'", new_plugin.name, new_plugin.version, url) return new_plugin
def downloadPlugin(url, plugin=None, zipFile=None): """download a plugin, extract and install it""" if not plugin: from iondb.rundb import models plugin = models.Plugin.objects.create(name='Unknown', version='Unknown', status={}) plugin.status["installStatus"] = "downloading" #normalise the URL url = urlparse.urlsplit(url).geturl() if not zipFile: if url.endswith(".xml"): status = downloadPluginZeroInstall(url, plugin, logger=logger) logger.error("xml") # logfile else: status = downloadPluginArchive(url, plugin, logger=logger) logger.error("zip") # logfile if not status: # FIXME - Errors! installStatus = plugin.status.get('installStatus', 'Unknown') result = plugin.status.get('result', 'unknown') msg = "Plugin install '%s', Result: '%s'" % (installStatus, result) logger.error(msg) # logfile from iondb.rundb import models models.Message.error(msg) # UI message return False else: # Extract zipfile scratch_path = os.path.join(settings.PLUGIN_PATH,"scratch") zip_file = os.path.join(scratch_path, zipFile) plugin.status["installStatus"] = "extracting zip" try: ret = unzipPlugin(zip_file) except: logger.exception("Failed to unzip Plugin: '%s'", zip_file) finally: #remove the zip file os.unlink(zip_file) plugin.name = ret['plugin'] plugin.path = ret['path'] plugin.status["installStatus"] = "installing from zip" # Now that it has been downloaded, # convert pre-plugin into real db plugin object try: from iondb.plugins.manager import pluginmanager (new_plugin, updated) = pluginmanager.install(plugin.name, plugin.path) except ValueError: logger.exception("Plugin rejected by installer. Check syntax and content.") return None # Copy over download status messages and url new_plugin.status = plugin.status if plugin.url: new_plugin.url = plugin.url new_plugin.save() logger.info("Successfully downloaded and installed plugin %s v%s from '%s'", new_plugin.name, new_plugin.version, url) return new_plugin
def unzipPlugin(zipfile, logger=None): if not logger: logger = logging.getLogger(__name__) ## Extract plugin to scratch folder. When complete, move to final location. plugin_path, ext = os.path.splitext(zipfile) plugin_name = os.path.basename(plugin_path) # ZIP file must named with plugin name - fragile # FIXME - handle (1) additions (common for multiple downloads via browser) # FIXME - handle version string in ZIP archive name scratch_path = os.path.join(settings.PLUGIN_PATH, "scratch", "install-temp", plugin_name) (prefix, files) = extract_zip(zipfile, scratch_path, auto_prefix=True, logger=logger) if prefix: plugin_name = os.path.basename(prefix) plugin_temp_home = os.path.join(scratch_path, prefix) try: # Convert script into PluginClass, get info by introspection from iondb.plugins.manager import pluginmanager script, islaunch = pluginmanager.find_pluginscript( plugin_temp_home, plugin_name) logger.debug("Got script: %s", script) from ion.plugin.loader import cache ret = cache.load_module(plugin_name, script) cls = cache.get_plugin(plugin_name) p = cls() final_name = p.name # what the plugin calls itself, regardless of ZIP file name logger.info("Plugin calls itself: '%s'", final_name) except: logger.exception("Unable to interrogate plugin name from: '%s'", zipfile) final_name = plugin_name #move to the plugin dir # New extract_zip removes prefix from extracted files. # But still writes to file_name try: final_install_dir = os.path.join(settings.PLUGIN_PATH, final_name) if os.path.exists(final_install_dir) and (final_install_dir != settings.PLUGIN_PATH): logger.info("Deleting old copy of plugin at '%s'", final_install_dir) delete_that_folder( final_install_dir, "Error Deleting old copy of plugin at '%s'" % final_install_dir) parent_folder = os.path.dirname(final_install_dir) if not os.path.exists(parent_folder): logger.info("Creating path for plugin '%s' for '%s'", parent_folder, final_install_dir) os.makedirs(parent_folder, 0555) logger.info( "Moving plugin from temp extract folder '%s' to final location: '%s'", plugin_temp_home, final_install_dir) shutil.move(plugin_temp_home, final_install_dir) delete_that_folder(scratch_path, "Deleting plugin install scratch folder") except (IOError, OSError): logger.exception( "Failed to move plugin from temp extract folder '%s' to final location: '%s'", plugin_temp_home, final_install_dir) raise # Now that it has been downloaded, # convert pre-plugin into real db plugin object try: from iondb.plugins.manager import pluginmanager (new_plugin, updated) = pluginmanager.install(final_name, final_install_dir) except ValueError: logger.exception("Failed to install plugin") #delete_that_folder(final_install_dir) return { "plugin": final_name, "path": final_install_dir, "files": files, }
def unzipPlugin(zipfile, logger=None): if not logger: logger = logging.getLogger(__name__) ## Extract plugin to scratch folder. When complete, move to final location. plugin_path, ext = os.path.splitext(zipfile) plugin_name = os.path.basename(plugin_path) # ZIP file must named with plugin name - fragile # FIXME - handle (1) additions (common for multiple downloads via browser) # FIXME - handle version string in ZIP archive name scratch_path = os.path.join(settings.PLUGIN_PATH,"scratch","install-temp",plugin_name) (prefix, files) = extract_zip(zipfile, scratch_path, auto_prefix=True, logger=logger) if prefix: plugin_name = os.path.basename(prefix) plugin_temp_home = os.path.join(scratch_path, prefix) try: # Convert script into PluginClass, get info by introspection from iondb.plugins.manager import pluginmanager script, islaunch = pluginmanager.find_pluginscript(plugin_temp_home, plugin_name) logger.debug("Got script: %s", script) from ion.plugin.loader import cache ret = cache.load_module(plugin_name, script) cls = cache.get_plugin(plugin_name) p = cls() final_name = p.name # what the plugin calls itself, regardless of ZIP file name logger.info("Plugin calls itself: '%s'", final_name) except: logger.exception("Unable to interrogate plugin name from: '%s'", zipfile) final_name = plugin_name #move to the plugin dir # New extract_zip removes prefix from extracted files. # But still writes to file_name try: final_install_dir = os.path.join(settings.PLUGIN_PATH, final_name) if os.path.exists(final_install_dir) and (final_install_dir != settings.PLUGIN_PATH): logger.info("Deleting old copy of plugin at '%s'", final_install_dir) delete_that_folder(final_install_dir, "Error Deleting old copy of plugin at '%s'" % final_install_dir) parent_folder = os.path.dirname(final_install_dir) if not os.path.exists(parent_folder): logger.info("Creating path for plugin '%s' for '%s'", parent_folder, final_install_dir) os.makedirs(parent_folder, 0555) logger.info("Moving plugin from temp extract folder '%s' to final location: '%s'", plugin_temp_home, final_install_dir) shutil.move(plugin_temp_home, final_install_dir) delete_that_folder(scratch_path, "Deleting plugin install scratch folder") except (IOError, OSError): logger.exception("Failed to move plugin from temp extract folder '%s' to final location: '%s'", plugin_temp_home, final_install_dir) raise # Now that it has been downloaded, # convert pre-plugin into real db plugin object try: from iondb.plugins.manager import pluginmanager (new_plugin, updated) = pluginmanager.install(final_name, final_install_dir) except ValueError: logger.exception("Failed to install plugin") #delete_that_folder(final_install_dir) return { "plugin": final_name, "path": final_install_dir, "files": files, }