Package ZenUtils :: Module zenpack
[hide private]
[frames] | no frames]

Source Code for Module ZenUtils.zenpack

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13  __doc__ = "Manage ZenPacks" 
 14   
 15  import Globals 
 16  from Products.ZenModel.ZenPack import ZenPack, zenPackPath 
 17  from Products.ZenUtils.ZenScriptBase import ZenScriptBase 
 18  from Products.ZenUtils.Utils import cleanupSkins, zenPath 
 19  import transaction 
 20  from zipfile import ZipFile 
 21  from StringIO import StringIO 
 22  import ConfigParser 
 23  from Products.ZenModel.ZenPackLoader import CONFIG_FILE, CONFIG_SECTION_ABOUT 
 24  import os, sys 
 25  import os.path 
 26   
27 -class ZenPackCmd(ZenScriptBase):
28 "Manage ZenPacks" 29 30
31 - def run(self):
32 "Execute the user's request" 33 self.connect() 34 if self.options.installPackName: 35 if not self.preInstallCheck(): 36 self.stop('%s not installed' % self.options.installPackName) 37 if os.path.isfile(self.options.installPackName): 38 packName = self.extract(self.options.installPackName) 39 elif os.path.isdir(self.options.installPackName): 40 if self.options.link: 41 packName = self.linkDir(self.options.installPackName) 42 else: 43 packName = self.copyDir(self.options.installPackName) 44 else: 45 self.stop('%s does not appear to be a valid file or directory.' 46 % self.options.installPackName) 47 # We want to make sure all zenpacks have a skins directory and that it 48 # is registered. The zip file may not contain a skins directory, so we 49 # create one here if need be. The directory should be registered 50 # by the zenpack's __init__.py and the skin should be registered 51 # by ZPLSkins loader. 52 skinsSubdir = zenPath('Products', packName, 'skins', packName) 53 if not os.path.exists(skinsSubdir): 54 os.makedirs(skinsSubdir) 55 self.install(packName) 56 57 elif self.options.removePackName: 58 self.remove(self.options.removePackName) 59 60 elif self.options.list: 61 for zp in self.dmd.packs(): 62 f = sys.modules[zp.__module__].__file__ 63 if f.endswith('.pyc'): 64 f = f[:-1] 65 print '%s (%s)' % (zp.id, f) 66 for extensionType, lst in zp.list(self.app): 67 print ' %s:' % extensionType 68 for item in lst: 69 print ' %s' % item 70 71 transaction.commit()
72 73
74 - def preInstallCheck(self):
75 ''' Check that prerequisite zenpacks are installed. 76 Return True if no prereqs specified or if they are present. 77 False otherwise. 78 ''' 79 if os.path.isfile(self.options.installPackName): 80 zf = ZipFile(self.options.installPackName) 81 for name in zf.namelist(): 82 if name.endswith == '/%s' % CONFIG_FILE: 83 sio = StringIO(zf.read()) 84 else: 85 return True 86 else: 87 name = os.path.join(self.options.installPackName, CONFIG_FILE) 88 if os.path.isfile(name): 89 fp = open(name) 90 sio = StringIO(fp.read()) 91 fp.close() 92 else: 93 return True 94 95 parser = ConfigParser.SafeConfigParser() 96 parser.readfp(sio, name) 97 if parser.has_section(CONFIG_SECTION_ABOUT) \ 98 and parser.has_option(CONFIG_SECTION_ABOUT, 'requires'): 99 requires = eval(parser.get(CONFIG_SECTION_ABOUT, 'requires')) 100 if not isinstance(requires, list): 101 requires = [zp.strip() for zp in requires.split(',')] 102 missing = [zp for zp in requires 103 if zp not in self.dataroot.packs.objectIds()] 104 if missing: 105 self.log.error('ZenPack %s was not installed because' 106 % self.options.installPackName 107 + ' it requires the following ZenPack(s): %s' 108 % ', '.join(missing)) 109 return False 110 return True
111 112
113 - def install(self, packName):
114 zp = None 115 try: 116 zp = self.dmd.packs._getOb(packName) 117 self.log.info('Upgrading %s' % packName) 118 zp.upgrade(self.app) 119 except AttributeError: 120 try: 121 module = __import__('Products.' + packName, globals(), {}, ['']) 122 zp = module.ZenPack(packName) 123 except (ImportError, AttributeError), ex: 124 self.log.debug("Unable to find custom ZenPack (%s), " 125 "defaulting to generic ZenPack", 126 ex) 127 zp = ZenPack(packName) 128 self.dmd.packs._setObject(packName, zp) 129 zp.install(self.app) 130 if zp: 131 for required in zp.requires: 132 try: 133 self.packs._getOb(required) 134 except: 135 self.log.error("Pack %s requires pack %s: not installing", 136 packName, required) 137 return 138 transaction.commit()
139
140 - def remove(self, packName):
141 self.log.debug('Removing Pack "%s"' % packName) 142 foundIt = False 143 for pack in self.dmd.packs(): 144 if packName in pack.requires: 145 self.log.error("Pack %s depends on pack %s, not removing", 146 pack.id, packName) 147 return 148 zp = None 149 try: 150 zp = self.dmd.packs._getOb(packName) 151 except AttributeError, ex: 152 # Pack not in zeo, might still exist in filesystem 153 self.log.debug('No ZenPack named %s in zeo' % packName) 154 if zp: 155 zp.remove(self.app) 156 self.dmd.packs._delObject(packName) 157 root = zenPackPath(packName) 158 self.log.debug('Removing %s' % root) 159 recurse = "" 160 if os.path.isdir(root): 161 recurse = "r" 162 os.system('rm -%sf %s' % (recurse, root)) 163 cleanupSkins(self.dmd)
164 165
166 - def extract(self, fname):
167 "Unpack a ZenPack, and return the name" 168 if not os.path.isfile(fname): 169 self.stop('Unable to open file "%s"' % fname) 170 zf = ZipFile(fname) 171 name = zf.namelist()[0] 172 packName = name.split('/')[0] 173 root = zenPackPath(packName) 174 self.log.debug('Extracting ZenPack "%s"' % packName) 175 for name in zf.namelist(): 176 fullname = zenPath('Products', name) 177 self.log.debug('Extracting %s' % name) 178 if name.find('/.svn') > -1: continue 179 if name.endswith('~'): continue 180 if name.endswith('/'): 181 if not os.path.exists(fullname): 182 os.makedirs(fullname, 0750) 183 else: 184 base = os.path.dirname(fullname) 185 if not os.path.isdir(base): 186 os.makedirs(base, 0750) 187 file(fullname, 'wb').write(zf.read(name)) 188 return packName
189 190
191 - def copyDir(self, srcDir):
192 '''Copy an unzipped zenpack to the appropriate location. 193 Return the name. 194 ''' 195 # Normalize srcDir to not end with slash 196 if srcDir.endswith('/'): 197 srcDir = srcDir[:-1] 198 199 if not os.path.isdir(srcDir): 200 self.stop('Specified directory does not appear to exist: %s' % 201 srcDir) 202 203 # Determine name of pack and it's destination directory 204 packName = os.path.split(srcDir)[1] 205 root = zenPackPath(packName) 206 207 # Continue without copying if the srcDir is already in Products 208 if os.path.exists(root) and os.path.samefile(root, srcDir): 209 self.log.debug('Directory already in %s, not copying.', 210 zenPath('Products')) 211 return packName 212 213 # Copy the source dir over to Products 214 self.log.debug('Copying %s' % packName) 215 result = os.system('cp -r %s %s' % (srcDir, zenPath('Products'))) 216 if result == -1: 217 self.stop('Error copying %s to %s' % (srcDir, zenPath('Products'))) 218 219 return packName
220 221
222 - def linkDir(self, srcDir):
223 '''Symlink the srcDir into Products 224 Return the name. 225 ''' 226 # Normalize srcDir to not end with slash 227 if srcDir.endswith('/'): 228 srcDir = srcDir[:-1] 229 230 # Need absolute path for links 231 srcDir = os.path.abspath(srcDir) 232 233 if not os.path.isdir(srcDir): 234 self.stop('Specified directory does not appear to exist: %s' % 235 srcDir) 236 237 # Determine name of pack and it's destination directory 238 packName = os.path.split(srcDir)[1] 239 root = zenPackPath(packName) 240 241 # Continue without copying if the srcDir is already in Products 242 if os.path.exists(root) and os.path.samefile(root, srcDir): 243 self.log.debug('Directory already in %s, not copying.', 244 zenPath('Products')) 245 return packName 246 247 targetdir = zenPath("Products", packName) 248 cmd = 'test -d %s && rm -rf %s' % (targetdir, targetdir) 249 r = os.system(cmd) 250 cmd = 'ln -s %s %s' % (srcDir, zenPath("Products")) 251 r = os.system(cmd) 252 253 return packName
254 255
256 - def stop(self, why):
257 self.log.error("zenpack stopped: %s", why) 258 import sys 259 sys.exit(1)
260 261
262 - def buildOptions(self):
263 self.parser.add_option('--install', 264 dest='installPackName', 265 default=None, 266 help="name of the pack to install") 267 self.parser.add_option('--remove', 268 dest='removePackName', 269 default=None, 270 help="name of the pack to remove") 271 self.parser.add_option('--list', 272 dest='list', 273 action="store_true", 274 default=False, 275 help="list installed zenpacks" 276 " and associated files") 277 self.parser.add_option('--link', 278 dest='link', 279 action="store_true", 280 default=False, 281 help="symlink the zenpack dir instead of" 282 " copying to $ZENHOME/Products") 283 ZenScriptBase.buildOptions(self)
284 285 if __name__ == '__main__': 286 zp = ZenPackCmd() 287 zp.run() 288