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

Source Code for Module Products.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 manageIp = manageIp.replace(' ', '') 105 106 # If we're not discovering and we have no IP, attempt the IP lookup 107 # locally 108 if discoverProto=='none': 109 if not manageIp: 110 try: 111 manageIp = socket.gethostbyname(deviceName) 112 except socket.error: 113 pass 114 115 # move the zProperties required by manage_createDevice to 116 # deviceProperties 117 for key in 'zSnmpCommunity', 'zSnmpPort', 'zSnmpVer': 118 if zProperties.has_key(key): 119 deviceProperties[key] = zProperties.pop(key) 120 121 # Make a device object in the database 122 self.deviceobj = manage_createDevice(self.context, deviceName, 123 devicePath, 124 performanceMonitor=performanceMonitor, 125 manageIp=manageIp, 126 zProperties=zProperties, 127 **deviceProperties) 128 129 # Flag this device as temporary. If discovery goes well, zendisc will 130 # flip this to False. 131 self.deviceobj._temp_device = True 132 133 # If we're not discovering, we're done 134 if discoverProto=='none': 135 return self.deviceobj 136 137 # Otherwise, time for zendisc to do its thing 138 self.run_zendisc(deviceName, devicePath, performanceMonitor) 139 140 finally: 141 # Check discovery's success and clean up accordingly 142 self.cleanup() 143 144 return self.deviceobj
145 146
147 -class JobDeviceLoader(BaseDeviceLoader):
148 implements(IDeviceLoader) 149
150 - def run_zendisc(self, deviceName, devicePath, performanceMonitor):
151 """ 152 In this subclass, just create the zendisc command and return it. The 153 job will do the actual running. 154 """ 155 # Commit to database so everybody can find the new device 156 transaction.commit() 157 158 jobid = self.context.getUid() 159 160 zm = binPath('zendisc') 161 zendiscCmd = [zm] 162 zendiscOptions = ['run', '--now','-d', deviceName, 163 '--monitor', performanceMonitor, 164 '--deviceclass', devicePath, 165 '--job', jobid] 166 zendiscCmd.extend(zendiscOptions) 167 self.zendiscCmd = zendiscCmd
168
169 - def cleanup(self):
170 """ 171 Delegate cleanup to the Job itself. 172 """ 173 pass
174 175
176 -class DeviceCreationJob(ShellCommandJob):
177 - def __init__(self, jobid, deviceName, devicePath="/Discovered", tag="", 178 serialNumber="", rackSlot=0, productionState=1000, 179 comments="", hwManufacturer="", hwProductName="", 180 osManufacturer="", osProductName="", locationPath="", 181 groupPaths=[], systemPaths=[], performanceMonitor="localhost", 182 discoverProto="snmp", priority=3, manageIp="", 183 zProperties=None):
184 185 # Store device name for later finding 186 self.deviceName = deviceName 187 self.devicePath = devicePath 188 self.performanceMonitor = performanceMonitor 189 self.discoverProto = discoverProto 190 self.manageIp = manageIp.replace(' ', '') 191 192 # Save the device stuff to set after adding 193 self.zProperties = zProperties 194 self.deviceProps = dict(tag=tag, 195 serialNumber=serialNumber, 196 rackSlot=rackSlot, 197 productionState=productionState, 198 comments=comments, 199 hwManufacturer=hwManufacturer, 200 hwProductName = hwProductName, 201 osManufacturer = osManufacturer, 202 osProductName = osProductName, 203 locationPath = locationPath, 204 groupPaths = groupPaths, 205 systemPaths = systemPaths, 206 priority = priority) 207 208 # Set up the job, passing in a blank command (gets set later) 209 super(DeviceCreationJob, self).__init__(jobid, '')
210 211
212 - def run(self, r):
213 # Store zProperties on the job 214 self.getStatus().setZProperties(**self.zProperties) 215 216 self._v_loader = JobDeviceLoader(self) 217 # Create the device object and generate the zendisc command 218 try: 219 self._v_loader.load_device(self.deviceName, self.devicePath, 220 self.discoverProto, 221 self.performanceMonitor, self.manageIp, 222 self.zProperties, self.deviceProps) 223 except Exception, e: 224 transaction.commit() 225 log = self.getStatus().getLog() 226 log.write(e.args[0]) 227 log.finish() 228 self.finished(FAILURE) 229 else: 230 self.cmd = self._v_loader.zendiscCmd 231 super(DeviceCreationJob, self).run(r)
232
233 - def finished(self, r):
234 self._v_loader.cleanup() 235 if self._v_loader.deviceobj is not None and r!=FAILURE: 236 result = SUCCESS 237 else: 238 result = FAILURE 239 super(DeviceCreationJob, self).finished(result)
240
241 -class WeblogDeviceLoader(BaseDeviceLoader):
242 - def __init__(self, context, request):
243 self.context = context 244 self.request = request
245
246 - def run_zendisc(self, deviceName, devicePath, performanceMonitor):
247 # Commit to database so everybody can find the new device 248 transaction.commit() 249 collector = self.deviceobj.getPerformanceServer() 250 collector._executeZenDiscCommand(deviceName, devicePath, 251 performanceMonitor, 252 REQUEST=self.request)
253 254
255 -class ZDeviceLoader(ZenModelItem,SimpleItem):
256 """Load devices into the DMD database""" 257 258 portal_type = meta_type = 'DeviceLoader' 259 260 manage_options = (( 261 {'label':'ManualDeviceLoader', 'action':'manualDeviceLoader'}, 262 ) + SimpleItem.manage_options) 263 264 265 security = ClassSecurityInfo() 266 267 factory_type_information = ( 268 { 269 'immediate_view' : 'addDevice', 270 'actions' : 271 ( 272 { 'id' : 'status' 273 , 'name' : 'Status' 274 , 'action' : 'addDevice' 275 , 'permissions' : ( 276 permissions.view, ) 277 }, 278 ) 279 }, 280 ) 281
282 - def __init__(self, id):
283 self.id = id
284 285
286 - def loadDevice(self, deviceName, devicePath="/Discovered", 287 tag="", serialNumber="", 288 zSnmpCommunity="", zSnmpPort=161, zSnmpVer=None, 289 rackSlot=0, productionState=1000, comments="", 290 hwManufacturer="", hwProductName="", 291 osManufacturer="", osProductName="", 292 locationPath="", groupPaths=[], systemPaths=[], 293 performanceMonitor="localhost", 294 discoverProto="snmp",priority=3,REQUEST=None):
295 """ 296 Load a device into the database connecting its major relations 297 and collecting its configuration. 298 """ 299 device = None 300 if not deviceName: return self.callZenScreen(REQUEST) 301 xmlrpc = isXmlRpc(REQUEST) 302 if REQUEST and not xmlrpc: 303 handler = setupLoggingHeader(self, REQUEST) 304 305 loader = WeblogDeviceLoader(self, REQUEST) 306 307 try: 308 device = loader.load_device(deviceName, devicePath, discoverProto, 309 performanceMonitor, 310 zProperties=dict( 311 zSnmpCommunity=zSnmpCommunity, 312 zSnmpPort=zSnmpPort, 313 zSnmpVer=zSnmpVer 314 ), 315 deviceProperties=dict( 316 tag=tag, 317 serialNumber=serialNumber, 318 rackSlot=rackSlot, 319 productionState=productionState, 320 comments=comments, 321 hwManufacturer=hwManufacturer, 322 hwProductName=hwProductName, 323 osManufacturer=osManufacturer, 324 osProductName=osProductName, 325 locationPath=locationPath, 326 groupPaths=groupPaths, 327 systemPaths=systemPaths, 328 priority=priority 329 )) 330 except (SystemExit, KeyboardInterrupt): 331 raise 332 except ZentinelException, e: 333 log.info(e) 334 if xmlrpc: return 1 335 except DeviceExistsError, e: 336 log.info(e) 337 if xmlrpc: return 2 338 except NoSnmp, e: 339 log.info(e) 340 if xmlrpc: return 3 341 except Exception, e: 342 log.exception(e) 343 log.exception('load of device %s failed' % deviceName) 344 transaction.abort() 345 if device is None: 346 log.error("Unable to add the device %s" % deviceName) 347 else: 348 log.info("Device %s loaded!" % deviceName) 349 350 if REQUEST and not xmlrpc: 351 self.loaderFooter(device, REQUEST.RESPONSE) 352 clearWebLoggingStream(handler) 353 if xmlrpc: return 0
354
355 - def addManufacturer(self, newHWManufacturerName=None, 356 newSWManufacturerName=None, REQUEST=None):
357 """add a manufacturer to the database""" 358 mname = newHWManufacturerName 359 field = 'hwManufacturer' 360 if not mname: 361 mname = newSWManufacturerName 362 field = 'osManufacturer' 363 try: 364 self.getDmdRoot("Manufacturers").createManufacturer(mname) 365 except BadRequest, e: 366 if REQUEST: 367 messaging.IMessageSender(self).sendToBrowser( 368 'Error', 369 str(e), 370 priority=messaging.WARNING 371 ) 372 else: 373 raise e 374 375 if REQUEST: 376 REQUEST[field] = mname 377 return self.callZenScreen(REQUEST)
378 379 380 security.declareProtected('Change Device', 'setHWProduct')
381 - def setHWProduct(self, newHWProductName, hwManufacturer, REQUEST=None):
382 """set the productName of this device""" 383 if not hwManufacturer and REQUEST: 384 messaging.IMessageSender(self).sendToBrowser( 385 'Error', 386 'Please select a HW Manufacturer', 387 priority=messaging.WARNING 388 ) 389 return self.callZenScreen(REQUEST) 390 391 self.getDmdRoot("Manufacturers").createHardwareProduct( 392 newHWProductName, hwManufacturer) 393 if REQUEST: 394 REQUEST['hwProductName'] = newHWProductName 395 return self.callZenScreen(REQUEST)
396 397 398 security.declareProtected('Change Device', 'setOSProduct')
399 - def setOSProduct(self, newOSProductName, osManufacturer, REQUEST=None):
400 """set the productName of this device""" 401 if not osManufacturer and REQUEST: 402 messaging.IMessageSender(self).sendToBrowser( 403 'Error', 404 'Please select an OS Manufacturer.', 405 priority=messaging.WARNING 406 ) 407 return self.callZenScreen(REQUEST) 408 409 self.getDmdRoot("Manufacturers").createSoftwareProduct( 410 newOSProductName, osManufacturer, isOS=True) 411 if REQUEST: 412 REQUEST['osProductName'] = newOSProductName 413 return self.callZenScreen(REQUEST)
414 415 416 security.declareProtected('Change Device', 'addLocation')
417 - def addLocation(self, newLocationPath, REQUEST=None):
418 """add a location to the database""" 419 try: 420 self.getDmdRoot("Locations").createOrganizer(newLocationPath) 421 except BadRequest, e: 422 if REQUEST: 423 messaging.IMessageSender(self).sendToBrowser( 424 'Error', 425 str(e), 426 priority=messaging.WARNING 427 ) 428 else: 429 raise e 430 431 if REQUEST: 432 REQUEST['locationPath'] = newLocationPath 433 return self.callZenScreen(REQUEST)
434 435 436 security.declareProtected('Change Device', 'addSystem')
437 - def addSystem(self, newSystemPath, REQUEST=None):
438 """add a system to the database""" 439 try: 440 self.getDmdRoot("Systems").createOrganizer(newSystemPath) 441 except BadRequest, e: 442 if REQUEST: 443 messaging.IMessageSender(self).sendToBrowser( 444 'Error', 445 str(e), 446 priority=messaging.WARNING 447 ) 448 else: 449 raise e 450 451 syss = REQUEST.get('systemPaths', []) 452 syss.append(newSystemPath) 453 if REQUEST: 454 REQUEST['systemPaths'] = syss 455 return self.callZenScreen(REQUEST)
456 457 458 security.declareProtected('Change Device', 'addDeviceGroup')
459 - def addDeviceGroup(self, newDeviceGroupPath, REQUEST=None):
460 """add a device group to the database""" 461 try: 462 self.getDmdRoot("Groups").createOrganizer(newDeviceGroupPath) 463 except BadRequest, e: 464 if REQUEST: 465 messaging.IMessageSender(self).sendToBrowser( 466 'Error', 467 str(e), 468 priority=messaging.WARNING 469 ) 470 else: 471 raise e 472 473 groups = REQUEST.get('groupPaths', []) 474 groups.append(newDeviceGroupPath) 475 if REQUEST: 476 REQUEST['groupPaths'] = groups 477 return self.callZenScreen(REQUEST)
478 479 480 security.declareProtected('Change Device', 'setPerformanceMonitor')
481 - def setPerformanceMonitor(self, newPerformanceMonitor, REQUEST=None):
482 """add new performance monitor to the database""" 483 try: 484 self.getDmdRoot("Monitors").getPerformanceMonitor(newPerformanceMonitor) 485 except BadRequest, e: 486 if REQUEST: 487 messaging.IMessageSender(self).sendToBrowser( 488 'Error', 489 str(e), 490 priority=messaging.WARNING 491 ) 492 else: 493 raise e 494 if REQUEST: 495 REQUEST['performanceMonitor'] = newPerformanceMonitor 496 return self.callZenScreen(REQUEST)
497 498
499 - def setupLog(self, response):
500 """setup logging package to send to browser""" 501 root = getLogger() 502 self._v_handler = StreamHandler(response) 503 fmt = Formatter("""<tr class="tablevalues"> 504 <td>%(asctime)s</td><td>%(levelname)s</td> 505 <td>%(name)s</td><td>%(message)s</td></tr> 506 """, "%Y-%m-%d %H:%M:%S") 507 self._v_handler.setFormatter(fmt) 508 root.addHandler(self._v_handler) 509 root.setLevel(10)
510 511
512 - def clearLog(self):
513 alog = getLogger() 514 if getattr(self, "_v_handler", False): 515 alog.removeHandler(self._v_handler)
516 517
518 - def loaderFooter(self, devObj, response):
519 """add navigation links to the end of the loader output""" 520 if not devObj: return 521 devurl = devObj.absolute_url() 522 response.write("""<tr class="tableheader"><td colspan="4"> 523 Navigate to device <a href=%s>%s</a></td></tr>""" 524 % (devurl, devObj.getId())) 525 response.write("</table></body></html>")
526