def transactional_actions(): # Instantiate ZenPack entryMap = pkg_resources.get_entry_map(dist, ZENPACK_ENTRY_POINT) if not entryMap or len(entryMap) > 1: raise ZenPackException( 'A ZenPack egg must contain exactly one' ' zenoss.zenpacks entry point. This egg appears to contain' ' %s such entry points.' % len(entryMap)) packName, packEntry = entryMap.items()[0] runExternalZenpack = True #if zenpack with same name exists we can't load both modules #installing new egg zenpack will be done in a sub process existing = dmd.ZenPackManager.packs._getOb(packName, None) if existing: log.info("Previous ZenPack exists with same name %s" % packName) if filesOnly or not existing: #running files only or zenpack by same name doesn't already exists # so no need to install the zenpack in an external process runExternalZenpack = False module = packEntry.load() if hasattr(module, 'ZenPack'): zenPack = module.ZenPack(packName) else: zenPack = ZenPack(packName) zenPack.eggPack = True CopyMetaDataToZenPackObject(dist, zenPack) if filesOnly: for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()): loader.load(zenPack, None) if fromUI and not zenPack.installableFromUI: raise ZenPackException( "This ZenPack cannot be installed through the UI.") if not filesOnly: # Look for an installed ZenPack to be upgraded. In this case # upgraded means that it is removed before the new one is installed # but that its objects are not removed and the packables are # copied to the new instance. existing = dmd.ZenPackManager.packs._getOb(packName, None) if not existing and zenPack.prevZenPackName: existing = dmd.ZenPackManager.packs._getOb( zenPack.prevZenPackName, None) deferFileDeletion = False packables = [] upgradingFrom = None if existing: upgradingFrom = existing.version for p in existing.packables(): packables.append(p) existing.packables.removeRelation(p) if existing.isEggPack(): forceNoFileDeletion = existing.eggPath() == dist.location RemoveZenPack(dmd, existing.id, skipDepsCheck=True, leaveObjects=True, forceNoFileDeletion=forceNoFileDeletion, uninstallEgg=False) else: # Don't delete files, might still be needed for # migrate scripts to be run below. deferFileDeletion = True oldzenpack.RemoveZenPack(dmd, existing.id, skipDepsCheck=True, leaveObjects=True, deleteFiles=False) if runExternalZenpack or forceRunExternal: log.info("installing zenpack %s; launching process" % packName) cmd = [binPath('zenpack')] if link: cmd += ["--link"] cmd += ["--install", eggPath] if upgradingFrom: cmd += ['--previousversion', upgradingFrom] if fromUI: cmd += ["--fromui"] cmdStr = " ".join(cmd) log.debug("launching sub process command: %s" % cmdStr) p = subprocess.Popen(cmdStr, shell=True) out, err = p.communicate() p.wait() if p.returncode: raise ZenPackException( 'Error installing the egg (%s): %s' % (p.returncode, err)) dmd._p_jar.sync() else: dmd.ZenPackManager.packs._setObject(packName, zenPack) zenPack = dmd.ZenPackManager.packs._getOb(packName) #hack because ZenPack.install is overridden by a lot of zenpacks #so we can't change the signature of install to take the #previousVerison zenPack.prevZenPackVersion = previousVersion zenPack.install(dmd) zenPack.prevZenPackVersion = None try: zenPack = dmd.ZenPackManager.packs._getOb(packName) for p in packables: pId = p.getPrimaryId() try: # make sure packable still exists; could be deleted by a # migrate getObjByPath(dmd, pId) log.debug("adding packable relation for id %s", pId) zenPack.packables.addRelation(p) except (KeyError, zExceptions.NotFound): log.debug('did not find packable %s', pId) except AttributeError, e: # If this happens in the child process or during the non-upgrade # flow, reraise the exception if not runExternalZenpack: raise # This specific error will occur when the version of the ZenPack # being installed subclasses Products.ZenModel.ZenPack, but the # previous version of the ZenPack did not. if str(e) == "'ZenPack' object has no attribute '__of__'": zenPack = ZenPack(packName) else: # This is the signature error of class-loading issues # during zenpack upgrade. The final state should be okay, # except that modified packables may be lost. message = "There has been an error during the post-" + \ "installation steps for the zenpack %s. In " + \ "most cases, no further action is required. If " + \ "issues persist, please reinstall this zenpack." message = message % packName log.warning(message) raise NonCriticalInstallError(message) cleanupSkins(dmd) return zenPack, deferFileDeletion, existing
def run(self): """Execute the user's request""" if self.args: print "Require one of --install, --remove, --export, --create, or --list flags." self.parser.print_help() return if self.options.installPackName: audit('Shell.ZenPack.Install', zenpack=self.options.installPackName) elif self.options.fetch: audit('Shell.ZenPack.Fetch', zenpack=self.options.fetch) elif self.options.exportPack: audit('Shell.ZenPack.Export', zenpack=self.options.exportPack) elif self.options.removePackName: audit('Shell.ZenPack.Remove', zenpack=self.options.removePackName) elif self.options.createPackName: audit('Shell.ZenPack.Create', zenpack=self.options.createPackName) ZenPack.currentServiceId = self.options.serviceId if self.options.createPackName: devDir, packName = os.path.split(self.options.createPackName) try: self.connect() self.dmd.ZenPackManager.manage_addZenPack(packName, devDir=devDir) except Exception as ex: self.log.fatal("could not create zenpack: %s", ex) sys.exit(1) sys.exit(0) if self.options.installPackName: eggInstall = (self.options.installPackName.lower().endswith('.egg') or os.path.exists( os.path.join(self.options.installPackName, 'setup.py'))) if self.options.removePackName and self.options.filesOnly: # A files-only remove implies a files-only install. Egg packs are only supported here. installedEggs = [p for p in iter_entry_points('zenoss.zenpacks')] theOne = filter(lambda x: x.name == self.options.removePackName, installedEggs) if not theOne: raise ZenPackNotFoundException( "Specified zenpack not installed") if len(theOne) > 1: raise ZenPackException( "Multiple matching distributions for {} found - aborting.". format(self.options.removePackName)) actualZPDir = theOne[0].dist.location class ZPProxy: def __init__(self, zpId, actualPath): self.id = zpId self.actualPath = actualPath def path(self, *parts): return self.actualPath proxy = ZPProxy(self.options.removePackName, actualZPDir) for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()): loader.unload(proxy, None) try: os.system('pip uninstall -y "%s"' % self.options.removePackName) except Exception as ex: self.log.error('Could not uninstall "%s"', self.options.removePackName) raise ex # treat it as a fatal error return self.connect() if not getattr(self.dmd, 'ZenPackManager', None): raise ZenPackNeedMigrateException( 'Your Zenoss database appears' ' to be out of date. Try running zenmigrate to update.') if (self.options.installPackName or self.options.removePackName ) and not self._verifyZepRunning(timeout=600, delay=5): print >> sys.stderr, "Error: Required daemon zeneventserver not running." print >> sys.stderr, "Execute 'zeneventserver start' and retry the ZenPack installation." sys.exit(1) if self.options.installPackName: # Process each install filter utility - order does not matter for name, util in getUtilitiesFor(IZenPackInstallFilter): # Get normalized pack name to compare. Split on path separator # in case absolute path was given egg_name = EGG_NAME( os.path.basename( os.path.normpath(self.options.installPackName))) if not egg_name: self.stop('Could not determine egg name from "%s"' % self.options.installPackName) packName = egg_name.group('name') if not util.installable(packName): self.stop('Filter %s does not allow %s to be installed' \ % (name, self.options.installPackName)) if self.options.skipSameVersion and self._sameVersion(): return if not self.preInstallCheck(eggInstall): self.stop('%s not installed' % self.options.installPackName) if eggInstall: try: return EggPackCmd.InstallEggAndZenPack( self.dmd, self.options.installPackName, link=self.options.link, filesOnly=self.options.filesOnly, previousVersion=self.options.previousVersion, fromUI=self.options.fromui, serviceId=self.options.serviceId, ignoreServiceInstall=self.options.ignoreServiceInstall) except (OSError, ) as e: if self.options.link: self.stop('%s cannot be installed with --link option' % self.options.installPackName) else: self.stop('%s could not be installed' % self.options.installPackName) if os.path.isfile(self.options.installPackName): packName = self.extract(self.options.installPackName) elif os.path.isdir(self.options.installPackName): if self.options.link: packName = self.linkDir(self.options.installPackName) else: packName = self.copyDir(self.options.installPackName) else: self.stop( '%s does not appear to be a valid file or directory.' % self.options.installPackName) # We want to make sure all zenpacks have a skins directory and that it # is registered. The zip file may not contain a skins directory, so we # create one here if need be. The directory should be registered # by the zenpack's __init__.py and the skin should be registered # by ZPLSkins loader. skinsSubdir = zenPath('Products', packName, 'skins', packName) if not os.path.exists(skinsSubdir): os.makedirs(skinsSubdir, 0750) self.install(packName) elif self.options.fetch: return EggPackCmd.FetchAndInstallZenPack(self.dmd, self.options.fetch) elif self.options.exportPack: return EggPackCmd.ExportZenPack(self.dmd, self.options.exportPack) elif self.options.removePackName: try: self.dmd.startPauseADM() pack = self.dmd.ZenPackManager.packs._getOb( self.options.removePackName, None) if not pack: if not self.options.ifinstalled: self.log.info('ZenPack %s is not installed.', self.options.removePackName) return False else: if pack: removeZenPackQueuesExchanges(pack.path()) if pack.isEggPack(): return EggPackCmd.RemoveZenPack( self.dmd, self.options.removePackName) RemoveZenPack(self.dmd, self.options.removePackName, self.log) finally: self.dmd.stopPauseADM() elif self.options.list: for zpId in self.dmd.ZenPackManager.packs.objectIds(): try: zp = self.dmd.ZenPackManager.packs._getOb(zpId, None) except AttributeError: zp = None if not zp: desc = 'broken' elif zp.isEggPack(): try: desc = zp.eggPath() except DistributionNotFound: desc = "zenpack missing" else: desc = zp.path() print('%s (%s)' % (zpId, desc)) elif self.options.restore: self.log.info("Restoring zenpacks") self.restore() transaction.commit()
def run(self): """Execute the user's request""" if self.args: print "Require one of --install, --remove or --list flags." self.parser.print_help() return if self.options.installPackName: audit('Shell.ZenPack.Install', zenpack=self.options.installPackName) elif self.options.fetch: audit('Shell.ZenPack.Fetch', zenpack=self.options.fetch) elif self.options.removePackName: audit('Shell.ZenPack.Remove', zenpack=self.options.removePackName) if self.options.installPackName: eggInstall = (self.options.installPackName.lower().endswith('.egg') or os.path.exists( os.path.join(self.options.installPackName, 'setup.py'))) # files-only just lays the files down and doesn't "install" # them into zeo class ZPProxy: def __init__(self, zpId): self.id = zpId def path(self, *parts): return zenPath('Products', self.id, *parts) if self.options.installPackName and self.options.filesOnly: if eggInstall: return EggPackCmd.InstallZenPack(None, self.options.installPackName, filesOnly=True) packName = self.extract(self.options.installPackName) proxy = ZPProxy(packName) for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()): loader.load(proxy, None) return if self.options.removePackName and self.options.filesOnly: # Remove files-only is not yet supported for egg zenpacks # todo proxy = ZPProxy(self.options.removePackName) for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()): loader.unload(proxy, None) os.system('rm -rf %s' % zenPath('Products', self.options.removePackName)) return self.connect() if not getattr(self.dmd, 'ZenPackManager', None): raise ZenPackNeedMigrateException( 'Your Zenoss database appears' ' to be out of date. Try running zenmigrate to update.') if (self.options.installPackName or self.options.removePackName) and not self._verifyZepRunning(): print >> sys.stderr, "Error: Required daemon zeneventserver not running." print >> sys.stderr, "Execute 'zeneventserver start' and retry the ZenPack installation." sys.exit(1) if self.options.installPackName: if not self.preInstallCheck(eggInstall): self.stop('%s not installed' % self.options.installPackName) if eggInstall: return EggPackCmd.InstallEggAndZenPack( self.dmd, self.options.installPackName, link=self.options.link, filesOnly=False, previousVersion=self.options.previousVersion, fromUI=self.options.fromui) if os.path.isfile(self.options.installPackName): packName = self.extract(self.options.installPackName) elif os.path.isdir(self.options.installPackName): if self.options.link: packName = self.linkDir(self.options.installPackName) else: packName = self.copyDir(self.options.installPackName) else: self.stop( '%s does not appear to be a valid file or directory.' % self.options.installPackName) # We want to make sure all zenpacks have a skins directory and that it # is registered. The zip file may not contain a skins directory, so we # create one here if need be. The directory should be registered # by the zenpack's __init__.py and the skin should be registered # by ZPLSkins loader. skinsSubdir = zenPath('Products', packName, 'skins', packName) if not os.path.exists(skinsSubdir): os.makedirs(skinsSubdir, 0750) self.install(packName) elif self.options.fetch: return EggPackCmd.FetchAndInstallZenPack(self.dmd, self.options.fetch) elif self.options.removePackName: pack = self.dmd.ZenPackManager.packs._getOb( self.options.removePackName, None) if not pack: if not self.options.ifinstalled: self.log.info('ZenPack %s is not installed.' % self.options.removePackName) return False else: removeZenPackQueuesExchanges(pack.path()) if pack.isEggPack(): return EggPackCmd.RemoveZenPack( self.dmd, self.options.removePackName) RemoveZenPack(self.dmd, self.options.removePackName, self.log) elif self.options.list: for zpId in self.dmd.ZenPackManager.packs.objectIds(): try: zp = self.dmd.ZenPackManager.packs._getOb(zpId, None) except AttributeError: zp = None if not zp: desc = 'broken' elif zp.isEggPack(): desc = zp.eggPath() else: desc = zp.path() print('%s (%s)' % (zpId, desc)) transaction.commit()