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 { 'id' : 'menus'
84 , 'name' : 'Menus'
85 , 'action' : '../editMenus'
86 , 'permissions' : ( "Manage DMD", )
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 )
109 },
110 )
111
112 security = ClassSecurityInfo()
113
114
115 security.declareProtected(ZEN_MANAGE_DMD, 'manage_addZenPack')
117 """
118 Create a new zenpack on the filesystem with the given info.
119 Install the pack. If REQUEST then render the REQUEST otherwise
120 return the new zenpack.
121 """
122 import Products.ZenUtils.ZenPackCmd as ZenPackCmd
123
124 if not getattr(self.dmd, 'ZenPackManager'):
125 msg = 'Your Zenoss database appears to be out of date. Try ' \
126 'running zenmigrate to update.'
127 if REQUEST:
128 messaging.IMessageSender(self).sendToBrowser(
129 'Error', msg, priority=messaging.WARNING)
130 return self.callZenScreen(REQUEST)
131 from ZenPack import ZenPackNeedMigrateException
132 raise ZenPackNeedMigrateException(msg)
133
134
135 canCreate, msgOrId = ZenPackCmd.CanCreateZenPack(self, packId)
136 if canCreate:
137 packId = msgOrId
138 else:
139 if REQUEST:
140 messaging.IMessageSender(self).sendToBrowser(
141 'Add ZenPack', msgOrId)
142 return self.callZenScreen(REQUEST, redirect=False)
143 from ZenPack import ZenPackException
144 raise ZenPackException(msgOrId)
145
146
147 zpDir = ZenPackCmd.CreateZenPack(packId)
148
149
150 zenPacks = ZenPackCmd.InstallEggAndZenPack(self.dmd, zpDir, link=True)
151 zenPack = self.packs._getOb(packId, None)
152 if REQUEST:
153 if zenPack:
154 return REQUEST['RESPONSE'].redirect(zenPack.getPrimaryUrlPath())
155 messaging.IMessageSender(self).sendToBrowser(
156 'Error', 'There was an error creating the ZenPack.',
157 priority=messaging.WARNING)
158 return self.callZenScreen(REQUEST)
159 return zenPack
160
161
162 security.declareProtected(ZEN_MANAGE_DMD, 'manage_removeZenPacks')
164 """
165 Uninstall the given zenpacks. Uninstall the zenpack egg. If not in
166 development mode then also delete the egg from the filesystem.
167 """
168 import Products.ZenUtils.ZenPackCmd as ZenPackCmd
169
170 if not getattr(self.dmd, 'ZenPackManager'):
171 msg = 'Your Zenoss database appears to be out of date. Try ' \
172 'running zenmigrate to update.'
173 if REQUEST:
174 messaging.IMessageSender(self).sendToBrowser(
175 'Error', msg, priority=messaging.WARNING)
176 return self.callZenScreen(REQUEST)
177 from ZenPack import ZenPackNeedMigrateException
178 raise ZenPackNeedMigrateException(msg)
179
180 canRemove, dependents = ZenPackCmd.CanRemoveZenPacks(self.dmd, ids)
181 if not canRemove:
182 msg = 'The following ZenPacks depend on one or more of the ' + \
183 ' ZenPacks you are trying to remove: %s' % ','.join(dependents)
184 if REQUEST:
185 messaging.IMessageSender(self).sendToBrowser(
186 'Error', msg, priority=messaging.WARNING)
187 return self.callZenScreen(REQUEST)
188 from ZenPack import ZenPackDependentsException
189 raise ZenPackDependentsException(msg)
190 for zpId in ids:
191 zp = self.packs._getOb(zpId, None)
192 if zp:
193 if zp.isEggPack():
194 ZenPackCmd.RemoveZenPack(self.dmd, zpId, skipDepsCheck=True)
195 else:
196 os.system('%s --remove %s' % (
197 binPath('zenpack'), zpId))
198 self._p_jar.sync()
199 if REQUEST:
200 return self.callZenScreen(REQUEST)
201
202
203 security.declareProtected(ZEN_MANAGE_DMD, 'fetchZenPack')
213
214
215
216 security.declareProtected(ZEN_MANAGE_DMD, 'manage_installZenPack')
218 """
219 Installs the given zenpack. Zenpack is a file upload from the browser.
220 """
221 import tempfile
222 import fcntl
223 import popen2
224 import signal
225 import time
226 import select
227
228 ZENPACK_INSTALL_TIMEOUT = 120
229
230 if not getattr(self.dmd, 'ZenPackManager'):
231 msg = 'Your Zenoss database appears to be out of date. Try ' \
232 'running zenmigrate to update.'
233 if REQUEST:
234 messaging.IMessageSender(self).sendToBrowser(
235 'Error', msg, priority=messaging.WARNING)
236 return self.callZenScreen(REQUEST)
237 from ZenPack import ZenPackNeedMigrateException
238 raise ZenPackNeedMigrateException(msg)
239
240 if REQUEST:
241 REQUEST['cmd'] = ''
242 header, footer = self.commandOutputTemplate().split('OUTPUT_TOKEN')
243 REQUEST.RESPONSE.write(str(header))
244 out = REQUEST.RESPONSE
245 else:
246 out = None
247
248 tFile = None
249 child = None
250 try:
251 try:
252
253 tDir = tempfile.gettempdir()
254 tFile = open(os.path.join(tDir, zenpack.filename), 'wb')
255 tFile.write(zenpack.read())
256 tFile.close()
257
258 cmd = 'zenpack --install %s' % tFile.name
259 child = popen2.Popen4(cmd)
260 flags = fcntl.fcntl(child.fromchild, fcntl.F_GETFL)
261 fcntl.fcntl(child.fromchild, fcntl.F_SETFL, flags | os.O_NDELAY)
262 endtime = time.time() + ZENPACK_INSTALL_TIMEOUT
263 self.write(out, '%s' % cmd)
264 self.write(out, '')
265 pollPeriod = 1
266 firstPass = True
267 while time.time() < endtime and (firstPass or child.poll()==-1):
268 firstPass = False
269 r, w, e = select.select([child.fromchild],[],[], pollPeriod)
270 if r:
271 t = child.fromchild.read()
272
273
274
275 if t:
276 self.write(out, t)
277 if child.poll() == -1:
278 self.write(out,
279 'Command timed out for %s' % cmd +
280 ' (timeout is %s seconds)' %
281 ZENPACK_INSTALL_TIMEOUT)
282 except:
283 self.write(out, 'Error installing ZenPack.')
284 self.write(
285 out, 'type: %s value: %s' % tuple(sys.exc_info()[:2]))
286 self.write(out, '')
287 finally:
288 if child and child.poll() == -1:
289 os.kill(child.pid, signal.SIGKILL)
290
291 self.write(out, '')
292 self.write(out, 'Done installing ZenPack.')
293 if REQUEST:
294 REQUEST.RESPONSE.write(footer)
295
296
298 """
299 Return a list of 2-tuples of (option value, option name) for the
300 user to select a Zenoss.net project from.
301 """
302 projects = self.getZnetProjectsList()
303 return [(p, p.split('/')[-1]) for p in projects]
304
305
319
320
322 ''' Extract the zenpack name from the broken module
323 '''
324 return ob.__class__.__module__
325
326
327 InitializeClass(ZenPackManager)
328