1
2
3
4
5
6
7
8
9
10
11
12
13 __doc__ = "Manage ZenPacks"
14
15 import Globals
16 from Products.ZenModel.ZenPack import ZenPack, ZenPackException, \
17 ZenPackNeedMigrateException
18 from Products.ZenUtils.ZenScriptBase import ZenScriptBase
19 from Products.ZenUtils.Utils import cleanupSkins, zenPath
20 import transaction
21 from zipfile import ZipFile
22 from StringIO import StringIO
23 import ConfigParser
24 import Products.ZenModel.ZenPackLoader as ZPL
25 from Products.ZenModel.ZenPackLoader import CONFIG_FILE, CONFIG_SECTION_ABOUT
26 import os, sys
27 import ZenPackCmd as EggPackCmd
28
29
30 -def RemoveZenPack(dmd, packName, log=None,
31 skipDepsCheck=False, leaveObjects=True,
32 deleteFiles=True):
69
70
72 "Manage ZenPacks"
73
74
76 "Execute the user's request"
77 import Products
78 Products.Five.zcml.load_config('event.zcml', Products.Five)
79
80 if self.args:
81 print "Require one of --install, --remove or --list flags."
82 self.parser.print_help()
83 return
84
85 if self.options.installPackName:
86 eggInstall = (self.options.installPackName.lower().endswith('.egg')
87 or os.path.exists(os.path.join(self.options.installPackName,
88 'setup.py')))
89
90
91
92 class ZPProxy:
93 def __init__(self, zpId):
94 self.id = zpId
95 def path(self, *parts):
96 return zenPath('Products', self.id, *parts)
97 if self.options.installPackName and self.options.filesOnly:
98 if eggInstall:
99 return EggPackCmd.InstallZenPack(None,
100 self.options.installPackName,
101 filesOnly=True)
102 packName = self.extract(self.options.installPackName)
103 proxy = ZPProxy(packName)
104 for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()):
105 loader.load(proxy, None)
106 return
107 if self.options.removePackName and self.options.filesOnly:
108
109
110 proxy = ZPProxy(self.options.removePackName)
111 for loader in (ZPL.ZPLDaemons(), ZPL.ZPLBin(), ZPL.ZPLLibExec()):
112 loader.unload(proxy, None)
113 os.system('rm -rf %s' % zenPath('Products',
114 self.options.removePackName))
115 return
116
117
118
119 self.connect()
120
121 if not getattr(self.dmd, 'ZenPackManager', None):
122 raise ZenPackNeedMigrateException('Your Zenoss database appears'
123 ' to be out of date. Try running zenmigrate to update.')
124
125 if self.options.installPackName:
126 if eggInstall:
127 return EggPackCmd.InstallEggAndZenPack(
128 self.dmd,
129 self.options.installPackName,
130 link=self.options.link,
131 filesOnly=False,
132 previousVersion= self.options.previousVersion)
133 if not self.preInstallCheck():
134 self.stop('%s not installed' % self.options.installPackName)
135 if os.path.isfile(self.options.installPackName):
136 packName = self.extract(self.options.installPackName)
137 elif os.path.isdir(self.options.installPackName):
138 if self.options.link:
139 packName = self.linkDir(self.options.installPackName)
140 else:
141 packName = self.copyDir(self.options.installPackName)
142 else:
143 self.stop('%s does not appear to be a valid file or directory.'
144 % self.options.installPackName)
145
146
147
148
149
150 skinsSubdir = zenPath('Products', packName, 'skins', packName)
151 if not os.path.exists(skinsSubdir):
152 os.makedirs(skinsSubdir, 0750)
153 self.install(packName)
154
155
156
157
158 elif self.options.removePackName:
159 pack = self.dmd.ZenPackManager.packs._getOb(
160 self.options.removePackName, None)
161 if not pack:
162 raise ZenPackException('ZenPack %s is not installed.' %
163 self.options.removePackName)
164 if pack.isEggPack():
165 return EggPackCmd.RemoveZenPack(self.dmd,
166 self.options.removePackName)
167 RemoveZenPack(self.dmd, self.options.removePackName, self.log)
168
169 elif self.options.list:
170 for zpId in self.dmd.ZenPackManager.packs.objectIds():
171 try:
172 zp = self.dmd.ZenPackManager.packs._getOb(zpId, None)
173 except AttributeError:
174 zp = None
175 if not zp:
176 desc = 'broken'
177 elif zp.isEggPack():
178 desc = zp.eggPath()
179 else:
180 desc = zp.path()
181 print('%s (%s)' % (zpId, desc))
182
183 transaction.commit()
184
185
223
224
226 zp = None
227 try:
228 zp = self.dmd.ZenPackManager.packs._getOb(packName)
229 self.log.info('Upgrading %s' % packName)
230 zp.upgrade(self.app)
231 except AttributeError:
232 try:
233 module = __import__('Products.' + packName, globals(), {}, [''])
234 zp = module.ZenPack(packName)
235 except (ImportError, AttributeError), ex:
236 self.log.debug("Unable to find custom ZenPack (%s), "
237 "defaulting to generic ZenPack",
238 ex)
239 zp = ZenPack(packName)
240 self.dmd.ZenPackManager.packs._setObject(packName, zp)
241 zp = self.dmd.ZenPackManager.packs._getOb(packName)
242 zp.install(self.app)
243 if zp:
244 for required in zp.requires:
245 try:
246 self.dmd.ZenPackManager.packs._getOb(required)
247 except:
248 self.log.error("Pack %s requires pack %s: not installing",
249 packName, required)
250 return
251 transaction.commit()
252
254 "Unpack a ZenPack, and return the name"
255 if not os.path.isfile(fname):
256 self.stop('Unable to open file "%s"' % fname)
257 zf = ZipFile(fname)
258 name = zf.namelist()[0]
259 packName = name.split('/')[0]
260 self.log.debug('Extracting ZenPack "%s"' % packName)
261 for name in zf.namelist():
262 fullname = zenPath('Products', name)
263 self.log.debug('Extracting %s' % name)
264 if name.find('/.svn') > -1: continue
265 if name.endswith('~'): continue
266 if name.endswith('/'):
267 if not os.path.exists(fullname):
268 os.makedirs(fullname, 0750)
269 else:
270 base = os.path.dirname(fullname)
271 if not os.path.isdir(base):
272 os.makedirs(base, 0750)
273 file(fullname, 'wb').write(zf.read(name))
274 return packName
275
276
278 '''Copy an unzipped zenpack to the appropriate location.
279 Return the name.
280 '''
281
282 if srcDir.endswith('/'):
283 srcDir = srcDir[:-1]
284
285 if not os.path.isdir(srcDir):
286 self.stop('Specified directory does not appear to exist: %s' %
287 srcDir)
288
289
290 packName = os.path.split(srcDir)[1]
291 root = zenPath('Products', packName)
292
293
294 if os.path.exists(root) and os.path.samefile(root, srcDir):
295 self.log.debug('Directory already in %s, not copying.',
296 zenPath('Products'))
297 return packName
298
299
300 self.log.debug('Copying %s' % packName)
301 result = os.system('cp -r %s %s' % (srcDir, zenPath('Products')))
302 if result == -1:
303 self.stop('Error copying %s to %s' % (srcDir, zenPath('Products')))
304
305 return packName
306
307
309 '''Symlink the srcDir into Products
310 Return the name.
311 '''
312
313 if srcDir.endswith('/'):
314 srcDir = srcDir[:-1]
315
316
317 srcDir = os.path.abspath(srcDir)
318
319 if not os.path.isdir(srcDir):
320 self.stop('Specified directory does not appear to exist: %s' %
321 srcDir)
322
323
324 packName = os.path.split(srcDir)[1]
325 root = zenPath('Products', packName)
326
327
328 if os.path.exists(root) and os.path.samefile(root, srcDir):
329 self.log.debug('Directory already in %s, not copying.',
330 zenPath('Products'))
331 return packName
332
333 targetdir = zenPath("Products", packName)
334 cmd = 'test -d %s && rm -rf %s' % (targetdir, targetdir)
335 os.system(cmd)
336 cmd = 'ln -s %s %s' % (srcDir, zenPath("Products"))
337 os.system(cmd)
338
339 return packName
340
341
342 - def stop(self, why):
343 self.log.error("zenpack stopped: %s", why)
344 sys.exit(1)
345
346
348 self.parser.add_option('--install',
349 dest='installPackName',
350 default=None,
351 help="Path to the ZenPack to install.")
352
353
354
355
356
357
358
359
360
361
362 self.parser.add_option('--remove',
363 dest='removePackName',
364 default=None,
365 help="Name of the ZenPack to remove.")
366 self.parser.add_option('--list',
367 dest='list',
368 action="store_true",
369 default=False,
370 help='List installed ZenPacks')
371 self.parser.add_option('--link',
372 dest='link',
373 action="store_true",
374 default=False,
375 help="Install the ZenPack in place, without "
376 "copying into $ZENHOME/ZenPacks.")
377 self.parser.add_option('--files-only',
378 dest='filesOnly',
379 action="store_true",
380 default=False,
381 help='Install the ZenPack files onto the '
382 'filesystem, but do not install the '
383 'ZenPack into Zenoss.')
384 self.parser.add_option('--previousversion',
385 dest='previousVersion',
386 default=None,
387 help="Previous version of the zenpack;"
388 ' used during upgrades')
389
390 ZenScriptBase.buildOptions(self)
391
392 if __name__ == '__main__':
393 try:
394 zp = ZenPackCmd()
395 zp.run()
396 except Exception, e:
397 sys.stderr.write('ERROR: zenpack command failed. Reason: %s: %s\n' %
398 (e.__class__.__name__, e))
399 sys.exit(-1)
400