Package Products :: Package ZenModel :: Module ZenPackManager
[hide private]
[frames] | no frames]

Source Code for Module Products.ZenModel.ZenPackManager

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2008, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  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   
29 -def manage_addZenPackManager(context, newId='', REQUEST=None):
30 """ 31 Create a ZenPackManager instance 32 """ 33 if not newId: 34 newId = 'ZenPackManager' 35 zpm = ZenPackManager(newId) 36 context._setObject(newId, zpm) 37 zpm = context._getOb(newId) 38 if REQUEST is not None: 39 REQUEST.RESPONSE.redirect(context.absolute_url() + '/manage_main')
40 41
42 -class ZenPackManager(ZenModelRM):
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')
118 - def manage_addZenPack(self, packId, REQUEST=None):
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 # Make sure a zenpack can be created with given info 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 # Create it 149 zpDir = ZenPackCmd.CreateZenPack(packId) 150 151 # Install it 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')
167 - def manage_removeZenPacks(self, ids=(), REQUEST=None):
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 # avoid circular imports 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')
213 - def fetchZenPack(self, packName, packVersion=''):
214 """ 215 Retrieve the given zenpack from Zenoss.net and install. 216 """ 217 import Products.ZenUtils.ZenPackCmd as ZenPackCmd 218 zp = ZenPackCmd.FetchAndInstallZenPack(self.dmd, packName, packVersion) 219 if REQUEST: 220 return REQUEST['RESPONSE'].redirect(zp.getPrimaryUrlPath()) 221 return zp
222 223 224 225 security.declareProtected(ZEN_MANAGE_DMD, 'manage_installZenPack')
226 - def manage_installZenPack(self, zenpack=None, REQUEST=None):
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 # 10 minutes 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 # zenpack.filename gives us filename of the zenpack with the 251 # path as it exists on the client. We need just the filename. 252 base_filename = re.split(r"\\|/", zenpack.filename)[-1] 253 # Macs (and other broswers/OSs) always append a .zip to files they 254 # believe to be zip files. Remedy that: 255 if base_filename.endswith('.egg.zip'): 256 base_filename = base_filename[:-7] + 'egg' 257 258 # Write the zenpack to the filesystem 259 tFile = open(os.path.join(tempDir, base_filename), 'wb') 260 tFile.write(zenpack.read()) 261 tFile.close() 262 263 p = None # zenpack install process 264 # ZEN-1781: Redirect to a temporary file so the stdout buffer 265 # doesn't fill up and block till you read from it. 266 outFile = None 267 try: 268 outFile = tempfile.SpooledTemporaryFile() 269 # Run zenpack install 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 # Wait for install to complete, fail, or time out 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 # TODO: show the output in a scrollable window. 290 # format command result for HTML 291 #msg = '<br>'.join(line.strip() for line in msg.split('\n') if line.strip()) 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
302 - def getZnetProjectOptions(self):
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
311 - def getZnetProjectsList(self):
312 """ 313 Return a list of the zenoss.net projects. 314 """ 315 import json 316 import Products.ZenUtils.DotNetCommunication as DotNetCommunication 317 userSettings = self.dmd.ZenUsers.getUserSettings() 318 session = DotNetCommunication.getDotNetSession( 319 userSettings.zenossNetUser, 320 userSettings.zenossNetPassword) 321 projects = session.retrieve('projectList') 322 projects = json.loads(projects) 323 return projects
324 325
326 - def getBrokenPackName(self, ob):
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