1
2
3
4
5
6
7
8
9
10
11 __doc__="""ZenPackManager
12 ZenPackManager is a Zope Product that helps manage ZenPacks
13 """
14
15 from Globals import InitializeClass
16 from ZenModelRM import ZenModelRM
17 from Products.ZenRelations.RelSchema import *
18 from AccessControl import ClassSecurityInfo
19 from ZenossSecurity import ZEN_MANAGE_DMD
20 from Products.ZenMessaging.audit import audit
21 from Products.ZenUtils.Utils import binPath
22 from Products.ZenWidgets import messaging
23 import os
24 import tempfile
25 import logging
26
27 log = logging.getLogger('zen.ZenPackManager')
28
40
41
43 """
44 ZenPackManager is responsibe for managing ZenPacks
45 """
46
47 portal_type = meta_type = 'ZenPackManager'
48
49 default_catalog = 'zenPackNameSearch'
50
51 _relations = ZenModelRM._relations + (
52 ('packs', ToManyCont(ToOne, 'Products.ZenModel.ZenPack', 'manager')),
53 )
54
55 factory_type_information = (
56 {
57 'immediate_view' : 'viewZenPacks',
58 'actions' :
59 (
60 { 'id' : 'settings'
61 , 'name' : 'Settings'
62 , 'action' : '../editSettings'
63 , 'permissions' : ( "Manage DMD", )
64 },
65 { 'id' : 'manage'
66 , 'name' : 'Commands'
67 , 'action' : '../dataRootManage'
68 , 'permissions' : ('Manage DMD',)
69 },
70 { 'id' : 'users'
71 , 'name' : 'Users'
72 , 'action' : '../ZenUsers/manageUserFolder'
73 , 'permissions' : ( 'Manage DMD', )
74 },
75 { 'id' : 'packs'
76 , 'name' : 'ZenPacks'
77 , 'action' : 'viewZenPacks'
78 , 'permissions' : ( "Manage DMD", )
79 },
80 { 'id' : 'portlets'
81 , 'name' : 'Portlets'
82 , 'action' : '../editPortletPerms'
83 , 'permissions' : ( "Manage DMD", )
84 },
85 { 'id' : 'daemons'
86 , 'name' : 'Daemons'
87 , 'action' : '../About/zenossInfo'
88 , 'permissions' : ( "Manage DMD", )
89 },
90 { 'id' : 'versions'
91 , 'name' : 'Versions'
92 , 'action' : '../About/zenossVersions'
93 , 'permissions' : ( "Manage DMD", )
94 },
95 { 'id' : 'backups'
96 , 'name' : 'Backups'
97 , 'action' : '../backupInfo'
98 , 'permissions' : ( "Manage DMD", )
99 },
100 { 'id' : 'eventConfig'
101 , 'name' : 'Events'
102 , 'action' : 'eventConfig'
103 , 'permissions' : ( "Manage DMD", )
104 },
105 { 'id' : 'userInterfaceConfig'
106 , 'name' : 'User Interface'
107 , 'action' : '../userInterfaceConfig'
108 , 'permissions' : ( "Manage DMD", )
109 },
110 )
111 },
112 )
113
114 security = ClassSecurityInfo()
115
116
117 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addZenPack')
119 """
120 Create a new zenpack on the filesystem with the given info.
121 Install the pack. If REQUEST then render the REQUEST otherwise
122 return the new zenpack.
123 """
124 import Products.ZenUtils.ZenPackCmd as ZenPackCmd
125
126 if not getattr(self.dmd, 'ZenPackManager'):
127 msg = 'Your Zenoss database appears to be out of date. Try ' \
128 'running zenmigrate to update.'
129 if REQUEST:
130 messaging.IMessageSender(self).sendToBrowser(
131 'Error', msg, priority=messaging.WARNING)
132 return self.callZenScreen(REQUEST)
133 from ZenPack import ZenPackNeedMigrateException
134 raise ZenPackNeedMigrateException(msg)
135
136
137 canCreate, msgOrId = ZenPackCmd.CanCreateZenPack(self, packId)
138 if canCreate:
139 packId = msgOrId
140 else:
141 if REQUEST:
142 messaging.IMessageSender(self).sendToBrowser(
143 'Add ZenPack', msgOrId)
144 return self.callZenScreen(REQUEST, redirect=False)
145 from ZenPack import ZenPackException
146 raise ZenPackException(msgOrId)
147
148
149 zpDir = ZenPackCmd.CreateZenPack(packId)
150
151
152 zenPacks = ZenPackCmd.InstallEggAndZenPack(self.dmd, zpDir, link=True,
153 forceRunExternal=True)
154 zenPack = self.packs._getOb(packId, None)
155 audit('UI.ZenPack.Create', packId)
156 if REQUEST:
157 if zenPack:
158 return REQUEST['RESPONSE'].redirect(zenPack.getPrimaryUrlPath())
159 messaging.IMessageSender(self).sendToBrowser(
160 'Error', 'There was an error creating the ZenPack.',
161 priority=messaging.WARNING)
162 return self.callZenScreen(REQUEST)
163 return zenPack
164
165
166 security.declareProtected(ZEN_MANAGE_DMD, 'manage_removeZenPacks')
168 """
169 Uninstall the given zenpacks. Uninstall the zenpack egg. If not in
170 development mode then also delete the egg from the filesystem.
171 """
172 import Products.ZenUtils.ZenPackCmd as ZenPackCmd
173
174 from Products.ZenMessaging.queuemessaging.schema import removeZenPackQueuesExchanges
175
176 if not getattr(self.dmd, 'ZenPackManager'):
177 msg = 'Your Zenoss database appears to be out of date. Try ' \
178 'running zenmigrate to update.'
179 if REQUEST:
180 messaging.IMessageSender(self).sendToBrowser(
181 'Error', msg, priority=messaging.WARNING)
182 return self.callZenScreen(REQUEST)
183 from ZenPack import ZenPackNeedMigrateException
184 raise ZenPackNeedMigrateException(msg)
185
186 canRemove, dependents = ZenPackCmd.CanRemoveZenPacks(self.dmd, ids)
187 if not canRemove:
188 msg = 'The following ZenPacks depend on one or more of the ' + \
189 ' ZenPacks you are trying to remove: %s' % ','.join(dependents)
190 if REQUEST:
191 messaging.IMessageSender(self).sendToBrowser(
192 'Error', msg, priority=messaging.WARNING)
193 return self.callZenScreen(REQUEST)
194 from ZenPack import ZenPackDependentsException
195 raise ZenPackDependentsException(msg)
196 for zpId in ids:
197 zp = self.packs._getOb(zpId, None)
198 if zp:
199 if zp.isEggPack():
200 ZenPackCmd.RemoveZenPack(self.dmd, zpId, skipDepsCheck=True)
201 audit('UI.ZenPack.Remove', zpId)
202 else:
203 os.system('%s --remove %s' % (
204 binPath('zenpack'), zpId))
205 self._p_jar.sync()
206
207 removeZenPackQueuesExchanges(zp.path())
208 if REQUEST:
209 return self.callZenScreen(REQUEST)
210
211
212 security.declareProtected(ZEN_MANAGE_DMD, 'fetchZenPack')
222
223
224
225 security.declareProtected(ZEN_MANAGE_DMD, 'manage_installZenPack')
227 """
228 Installs the given zenpack. Zenpack is a file upload from the browser.
229 """
230 import re
231 import time
232 from subprocess import Popen, PIPE, STDOUT
233
234 from Products.ZenUtils.Utils import get_temp_dir
235
236 ZENPACK_INSTALL_TIMEOUT = 10 * 60
237
238 if not getattr(self.dmd, 'ZenPackManager'):
239 msg = 'Your Zenoss database appears to be out of date. Try ' \
240 'running zenmigrate to update.'
241 if REQUEST:
242 messaging.IMessageSender(self).sendToBrowser(
243 'Error', msg, priority=messaging.WARNING)
244 return self.callZenScreen(REQUEST)
245 from ZenPack import ZenPackNeedMigrateException
246 raise ZenPackNeedMigrateException(msg)
247
248 msg = ''
249 with get_temp_dir() as tempDir:
250
251
252 base_filename = re.split(r"\\|/", zenpack.filename)[-1]
253
254
255 if base_filename.endswith('.egg.zip'):
256 base_filename = base_filename[:-7] + 'egg'
257
258
259 tFile = open(os.path.join(tempDir, base_filename), 'wb')
260 tFile.write(zenpack.read())
261 tFile.close()
262
263 p = None
264
265
266 outFile = None
267 try:
268 outFile = tempfile.SpooledTemporaryFile()
269
270 cmd = 'zenpack --install %s --fromui' % tFile.name
271 p = Popen(cmd, shell=True, stdout=outFile, stderr=STDOUT)
272
273 endWait = time.time() + ZENPACK_INSTALL_TIMEOUT
274
275 while p.poll() is None and time.time() < endWait:
276 time.sleep(1)
277
278 if p.poll() is not None:
279 outFile.seek(0)
280 msg = outFile.read()
281 finally:
282 if outFile:
283 outFile.close()
284 if p and p.poll() is None:
285 p.kill()
286 msg += 'Zenpack install killed due to timeout'
287
288 if REQUEST:
289
290
291
292 log.info("Output from installing ZenPack %s:\n%s" % (zenpack.filename, msg))
293 success = 'ERROR' not in msg
294 msg = "Successfully installed ZenPack %s" % zenpack.filename if success \
295 else "Failed to install ZenPack %s. " \
296 "See event.log for details." % zenpack.filename
297 messaging.IMessageSender(self).sendToBrowser('Zenpack', msg,
298 priority = messaging.INFO if success else messaging.CRITICAL)
299 return self.callZenScreen(REQUEST)
300
301
303 """
304 Return a list of 2-tuples of (option value, option name) for the
305 user to select a Zenoss.net project from.
306 """
307 projects = self.getZnetProjectsList()
308 return [(p, p.split('/')[-1]) for p in projects]
309
310
324
325
327 ''' Extract the zenpack name from the broken module
328 '''
329 return ob.id if ob.id and ob.id != 'broken' else ob.__class__.__module__
330
331
332 InitializeClass(ZenPackManager)
333