def UploadZenPack(dmd, packName, project, description, znetUser, znetPass): """ Upload the specified zenpack to the given project. Project is a string of the form 'enterprise/myproject' or 'community/otherproject'. """ zp = dmd.ZenPackManager.packs._getOb(packName, None) if not zp: raise ZenPackException('No ZenPack named %s' % packName) # Export the zenpack fileName = zp.manage_exportPack() # Login to Zenoss.net from DotNetCommunication import DotNetSession session = DotNetSession() session.login(znetUser, znetPass) # Upload zpFile = open(zenPath('export', fileName), 'r') try: response = session.open('%s/createRelease' % project.strip('/'), { 'description': description, 'fileStorage': zpFile, }) finally: zpFile.close() if response: result = response.read() if "'success':true" not in result: raise ZenPackException('Upload failed') else: raise ZenPackException('Failed to connect to Zenoss.net') return
def run(self): if not self.options.newid: raise ZenPackException('You must specify a new id with the' ' --newid option.') zpName = self.args[0] if not os.path.isdir(zenPath('Products', zpName)): raise ZenPackException( 'Can not locate %s.' % zpName + ' This command only operates on installed ZenPacks.') (possible, msgOrId) = ZenPackCmd.CanCreateZenPack(None, self.options.newid) if possible: newId = msgOrId else: raise ZenPackException('Unable to eggify %s: %s' % (zpName, msgOrId)) self.connect() # Create new zenpack eggDir = ZenPackCmd.CreateZenPack(newId, prevZenPackName=zpName) # Copy old one into new one parts = newId.split('.') zpDir = os.path.join(eggDir, *parts) os.system('rm -rf %s' % zpDir) shutil.copytree(zenPath('Products', zpName), zpDir, symlinks=False) # Create a skins directory if there isn't one skinsDir = os.path.join(zpDir, 'skins', zpName) if not os.path.isdir(skinsDir): os.makedirs(skinsDir) # Install it ZenPackCmd.InstallEggAndZenPack(self.dmd, eggDir, link=True) # Confirm pack is eggified pack = self.dmd.ZenPackManager.packs._getOb(zpName, None) success = pack and pack.isEggPack() if success: print('%s successfully converted to %s.' % (zpName, newId)) print('The code for %s is located at $ZENHOME/ZenPacks/%s' % (newId, newId)) print('NOTE: If your ZenPack provides DataSource classes ' 'or any other python class for objects that are stored ' 'in the object database then further steps are ' 'required. Please see the Zenoss Developer Guide for ' 'more instructions.')
def InstallEgg(dmd, eggPath, link=False): """ Install the given egg and add to the current working set. This does not install the egg as a ZenPack. Return a list of distributions that should be installed as ZenPacks. """ eggPath = os.path.abspath(eggPath) zenPackDir = zenPath('ZenPacks') # Make sure $ZENHOME/ZenPacks exists CreateZenPacksDir() # Install the egg if link: zenPackDir = varPath('ZenPacks') cmd = ('%s setup.py develop ' % binPath('python') + '--site-dirs=%s ' % zenPackDir + '-d %s' % zenPackDir) returncode, out, err = None, '', '' for attempt in range(3): p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=eggPath) out, err = p.communicate() p.wait() returncode = p.returncode if returncode: log.info("Error installing the egg (%s): %s" % (returncode, err)) try: DoEasyUninstall(eggPath) except Exception: pass else: break if returncode: raise ZenPackException('Error installing the egg (%s): %s' % (returncode, err)) zpDists = AddDistToWorkingSet(eggPath) else: try: zpDists = DoEasyInstall(eggPath) except Exception: DoEasyUninstall(eggPath) raise # cmd = 'easy_install --always-unzip --site-dirs=%s -d %s %s' % ( # zenPackDir, # zenPackDir, # eggPath) # p = subprocess.Popen(cmd, # stdout=subprocess.PIPE, # stderr=subprocess.PIPE, # shell=True) # p.wait() # eggName = os.path.split(eggPath)[1] # eggPath = os.path.join(zenPackDir, eggName) return zpDists
def ExportZenPack(dmd, packName): """ Export the zenpack to $ZENHOME/export """ zp = dmd.ZenPackManager.packs._getOb(packName, None) if not zp: raise ZenPackException('No ZenPack named %s' % packName) # Export the zenpack return zp.manage_exportPack()
def RemoveZenPack(dmd, packName, log=None, skipDepsCheck=False, leaveObjects=True, deleteFiles=True): if log: log.debug('Removing Pack "%s"', packName) if not skipDepsCheck: for pack in dmd.ZenPackManager.packs(): if packName in pack.requires: raise ZenPackException('Pack %s depends on pack %s, ' 'not removing' % (pack.id, packName)) zp = None try: zp = dmd.ZenPackManager.packs._getOb(packName) except AttributeError: # Pack not in zeo, might still exist in filesystem if log: log.debug('No ZenPack named %s in zeo', packName) if zp: try: # In 2.2 we added an additional parameter to the remove method. # Any ZenPack subclasses that haven't been updated to take the new # parameter will throw a TypeError. # The newer version of zenoss-supplied ZenPacks monkey patch # older installed versions during an upgrade so that the remove # accepts the leaveObjects method. zp.remove(dmd, leaveObjects=True) except TypeError: zp.remove(dmd) dmd.ZenPackManager.packs._delObject(packName) root = zenPath('Products', packName) if deleteFiles: if log: log.debug('Removing %s', root) recurse = "" if os.path.isdir(root): recurse = "r" os.system('rm -%sf %s' % (recurse, root)) cleanupSkins(dmd) return True
def AddEntryAndProcessDeps(e): orderedEntries.append(e) for name in [r.project_name for r in e.dist.requires()]: if name in [e.name for e in orderedEntries]: # This entry depends on something that we've already processed. # This might be a circular dependency, might not be. # We are just going to bail however. This should be # very unusual and the user can install deps first to work # around. raise ZenPackException('Unable to resolve ZenPack dependencies.' ' Try installing dependencies first.') if name in entriesByName: # The requirement is an entry that has not yet been processed # here. Add it to the list of entries to install/upgrade. AddEntryAndProcessDeps(entriesByName[name]) else: # The requirement is not in the entries generated above. # This either means that the dep is already installed (this # is likely) or that easy_install missed something and the dep # is not installed/available (this should be unlikely.) pass
def RemoveZenPack(dmd, packName, log=None, skipDepsCheck=False, leaveObjects=True, deleteFiles=True): if log: log.debug('Removing Pack "%s"' % packName) if not skipDepsCheck: for pack in dmd.ZenPackManager.packs(): if packName in pack.requires: raise ZenPackException('Pack %s depends on pack %s, ' 'not removing' % (pack.id, packName)) zp = None try: zp = dmd.ZenPackManager.packs._getOb(packName) except AttributeError, ex: # Pack not in zeo, might still exist in filesystem if log: log.debug('No ZenPack named %s in zeo' % packName)
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 RemoveZenPack(dmd, packName, filesOnly=False, skipDepsCheck=False, leaveObjects=False, sendEvent=True, forceNoFileDeletion=False, uninstallEgg=True): """ Remove the given ZenPack from Zenoss. Whether the ZenPack will be removed from the filesystem or not depends on the result of the ZenPack's shouldDeleteFilesOnRemoval method. """ try: if filesOnly: skipDepsCheck = True # Check for dependency implications here? if not skipDepsCheck: deps = GetDependents(dmd, packName) if deps: raise ZenPackDependentsException( '%s cannot be removed ' % packName + 'because it is required by %s' % ', '.join(deps)) if not filesOnly: # Fetch the zenpack, call its remove() and remove from packs zp = None try: zp = dmd.ZenPackManager.packs._getOb(packName) except AttributeError, ex: raise ZenPackNotFoundException( 'No ZenPack named %s is installed' % packName) # If zencatalog hasn't finished yet, we get ugly messages that don't # mean anything. Hide them. logFilter = None if not getattr(dmd.zport, '_zencatalog_completed', False): logFilter = CatalogLoggingFilter() logging.getLogger('Zope.ZCatalog').addFilter(logFilter) try: zp.remove(dmd, leaveObjects) dmd.ZenPackManager.packs._delObject(packName) transaction.commit() finally: # Remove our logging filter so we don't hide anything important if logFilter is not None: logging.getLogger('Zope.ZCatalog').removeFilter(logFilter) # Uninstall the egg and possibly delete it # If we can't find the distribution then apparently the zp egg itself is # missing. Continue on with the removal and swallow the # DistributionNotFound exception try: dist = zp.getDistribution() except pkg_resources.DistributionNotFound: dist = None if dist: # Determine deleteFiles before develop -u gets called. Once # it is called the egg has problems figuring out some of it's state. deleteFiles = zp.shouldDeleteFilesOnRemoval() if uninstallEgg: if zp.isDevelopment(): zenPackDir = zenPath('ZenPacks') cmd = ('%s setup.py develop -u ' % binPath('python') + '--site-dirs=%s ' % zenPackDir + '-d %s' % zenPackDir) p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=zp.eggPath()) out, err = p.communicate() code = p.wait() if code: raise ZenPackException(err) else: DoEasyUninstall(packName) # elif cleanupEasyInstallPth: # # Do we need to call easy_install -m here? It causes problems # # because it tries to install deps. Cleanup easy-install.pth # # ourselves instead. # # We don't want to cleanup easy-install.pth when a newer # # version of the egg has already been installed (when doing # # an upgrade or installing in new location.) # eggLink = './%s' % zp.eggName() # CleanupEasyInstallPth(eggLink) if deleteFiles and not forceNoFileDeletion: eggDir = zp.eggPath() if os.path.islink(eggDir): os.remove(eggDir) else: shutil.rmtree(eggDir) cleanupSkins(dmd) transaction.commit()
def DiscoverEggs(dmd, zenPackId): """ Find installed eggs that provide a zenoss.zenpacks entry point. Return a list of distributions whose ZenPacks need to be installed or upgraded. The list is sorted into the order in which this needs to happen. """ # Create a set of all available zenoss.zenpack entries that aren't # already installed in zenoss or need to be upgraded in zenoss. entries = set() parse_version = pkg_resources.parse_version for entry in pkg_resources.iter_entry_points(ZENPACK_ENTRY_POINT): packName = entry.name packVers = entry.dist.version existing = dmd.ZenPackManager.packs._getOb(packName, None) if existing and existing.isEggPack(): # We use >= to allow migrate to be run on currently installed # zenpacks whose version has been changed or for whom new # migrates have been added. if parse_version(packVers) >= parse_version(existing.version): entries.add(entry) else: entries.add(entry) # Starting with the entry representing zenPackId create a list of # all entrypoints # orderedEntries lists entries in the opposite order of that in which # they need to be installed. This is simply for convenience of using # .append() in code below. orderedEntries = [] entriesByName = dict((e.name, e) for e in entries) def AddEntryAndProcessDeps(e): orderedEntries.append(e) for name in [r.project_name for r in e.dist.requires()]: if name in [e.name for e in orderedEntries]: # This entry depends on something that we've already processed. # This might be a circular dependency, might not be. # We are just going to bail however. This should be # very unusual and the user can install deps first to work # around. raise ZenPackException( 'Unable to resolve ZenPack dependencies.' ' Try installing dependencies first.') if name in entriesByName: # The requirement is an entry that has not yet been processed # here. Add it to the list of entries to install/upgrade. AddEntryAndProcessDeps(entriesByName[name]) else: # The requirement is not in the entries generated above. # This either means that the dep is already installed (this # is likely) or that easy_install missed something and the dep # is not installed/available (this should be unlikely.) pass if zenPackId not in entriesByName: if zenPackId in dmd.ZenPackManager.packs.objectIds(): return [] else: raise ZenPackException('Unable to discover ZenPack named %s' % zenPackId) AddEntryAndProcessDeps(entriesByName[zenPackId]) orderedEntries.reverse() return [e.dist for e in orderedEntries]
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 InstallDistAsZenPack(dmd, dist, eggPath, link=False, filesOnly=False, previousVersion=None, forceRunExternal=False, fromUI=False, serviceId=None, ignoreServiceInstall=False): """ Given an installed dist, install it into Zenoss as a ZenPack. Return the ZenPack instance. """ @transact 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 def doesExist(): existing = dmd.ZenPackManager.packs._getOb(packName, None) if existing: log.info("Previous ZenPack exists with same name %s" % packName) return existing if filesOnly or not doesExist(): if filesOnly: log.info("ZenPack files only install: %s" % packName) #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.resolve() 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"] if serviceId: cmd += ['--service-id', serviceId] if ignoreServiceInstall: cmd += ['--ignore-service-install'] 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 if ignoreServiceInstall: ZenPack.ignoreServiceInstall = True 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 as 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 else: return zenPack, False, True info = ReadZenPackInfo(dist) if ('compatZenossVers' in info): vers = info['compatZenossVers'] if vers[0] in string.digits: vers = '==' + vers try: req = pkg_resources.Requirement.parse('zenoss%s' % vers) except ValueError: raise ZenPackException("Couldn't parse requirement zenoss%s" % vers) if not req.__contains__(ZENOSS_VERSION): raise ZenPackException("Incompatible Zenoss Version %s, need %s" % (ZENOSS_VERSION, vers)) ZenPack.currentServiceId = serviceId zenPack, deferFileDeletion, existing = transactional_actions() packInfos = {} oldPacksDump = getPacksDump() for pack in dmd.ZenPackManager.packs(): try: eggPath = "" eggPath = pack.eggPath() except Exception: if pack.id in oldPacksDump: eggPath = oldPacksDump[pack.id] packInfos[pack.id] = { "id": pack.id, "version": pack.version, "dependencies": pack.dependencies, "eggPack": pack.eggPack, "eggPath": eggPath, "compatZenossVers": pack.compatZenossVers, "createdTime": pack.createdTime.ISO8601(), } atomicWrite(PACKS_DUMP, json.dumps(packInfos)) if not filesOnly and deferFileDeletion: # We skipped deleting the existing files from filesystem # because maybe they'd be needed in migrate scripts. # Delete them now oldZpDir = zenPath('Products', existing.id) if os.path.islink(oldZpDir): os.remove(oldZpDir) else: shutil.rmtree(oldZpDir) return zenPack
raise NonCriticalInstallError(message) cleanupSkins(dmd) return zenPack, deferFileDeletion, existing else: return zenPack, False, True info = ReadZenPackInfo(dist) if ('compatZenossVers' in info): vers = info['compatZenossVers'] if vers[0] in string.digits: vers = '==' + vers try: req = pkg_resources.Requirement.parse('zenoss%s' % vers) except ValueError: raise ZenPackException("Couldn't parse requirement zenoss%s" % vers) if not req.__contains__(ZENOSS_VERSION): raise ZenPackException("Incompatible Zenoss Version %s, need %s" % (ZENOSS_VERSION, vers)) ZenPack.currentServiceId = serviceId zenPack, deferFileDeletion, existing = transactional_actions() packInfos = {} oldPacksDump = getPacksDump() for pack in dmd.ZenPackManager.packs(): try: eggPath = "" eggPath = pack.eggPath() except Exception: if pack.id in oldPacksDump: eggPath = oldPacksDump[pack.id]