1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__="""ZenPackManager
15 ZenPackManager is a Zope Product that helps manage ZenPacks
16 """
17
18 from Globals import InitializeClass
19 from ZenModelRM import ZenModelRM
20 from Products.ZenRelations.RelSchema import *
21 from AccessControl import ClassSecurityInfo
22 from ZenossSecurity import ZEN_MANAGE_DMD
23 from Products.ZenUtils.Utils import binPath
24 from Products.ZenWidgets import messaging
25 import os
26
38
39
41 """
42 ZenPackManager is responsibe for managing ZenPacks
43 """
44
45 portal_type = meta_type = 'ZenPackManager'
46
47 default_catalog = 'zenPackNameSearch'
48
49 _relations = ZenModelRM._relations + (
50 ('packs', ToManyCont(ToOne, 'Products.ZenModel.ZenPack', 'manager')),
51 )
52
53 factory_type_information = (
54 {
55 'immediate_view' : 'viewZenPacks',
56 'actions' :
57 (
58 { 'id' : 'settings'
59 , 'name' : 'Settings'
60 , 'action' : '../editSettings'
61 , 'permissions' : ( "Manage DMD", )
62 },
63 { 'id' : 'manage'
64 , 'name' : 'Commands'
65 , 'action' : '../dataRootManage'
66 , 'permissions' : ('Manage DMD',)
67 },
68 { 'id' : 'users'
69 , 'name' : 'Users'
70 , 'action' : '../ZenUsers/manageUserFolder'
71 , 'permissions' : ( 'Manage DMD', )
72 },
73 { 'id' : 'packs'
74 , 'name' : 'ZenPacks'
75 , 'action' : 'viewZenPacks'
76 , 'permissions' : ( "Manage DMD", )
77 },
78 { 'id' : 'jobs'
79 , 'name' : 'Jobs'
80 , 'action' : '../joblist'
81 , 'permissions' : ( "Manage DMD", )
82 },
83
84
85
86
87
88 { 'id' : 'portlets'
89 , 'name' : 'Portlets'
90 , 'action' : '../editPortletPerms'
91 , 'permissions' : ( "Manage DMD", )
92 },
93 { 'id' : 'daemons'
94 , 'name' : 'Daemons'
95 , 'action' : '../About/zenossInfo'
96 , 'permissions' : ( "Manage DMD", )
97 },
98 { 'id' : 'versions'
99 , 'name' : 'Versions'
100 , 'action' : '../About/zenossVersions'
101 , 'permissions' : ( "Manage DMD", )
102 },
103 { 'id' : 'backups'
104 , 'name' : 'Backups'
105 , 'action' : '../backupInfo'
106 , 'permissions' : ( "Manage DMD", )
107 },
108 { 'id' : 'eventConfig'
109 , 'name' : 'Events'
110 , 'action' : 'eventConfig'
111 , 'permissions' : ( "Manage DMD", )
112 },
113 )
114 },
115 )
116
117 security = ClassSecurityInfo()
118
119
120 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addZenPack')
122 """
123 Create a new zenpack on the filesystem with the given info.
124 Install the pack. If REQUEST then render the REQUEST otherwise
125 return the new zenpack.
126 """
127 import Products.ZenUtils.ZenPackCmd as ZenPackCmd
128
129 if not getattr(self.dmd, 'ZenPackManager'):
130 msg = 'Your Zenoss database appears to be out of date. Try ' \
131 'running zenmigrate to update.'
132 if REQUEST:
133 messaging.IMessageSender(self).sendToBrowser(
134 'Error', msg, priority=messaging.WARNING)
135 return self.callZenScreen(REQUEST)
136 from ZenPack import ZenPackNeedMigrateException
137 raise ZenPackNeedMigrateException(msg)
138
139
140 canCreate, msgOrId = ZenPackCmd.CanCreateZenPack(self, packId)
141 if canCreate:
142 packId = msgOrId
143 else:
144 if REQUEST:
145 messaging.IMessageSender(self).sendToBrowser(
146 'Add ZenPack', msgOrId)
147 return self.callZenScreen(REQUEST, redirect=False)
148 from ZenPack import ZenPackException
149 raise ZenPackException(msgOrId)
150
151
152 zpDir = ZenPackCmd.CreateZenPack(packId)
153
154
155 zenPacks = ZenPackCmd.InstallEggAndZenPack(self.dmd, zpDir, link=True,
156 forceRunExternal=True)
157 zenPack = self.packs._getOb(packId, None)
158 if REQUEST:
159 if zenPack:
160 return REQUEST['RESPONSE'].redirect(zenPack.getPrimaryUrlPath())
161 messaging.IMessageSender(self).sendToBrowser(
162 'Error', 'There was an error creating the ZenPack.',
163 priority=messaging.WARNING)
164 return self.callZenScreen(REQUEST)
165 return zenPack
166
167
168 security.declareProtected(ZEN_MANAGE_DMD, 'manage_removeZenPacks')
170 """
171 Uninstall the given zenpacks. Uninstall the zenpack egg. If not in
172 development mode then also delete the egg from the filesystem.
173 """
174 import Products.ZenUtils.ZenPackCmd as ZenPackCmd
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 else:
202 os.system('%s --remove %s' % (
203 binPath('zenpack'), zpId))
204 self._p_jar.sync()
205 if REQUEST:
206 return self.callZenScreen(REQUEST)
207
208
209 security.declareProtected(ZEN_MANAGE_DMD, 'fetchZenPack')
219
220
221
222 security.declareProtected(ZEN_MANAGE_DMD, 'manage_installZenPack')
224 """
225 Installs the given zenpack. Zenpack is a file upload from the browser.
226 """
227 import os
228 import re
229 from subprocess import Popen, PIPE, STDOUT
230 import time
231
232 from Products.ZenUtils.Utils import get_temp_dir
233
234 ZENPACK_INSTALL_TIMEOUT = 10 * 60
235
236 if not getattr(self.dmd, 'ZenPackManager'):
237 msg = 'Your Zenoss database appears to be out of date. Try ' \
238 'running zenmigrate to update.'
239 if REQUEST:
240 messaging.IMessageSender(self).sendToBrowser(
241 'Error', msg, priority=messaging.WARNING)
242 return self.callZenScreen(REQUEST)
243 from ZenPack import ZenPackNeedMigrateException
244 raise ZenPackNeedMigrateException(msg)
245
246 msg = ''
247 with get_temp_dir() as tempDir:
248
249
250 base_filename = re.split(r"\\|/", zenpack.filename)[-1]
251
252
253 if base_filename.endswith('.egg.zip'):
254 base_filename = base_filename[:-7] + 'egg'
255
256
257 tFile = open(os.path.join(tempDir, base_filename), 'wb')
258 tFile.write(zenpack.read())
259 tFile.close()
260
261 p = None
262 try:
263
264 cmd = 'zenpack --install %s' % tFile.name
265 p = Popen(cmd, shell=True, stdout=PIPE, stderr=STDOUT)
266 endWait = time.time() + ZENPACK_INSTALL_TIMEOUT
267
268 while p.poll() is None and time.time() < endWait:
269 time.sleep(1)
270 if p.poll() is not None:
271 msg = p.stdout.read()
272 finally:
273 if p and p.poll() is None:
274 p.kill()
275 msg += 'Zenpack install killed due to timeout'
276
277 if REQUEST:
278
279 msg = '<br>'.join(line.strip() for line in msg.split('\n') if line.strip())
280 messaging.IMessageSender(self).sendToBrowser('Zenpack', msg,
281 priority = messaging.CRITICAL if 'ERROR' in msg
282 else messaging.INFO)
283 return self.callZenScreen(REQUEST)
284
285
287 """
288 Return a list of 2-tuples of (option value, option name) for the
289 user to select a Zenoss.net project from.
290 """
291 projects = self.getZnetProjectsList()
292 return [(p, p.split('/')[-1]) for p in projects]
293
294
308
309
311 ''' Extract the zenpack name from the broken module
312 '''
313 return ob.id if ob.id else ob.__class__.__module__
314
315
316 InitializeClass(ZenPackManager)
317