Package ZenModel :: Module ZDeviceLoader
[hide private]
[frames] | no frames]

Source Code for Module ZenModel.ZDeviceLoader

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  __doc__="""ZDeviceLoader.py 
 15   
 16  load devices from a GUI screen in the ZMI 
 17   
 18  $Id: ZDeviceLoader.py,v 1.19 2004/04/22 02:14:12 edahl Exp $""" 
 19   
 20  __version__ = "$Revision: 1.19 $"[11:-2] 
 21   
 22  import socket 
 23  from logging import StreamHandler, Formatter, getLogger 
 24  log = getLogger("zen.DeviceLoader") 
 25   
 26  import transaction 
 27  from zope.interface import implements 
 28  from AccessControl import ClassSecurityInfo 
 29  from AccessControl import Permissions as permissions 
 30   
 31  from OFS.SimpleItem import SimpleItem 
 32   
 33  from Products.ZenUtils.Utils import isXmlRpc, setupLoggingHeader  
 34  from Products.ZenUtils.Utils import binPath, clearWebLoggingStream 
 35  from Products.ZenUtils.Exceptions import ZentinelException 
 36  from Products.ZenModel.Exceptions import DeviceExistsError, NoSnmp 
 37  from Products.ZenModel.Device import manage_createDevice 
 38  from Products.ZenWidgets import messaging 
 39  from Products.Jobber.interfaces import IJobStatus 
 40  from Products.Jobber.jobs import ShellCommandJob 
 41  from Products.Jobber.status import SUCCESS, FAILURE 
 42  from ZenModelItem import ZenModelItem 
 43  from zExceptions import BadRequest 
 44  from Products.ZenModel.interfaces import IDeviceLoader 
 45   
 46   
47 -def manage_addZDeviceLoader(context, id="", REQUEST = None):
48 """make a DeviceLoader""" 49 if not id: id = "DeviceLoader" 50 d = ZDeviceLoader(id) 51 context._setObject(id, d) 52 53 if REQUEST is not None: 54 REQUEST['RESPONSE'].redirect(context.absolute_url() 55 +'/manage_main')
56
57 -class BaseDeviceLoader(object):
58 implements(IDeviceLoader) 59 60 context = None 61 request = None 62 deviceobj = None 63
64 - def __init__(self, context):
65 self.context = context
66
67 - def run_zendisc(self, deviceName, devicePath, performanceMonitor):
68 """ 69 Various ways of doing this should be implemented in subclasses. 70 """ 71 raise NotImplementedError
72
73 - def cleanup(self):
74 """ 75 Delete the device object, presumably because discovery failed. 76 """ 77 if self.deviceobj is not None: 78 try: 79 self.deviceobj._p_jar.sync() 80 except AttributeError: 81 pass 82 else: 83 if self.deviceobj.isTempDevice(): 84 # Flag's still True, so discovery failed somehow. Clean up 85 # the device object. 86 self.deviceobj.deleteDevice(True, True, True) 87 self.deviceobj = None
88
89 - def load_device(self, deviceName, devicePath='/Discovered', 90 discoverProto='snmp', performanceMonitor='localhost', 91 manageIp="", zProperties=None, deviceProperties=None):
92 """ 93 Load a single device into the database. 94 """ 95 # Make the config dictionaries the proper type 96 try: 97 if zProperties is None: 98 zProperties = {} 99 if deviceProperties is None: 100 deviceProperties = {} 101 102 # Remove spaces from the name 103 deviceName = deviceName.replace(' ', '') 104 105 # If we're not discovering and we have no IP, attempt the IP lookup 106 # locally 107 if discoverProto=='none': 108 if not manageIp: 109 try: 110 manageIp = socket.gethostbyname(deviceName) 111 except socket.error: 112 pass 113 114 # move the zProperties required by manage_createDevice to 115 # deviceProperties 116 for key in 'zSnmpCommunity', 'zSnmpPort', 'zSnmpVer': 117 if zProperties.has_key(key): 118 deviceProperties[key] = zProperties.pop(key) 119 120 # Make a device object in the database 121 self.deviceobj = manage_createDevice(self.context, deviceName, 122 devicePath, 123 performanceMonitor=performanceMonitor, 124 manageIp=manageIp, 125 zProperties=zProperties, 126 **deviceProperties) 127 128 # Flag this device as temporary. If discovery goes well, zendisc will 129 # flip this to False. 130 self.deviceobj._temp_device = True 131 132 # If we're not discovering, we're done 133 if discoverProto=='none': 134 return self.deviceobj 135 136 # Otherwise, time for zendisc to do its thing 137 self.run_zendisc(deviceName, devicePath, performanceMonitor) 138 139 finally: 140 # Check discovery's success and clean up accordingly 141 self.cleanup() 142 143 return self.deviceobj
144 145
146 -class JobDeviceLoader(BaseDeviceLoader):
147 implements(IDeviceLoader) 148
149 - def run_zendisc(self, deviceName, devicePath, performanceMonitor):
150 """ 151 In this subclass, just create the zendisc command and return it. The 152 job will do the actual running. 153 """ 154 # Commit to database so everybody can find the new device 155 transaction.commit() 156 157 jobid = self.context.getUid() 158 159 zm = binPath('zendisc') 160 zendiscCmd = [zm] 161 zendiscOptions = ['run', '--now','-d', deviceName, 162 '--monitor', performanceMonitor, 163 '--deviceclass', devicePath, 164 '--job', jobid] 165 zendiscCmd.extend(zendiscOptions) 166 self.zendiscCmd = zendiscCmd
167
168 - def cleanup(self):
169 """ 170 Delegate cleanup to the Job itself. 171 """ 172 pass
173 174
175 -class DeviceCreationJob(ShellCommandJob):
176 - def __init__(self, jobid, deviceName, devicePath="/Discovered", tag="", 177 serialNumber="", rackSlot=0, productionState=1000, 178 comments="", hwManufacturer="", hwProductName="", 179 osManufacturer="", osProductName="", locationPath="", 180 groupPaths=[], systemPaths=[], performanceMonitor="localhost", 181 discoverProto="snmp", priority=3, manageIp="", 182 zProperties=None):
183 184 # Store device name for later finding 185 self.deviceName = deviceName 186 self.devicePath = devicePath 187 self.performanceMonitor = performanceMonitor 188 self.discoverProto = discoverProto 189 self.manageIp = manageIp 190 191 # Save the device stuff to set after adding 192 self.zProperties = zProperties 193 self.deviceProps = dict(tag=tag, 194 serialNumber=serialNumber, 195 rackSlot=rackSlot, 196 productionState=productionState, 197 comments=comments, 198 hwManufacturer=hwManufacturer, 199 hwProductName = hwProductName, 200 osManufacturer = osManufacturer, 201 osProductName = osProductName, 202 locationPath = locationPath, 203 groupPaths = groupPaths, 204 systemPaths = systemPaths, 205 priority = priority) 206 207 # Set up the job, passing in a blank command (gets set later) 208 super(DeviceCreationJob, self).__init__(jobid, '')
209 210
211 - def run(self, r):
212 # Store zProperties on the job 213 self.getStatus().setZProperties(**self.zProperties) 214 215 self._v_loader = JobDeviceLoader(self) 216 # Create the device object and generate the zendisc command 217 try: 218 self._v_loader.load_device(self.deviceName, self.devicePath, 219 self.discoverProto, 220 self.performanceMonitor, self.manageIp, 221 self.zProperties, self.deviceProps) 222 except Exception, e: 223 transaction.commit() 224 log = self.getStatus().getLog() 225 log.write(e.args[0]) 226 log.finish() 227 self.finished(FAILURE) 228 else: 229 self.cmd = self._v_loader.zendiscCmd 230 super(DeviceCreationJob, self).run(r)
231
232 - def finished(self, r):
233 self._v_loader.cleanup() 234 if self._v_loader.deviceobj is not None and r!=FAILURE: 235 result = SUCCESS 236 else: 237 result = FAILURE 238 super(DeviceCreationJob, self).finished(result)
239
240 -class WeblogDeviceLoader(BaseDeviceLoader):
241 - def __init__(self, context, request):
242 self.context = context 243 self.request = request
244
245 - def run_zendisc(self, deviceName, devicePath, performanceMonitor):
246 # Commit to database so everybody can find the new device 247 transaction.commit() 248 collector = self.deviceobj.getPerformanceServer() 249 collector._executeZenDiscCommand(deviceName, devicePath, 250 performanceMonitor, 251 REQUEST=self.request)
252 253
254 -class ZDeviceLoader(ZenModelItem,SimpleItem):
255 """Load devices into the DMD database""" 256 257 portal_type = meta_type = 'DeviceLoader' 258 259 manage_options = (( 260 {'label':'ManualDeviceLoader', 'action':'manualDeviceLoader'}, 261 ) + SimpleItem.manage_options) 262 263 264 security = ClassSecurityInfo() 265 266 factory_type_information = ( 267 { 268 'immediate_view' : 'addDevice', 269 'actions' : 270 ( 271 { 'id' : 'status' 272 , 'name' : 'Status' 273 , 'action' : 'addDevice' 274 , 'permissions' : ( 275 permissions.view, ) 276 }, 277 ) 278 }, 279 ) 280
281 - def __init__(self, id):
282 self.id = id
283 284
285 - def loadDevice(self, deviceName, devicePath="/Discovered", 286 tag="", serialNumber="", 287 zSnmpCommunity="", zSnmpPort=161, zSnmpVer=None, 288 rackSlot=0, productionState=1000, comments="", 289 hwManufacturer="", hwProductName="", 290 osManufacturer="", osProductName="", 291 locationPath="", groupPaths=[], systemPaths=[], 292 performanceMonitor="localhost", 293 discoverProto="snmp",priority=3,REQUEST=None):
294 """ 295 Load a device into the database connecting its major relations 296 and collecting its configuration. 297 """ 298 device = None 299 if not deviceName: return self.callZenScreen(REQUEST) 300 xmlrpc = isXmlRpc(REQUEST) 301 if REQUEST and not xmlrpc: 302 handler = setupLoggingHeader(self, REQUEST) 303 304 loader = WeblogDeviceLoader(self, REQUEST) 305 306 try: 307 device = loader.load_device(deviceName, devicePath, discoverProto, 308 performanceMonitor, 309 zProperties=dict( 310 zSnmpCommunity=zSnmpCommunity, 311 zSnmpPort=zSnmpPort, 312 zSnmpVer=zSnmpVer 313 ), 314 deviceProperties=dict( 315 tag=tag, 316 serialNumber=serialNumber, 317 rackSlot=rackSlot, 318 productionState=productionState, 319 comments=comments, 320 hwManufacturer=hwManufacturer, 321 hwProductName=hwProductName, 322 osManufacturer=osManufacturer, 323 osProductName=osProductName, 324 locationPath=locationPath, 325 groupPaths=groupPaths, 326 systemPaths=systemPaths, 327 priority=priority 328 )) 329 except (SystemExit, KeyboardInterrupt): 330 raise 331 except ZentinelException, e: 332 log.info(e) 333 if xmlrpc: return 1 334 except DeviceExistsError, e: 335 log.info(e) 336 if xmlrpc: return 2 337 except NoSnmp, e: 338 log.info(e) 339 if xmlrpc: return 3 340 except Exception, e: 341 log.exception(e) 342 log.exception('load of device %s failed' % deviceName) 343 transaction.abort() 344 if device is None: 345 log.error("Unable to add the device %s" % deviceName) 346 else: 347 log.info("Device %s loaded!" % deviceName) 348 349 if REQUEST and not xmlrpc: 350 self.loaderFooter(device, REQUEST.RESPONSE) 351 clearWebLoggingStream(handler) 352 if xmlrpc: return 0
353
354 - def addManufacturer(self, newHWManufacturerName=None, 355 newSWManufacturerName=None, REQUEST=None):
356 """add a manufacturer to the database""" 357 mname = newHWManufacturerName 358 field = 'hwManufacturer' 359 if not mname: 360 mname = newSWManufacturerName 361 field = 'osManufacturer' 362 try: 363 self.getDmdRoot("Manufacturers").createManufacturer(mname) 364 except BadRequest, e: 365 if REQUEST: 366 messaging.IMessageSender(self).sendToBrowser( 367 'Error', 368 str(e), 369 priority=messaging.WARNING 370 ) 371 else: 372 raise e 373 374 if REQUEST: 375 REQUEST[field] = mname 376 return self.callZenScreen(REQUEST)
377 378 379 security.declareProtected('Change Device', 'setHWProduct')
380 - def setHWProduct(self, newHWProductName, hwManufacturer, REQUEST=None):
381 """set the productName of this device""" 382 if not hwManufacturer and REQUEST: 383 messaging.IMessageSender(self).sendToBrowser( 384 'Error', 385 'Please select a HW Manufacturer', 386 priority=messaging.WARNING 387 ) 388 return self.callZenScreen(REQUEST) 389 390 self.getDmdRoot("Manufacturers").createHardwareProduct( 391 newHWProductName, hwManufacturer) 392 if REQUEST: 393 REQUEST['hwProductName'] = newHWProductName 394 return self.callZenScreen(REQUEST)
395 396 397 security.declareProtected('Change Device', 'setOSProduct')
398 - def setOSProduct(self, newOSProductName, osManufacturer, REQUEST=None):
399 """set the productName of this device""" 400 if not osManufacturer and REQUEST: 401 messaging.IMessageSender(self).sendToBrowser( 402 'Error', 403 'Please select an OS Manufacturer.', 404 priority=messaging.WARNING 405 ) 406 return self.callZenScreen(REQUEST) 407 408 self.getDmdRoot("Manufacturers").createSoftwareProduct( 409 newOSProductName, osManufacturer, isOS=True) 410 if REQUEST: 411 REQUEST['osProductName'] = newOSProductName 412 return self.callZenScreen(REQUEST)
413 414 415 security.declareProtected('Change Device', 'addLocation')
416 - def addLocation(self, newLocationPath, REQUEST=None):
417 """add a location to the database""" 418 try: 419 self.getDmdRoot("Locations").createOrganizer(newLocationPath) 420 except BadRequest, e: 421 if REQUEST: 422 messaging.IMessageSender(self).sendToBrowser( 423 'Error', 424 str(e), 425 priority=messaging.WARNING 426 ) 427 else: 428 raise e 429 430 if REQUEST: 431 REQUEST['locationPath'] = newLocationPath 432 return self.callZenScreen(REQUEST)
433 434 435 security.declareProtected('Change Device', 'addSystem')
436 - def addSystem(self, newSystemPath, REQUEST=None):
437 """add a system to the database""" 438 try: 439 self.getDmdRoot("Systems").createOrganizer(newSystemPath) 440 except BadRequest, e: 441 if REQUEST: 442 messaging.IMessageSender(self).sendToBrowser( 443 'Error', 444 str(e), 445 priority=messaging.WARNING 446 ) 447 else: 448 raise e 449 450 syss = REQUEST.get('systemPaths', []) 451 syss.append(newSystemPath) 452 if REQUEST: 453 REQUEST['systemPaths'] = syss 454 return self.callZenScreen(REQUEST)
455 456 457 security.declareProtected('Change Device', 'addDeviceGroup')
458 - def addDeviceGroup(self, newDeviceGroupPath, REQUEST=None):
459 """add a device group to the database""" 460 try: 461 self.getDmdRoot("Groups").createOrganizer(newDeviceGroupPath) 462 except BadRequest, e: 463 if REQUEST: 464 messaging.IMessageSender(self).sendToBrowser( 465 'Error', 466 str(e), 467 priority=messaging.WARNING 468 ) 469 else: 470 raise e 471 472 groups = REQUEST.get('groupPaths', []) 473 groups.append(newDeviceGroupPath) 474 if REQUEST: 475 REQUEST['groupPaths'] = groups 476 return self.callZenScreen(REQUEST)
477 478 479 security.declareProtected('Change Device', 'setPerformanceMonitor')
480 - def setPerformanceMonitor(self, newPerformanceMonitor, REQUEST=None):
481 """add new performance monitor to the database""" 482 try: 483 self.getDmdRoot("Monitors").getPerformanceMonitor(newPerformanceMonitor) 484 except BadRequest, e: 485 if REQUEST: 486 messaging.IMessageSender(self).sendToBrowser( 487 'Error', 488 str(e), 489 priority=messaging.WARNING 490 ) 491 else: 492 raise e 493 if REQUEST: 494 REQUEST['performanceMonitor'] = newPerformanceMonitor 495 return self.callZenScreen(REQUEST)
496 497
498 - def setupLog(self, response):
499 """setup logging package to send to browser""" 500 root = getLogger() 501 self._v_handler = StreamHandler(response) 502 fmt = Formatter("""<tr class="tablevalues"> 503 <td>%(asctime)s</td><td>%(levelname)s</td> 504 <td>%(name)s</td><td>%(message)s</td></tr> 505 """, "%Y-%m-%d %H:%M:%S") 506 self._v_handler.setFormatter(fmt) 507 root.addHandler(self._v_handler) 508 root.setLevel(10)
509 510
511 - def clearLog(self):
512 alog = getLogger() 513 if getattr(self, "_v_handler", False): 514 alog.removeHandler(self._v_handler)
515 516
517 - def loaderFooter(self, devObj, response):
518 """add navigation links to the end of the loader output""" 519 if not devObj: return 520 devurl = devObj.absolute_url() 521 response.write("""<tr class="tableheader"><td colspan="4"> 522 Navigate to device <a href=%s>%s</a></td></tr>""" 523 % (devurl, devObj.getId())) 524 response.write("</table></body></html>")
525