Ejemplo n.º 1
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.º 2
0
    def preInstallCheck(self, eggInstall=True):
        """Check that prerequisite zenpacks are installed.
        Return True if no prereqs specified or if they are present.
        False otherwise.
        """
        if eggInstall:
            installedPacks = dict((pack.id, pack.version) \
                             for pack in self.dataroot.ZenPackManager.packs())

            if self.options.installPackName.lower().endswith('.egg'):
                # standard prebuilt egg
                if not os.path.exists(self.options.installPackName):
                    raise ZenPackNotFoundException("Unable to find ZenPack named '%s'" % \
                                           self.options.installPackName)
                zf = ZipFile(self.options.installPackName)
                if 'EGG-INFO/requires.txt' in zf.namelist():
                    reqZenpacks = zf.read('EGG-INFO/requires.txt').split('\n')
                else:
                    return True
            else:
                # source egg, no prebuilt egg-info
                with get_temp_dir() as tempEggDir:
                    cmd = '%s setup.py egg_info -e %s' % \
                                                (binPath('python'), tempEggDir)
                    subprocess.call(cmd,
                                    shell=True,
                                    stdout=open('/dev/null', 'w'),
                                    cwd=self.options.installPackName)

                    eggRequires = os.path.join(
                        tempEggDir, self.options.installPackName + '.egg-info',
                        'requires.txt')
                    if os.path.isfile(eggRequires):
                        reqZenpacks = open(eggRequires, 'r').read().split('\n')
                    else:
                        return True

            prereqsMet = True
            for req in reqZenpacks:
                if not req.startswith('ZenPacks'):
                    continue
                for parsed_req in parse_requirements([req]):
                    installed_version = installedPacks.get(
                        parsed_req.project_name, None)
                    if installed_version is None:
                        self.log.error('Zenpack %s requires %s',
                                       self.options.installPackName,
                                       parsed_req)
                        prereqsMet = False
                    else:
                        if not installed_version in parsed_req:
                            self.log.error('Zenpack %s requires %s, found: %s',
                                           self.options.installPackName,
                                           parsed_req, installed_version)
                            prereqsMet = False
            return prereqsMet

        if os.path.isfile(self.options.installPackName):
            zf = ZipFile(self.options.installPackName)
            for name in zf.namelist():
                if name.endswith == '/%s' % CONFIG_FILE:
                    sio = StringIO(zf.read(name))
            else:
                return True
        else:
            name = os.path.join(self.options.installPackName, CONFIG_FILE)
            if os.path.isfile(name):
                fp = open(name)
                sio = StringIO(fp.read())
                fp.close()
            else:
                return True

        parser = ConfigParser.SafeConfigParser()
        parser.readfp(sio, name)
        if parser.has_section(CONFIG_SECTION_ABOUT) \
            and parser.has_option(CONFIG_SECTION_ABOUT, 'requires'):
            requires = eval(parser.get(CONFIG_SECTION_ABOUT, 'requires'))
            if not isinstance(requires, list):
                requires = [zp.strip() for zp in requires.split(',')]
            missing = [
                zp for zp in requires
                if zp not in self.dataroot.ZenPackManager.packs.objectIds()
            ]
            if missing:
                self.log.error('ZenPack %s was not installed because',
                               self.options.installPackName,
                               ' it requires the following ZenPack(s): %s',
                               ', '.join(missing))
                return False
        return True
Ejemplo n.º 3
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()