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