Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
    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.')
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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()
Ejemplo n.º 5
0
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
Ejemplo n.º 6
0
 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
Ejemplo n.º 7
0
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)
Ejemplo n.º 8
0
    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()
Ejemplo n.º 9
0
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()
Ejemplo n.º 10
0
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]
Ejemplo n.º 11
0
    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
Ejemplo n.º 12
0
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
Ejemplo n.º 13
0
                    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]