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
def manage_installZenPack(self, zenpack=None, REQUEST=None): """ Installs the given zenpack. Zenpack is a file upload from the browser. """ import re import time from subprocess import Popen, PIPE, STDOUT from Products.ZenUtils.Utils import get_temp_dir ZENPACK_INSTALL_TIMEOUT = 10 * 60 # 10 minutes if not getattr(self.dmd, 'ZenPackManager'): msg = 'Your Zenoss database appears to be out of date. Try ' \ 'running zenmigrate to update.' if REQUEST: messaging.IMessageSender(self).sendToBrowser( 'Error', msg, priority=messaging.WARNING) return self.callZenScreen(REQUEST) from ZenPack import ZenPackNeedMigrateException raise ZenPackNeedMigrateException(msg) msg = '' with get_temp_dir() as tempDir: # zenpack.filename gives us filename of the zenpack with the # path as it exists on the client. We need just the filename. base_filename = re.split(r"\\|/", zenpack.filename)[-1] # Macs (and other broswers/OSs) always append a .zip to files they # believe to be zip files. Remedy that: if base_filename.endswith('.egg.zip'): base_filename = base_filename[:-7] + 'egg' # Write the zenpack to the filesystem tFile = open(os.path.join(tempDir, base_filename), 'wb') tFile.write(zenpack.read()) tFile.close() p = None # zenpack install process # ZEN-1781: Redirect to a temporary file so the stdout buffer # doesn't fill up and block till you read from it. outFile = None try: outFile = tempfile.SpooledTemporaryFile() # Run zenpack install cmd = 'zenpack --install %s --fromui' % tFile.name p = Popen(cmd, shell=True, stdout=outFile, stderr=STDOUT) endWait = time.time() + ZENPACK_INSTALL_TIMEOUT # Wait for install to complete, fail, or time out while p.poll() is None and time.time() < endWait: time.sleep(1) if p.poll() is not None: outFile.seek(0) msg = outFile.read() finally: if outFile: outFile.close() if p and p.poll() is None: p.kill() msg += 'Zenpack install killed due to timeout' if REQUEST: # TODO: show the output in a scrollable window. # format command result for HTML #msg = '<br>'.join(line.strip() for line in msg.split('\n') if line.strip()) log.info("Output from installing ZenPack %s:\n%s" % (zenpack.filename, msg)) success = 'ERROR' not in msg msg = "Successfully installed ZenPack %s" % zenpack.filename if success \ else "Failed to install ZenPack %s. " \ "See event.log for details." % zenpack.filename messaging.IMessageSender(self).sendToBrowser( 'Zenpack', msg, priority=messaging.INFO if success else messaging.CRITICAL) return self.callZenScreen(REQUEST)
def manage_installZenPack(self, zenpack=None, REQUEST=None): """ Installs the given zenpack. Zenpack is a file upload from the browser. """ import re import time from subprocess import Popen, PIPE, STDOUT from Products.ZenUtils.Utils import get_temp_dir ZENPACK_INSTALL_TIMEOUT = 10 * 60 # 10 minutes if not getattr(self.dmd, "ZenPackManager"): msg = "Your Zenoss database appears to be out of date. Try " "running zenmigrate to update." if REQUEST: messaging.IMessageSender(self).sendToBrowser("Error", msg, priority=messaging.WARNING) return self.callZenScreen(REQUEST) from ZenPack import ZenPackNeedMigrateException raise ZenPackNeedMigrateException(msg) msg = "" with get_temp_dir() as tempDir: # zenpack.filename gives us filename of the zenpack with the # path as it exists on the client. We need just the filename. base_filename = re.split(r"\\|/", zenpack.filename)[-1] # Macs (and other broswers/OSs) always append a .zip to files they # believe to be zip files. Remedy that: if base_filename.endswith(".egg.zip"): base_filename = base_filename[:-7] + "egg" # Write the zenpack to the filesystem tFile = open(os.path.join(tempDir, base_filename), "wb") tFile.write(zenpack.read()) tFile.close() p = None # zenpack install process # ZEN-1781: Redirect to a temporary file so the stdout buffer # doesn't fill up and block till you read from it. outFile = None try: outFile = tempfile.SpooledTemporaryFile() # Run zenpack install cmd = "zenpack --install %s --fromui" % tFile.name p = Popen(cmd, shell=True, stdout=outFile, stderr=STDOUT) endWait = time.time() + ZENPACK_INSTALL_TIMEOUT # Wait for install to complete, fail, or time out while p.poll() is None and time.time() < endWait: time.sleep(1) if p.poll() is not None: outFile.seek(0) msg = outFile.read() finally: if outFile: outFile.close() if p and p.poll() is None: p.kill() msg += "Zenpack install killed due to timeout" if REQUEST: # TODO: show the output in a scrollable window. # format command result for HTML # msg = '<br>'.join(line.strip() for line in msg.split('\n') if line.strip()) log.info("Output from installing ZenPack %s:\n%s" % (zenpack.filename, msg)) success = "ERROR" not in msg msg = ( "Successfully installed ZenPack %s" % zenpack.filename if success else "Failed to install ZenPack %s. " "See event.log for details." % zenpack.filename ) messaging.IMessageSender(self).sendToBrowser( "Zenpack", msg, priority=messaging.INFO if success else messaging.CRITICAL ) return self.callZenScreen(REQUEST)
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 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: 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