| Trees | Indices | Help |
|
|---|
|
|
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 or (at your
8 # option) any later version as published by 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 """
19
20 import socket
21 from logging import StreamHandler, Formatter, getLogger
22 log = getLogger("zen.DeviceLoader")
23
24 from ipaddr import IPAddress
25
26 import transaction
27 from ZODB.transact import transact
28 from zope.interface import implements
29 from AccessControl import ClassSecurityInfo
30 from AccessControl import Permissions as permissions
31
32 from OFS.SimpleItem import SimpleItem
33
34 from Products.ZenUtils.Utils import isXmlRpc, setupLoggingHeader
35 from Products.ZenUtils.Utils import binPath, clearWebLoggingStream
36 from Products.ZenUtils.IpUtil import getHostByName, ipwrap
37
38 from Products.ZenUtils.Exceptions import ZentinelException
39 from Products.ZenModel.Exceptions import DeviceExistsError, NoSnmp
40 from Products.ZenModel.Device import manage_createDevice
41 from Products.ZenWidgets import messaging
42 from Products.Jobber.interfaces import IJobStatus
43 from Products.Jobber.jobs import ShellCommandJob
44 from Products.Jobber.status import SUCCESS, FAILURE
45 from ZenModelItem import ZenModelItem
46 from zExceptions import BadRequest
47 from Products.ZenModel.interfaces import IDeviceLoader
48 from Products.ZenEvents.Event import Event
52 """make a DeviceLoader"""
53 if not id: id = "DeviceLoader"
54 d = ZDeviceLoader(id)
55 context._setObject(id, d)
56
57 if REQUEST is not None:
58 REQUEST['RESPONSE'].redirect(context.absolute_url()
59 +'/manage_main')
60
62 implements(IDeviceLoader)
63
64 context = None
65 request = None
66 deviceobj = None
67
70
72 """
73 Various ways of doing this should be implemented in subclasses.
74 """
75 raise NotImplementedError
76
78 """
79 Delete the device object, presumably because discovery failed.
80 """
81 if self.deviceobj is not None:
82 try:
83 self.deviceobj._p_jar.sync()
84 except AttributeError:
85 pass
86 else:
87 if self.deviceobj.isTempDevice():
88 # Flag's still True, so discovery failed somehow. Clean up
89 # the device object.
90 self.deviceobj.deleteDevice(True, True, True)
91 self.deviceobj = None
92
93 - def load_device(self, deviceName, devicePath='/Discovered',
94 discoverProto='snmp', performanceMonitor='localhost',
95 manageIp="", zProperties=None, deviceProperties=None):
96 """
97 Load a single device into the database.
98 """
99 # Make the config dictionaries the proper type
100 try:
101 if zProperties is None:
102 zProperties = {}
103 if deviceProperties is None:
104 deviceProperties = {}
105
106 # Remove spaces from the name
107 deviceName = deviceName.replace(' ', '')
108 manageIp = manageIp.replace(' ', '')
109
110 # Check to see if we got passed in an IPv6 address
111 try:
112 ipv6addr = IPAddress(deviceName)
113 manageIp = deviceName
114 deviceName = ipwrap(deviceName)
115 deviceProperties.setdefault('title', manageIp)
116 except ValueError:
117 pass
118
119 # If we're not discovering and we have no IP, attempt the IP lookup
120 # locally
121 if discoverProto=='none':
122 if not manageIp:
123 try:
124 manageIp = getHostByName(deviceName)
125 except socket.error:
126 pass
127
128 # move the zProperties required by manage_createDevice to
129 # deviceProperties
130 for key in 'zSnmpCommunity', 'zSnmpPort', 'zSnmpVer':
131 if key in zProperties:
132 deviceProperties[key] = zProperties.pop(key)
133
134 # Make a device object in the database
135 self.deviceobj = manage_createDevice(self.context, deviceName,
136 devicePath,
137 performanceMonitor=performanceMonitor,
138 manageIp=manageIp,
139 zProperties=zProperties,
140 **deviceProperties)
141
142 # Flag this device as temporary. If discovery goes well, zendisc will
143 # flip this to False.
144 self.deviceobj._temp_device = True
145
146 # If we're not discovering, we're done
147 if discoverProto=='none':
148 return self.deviceobj
149
150 # Otherwise, time for zendisc to do its thing
151 self.run_zendisc(deviceName, devicePath, performanceMonitor)
152
153 finally:
154 # Check discovery's success and clean up accordingly
155 self.cleanup()
156
157 return self.deviceobj
158
161 implements(IDeviceLoader)
162
164 """
165 In this subclass, just commit to database,
166 so everybody can find the new device
167 """
168 pass
169
175
178 - def __init__(self, jobid, deviceName, devicePath="/Discovered", tag="",
179 serialNumber="", rackSlot=0, productionState=1000,
180 comments="", hwManufacturer="", hwProductName="",
181 osManufacturer="", osProductName="", locationPath="",
182 groupPaths=[], systemPaths=[], performanceMonitor="localhost",
183 discoverProto="snmp", priority=3, manageIp="",
184 zProperties=None, title=None, zendiscCmd=[]):
185
186 # Store device name for later finding
187 self.deviceName = deviceName
188 self.devicePath = devicePath
189 self.performanceMonitor = performanceMonitor
190 self.discoverProto = discoverProto
191 self.manageIp = manageIp.replace(' ', '')
192
193 # Save the device stuff to set after adding
194 self.zProperties = zProperties
195 self.deviceProps = dict(tag=tag,
196 serialNumber=serialNumber,
197 rackSlot=rackSlot,
198 productionState=productionState,
199 comments=comments,
200 hwManufacturer=hwManufacturer,
201 hwProductName = hwProductName,
202 osManufacturer = osManufacturer,
203 osProductName = osProductName,
204 locationPath = locationPath,
205 groupPaths = groupPaths,
206 systemPaths = systemPaths,
207 priority = priority,
208 title= title)
209
210 zendiscCmd.extend(['--job', jobid])
211 super(DeviceCreationJob, self).__init__(jobid, zendiscCmd)
212
213
215
216 self._v_loader = JobDeviceLoader(self)
217
218 @transact
219 def createDevice(loader, zProperties):
220 # set the status properties that were modified up until this
221 # point in case of a Conflict Error
222 loader.getStatus().setZProperties(**zProperties)
223 # create the device
224 loader._v_loader.load_device(loader.deviceName, loader.devicePath,
225 loader.discoverProto,
226 loader.performanceMonitor, loader.manageIp,
227 loader.zProperties, loader.deviceProps)
228
229 # Create the device object and generate the zendisc command
230 try:
231 createDevice(self, self.zProperties)
232 except Exception, e:
233 log.exception("Encountered error. Rolling back initial device add.")
234 transaction.abort()
235 job_log = self.getStatus().getLog()
236 job_log.write(str(e.args[0]))
237 job_log.finish()
238 self.finished(FAILURE)
239 transaction.commit()
240 else:
241 if self.discoverProto != 'none':
242 super(DeviceCreationJob, self).run(r)
243 else:
244 job_log = self.getStatus().getLog()
245 job_log.write("device added without modeling")
246 job_log.finish()
247 self.finished(SUCCESS)
248
250 if self._v_loader.deviceobj is not None and r!=FAILURE:
251 result = SUCCESS
252 self.dmd.ZenEventManager.sendEvent(Event(
253 summary='Added device: '+self.deviceName,
254 severity=2, #info
255 eventClass='/Change/Add', #zEventAction=history
256 device=self.deviceName))
257 else:
258 result = FAILURE
259 super(DeviceCreationJob, self).finished(result)
260
265
267 # Commit to database so everybody can find the new device
268 transaction.commit()
269 collector = self.deviceobj.getPerformanceServer()
270 collector._executeZenDiscCommand(deviceName, devicePath,
271 performanceMonitor,
272 REQUEST=self.request)
273
276 """Load devices into the DMD database"""
277
278 portal_type = meta_type = 'DeviceLoader'
279
280 manage_options = ((
281 {'label':'ManualDeviceLoader', 'action':'manualDeviceLoader'},
282 ) + SimpleItem.manage_options)
283
284
285 security = ClassSecurityInfo()
286
287 factory_type_information = (
288 {
289 'immediate_view' : 'addDevice',
290 'actions' :
291 (
292 { 'id' : 'status'
293 , 'name' : 'Status'
294 , 'action' : 'addDevice'
295 , 'permissions' : (
296 permissions.view, )
297 },
298 )
299 },
300 )
301
304
305
306 - def loadDevice(self, deviceName, devicePath="/Discovered",
307 tag="", serialNumber="",
308 zSnmpCommunity="", zSnmpPort=161, zSnmpVer=None,
309 rackSlot=0, productionState=1000, comments="",
310 hwManufacturer="", hwProductName="",
311 osManufacturer="", osProductName="",
312 locationPath="", groupPaths=[], systemPaths=[],
313 performanceMonitor="localhost",
314 discoverProto="snmp",priority=3,REQUEST=None):
315 """
316 Load a device into the database connecting its major relations
317 and collecting its configuration.
318 """
319 device = None
320 if not deviceName: return self.callZenScreen(REQUEST)
321 xmlrpc = isXmlRpc(REQUEST)
322 if REQUEST and not xmlrpc:
323 handler = setupLoggingHeader(self, REQUEST)
324
325 loader = WeblogDeviceLoader(self, REQUEST)
326
327 try:
328 device = loader.load_device(deviceName, devicePath, discoverProto,
329 performanceMonitor,
330 zProperties=dict(
331 zSnmpCommunity=zSnmpCommunity,
332 zSnmpPort=zSnmpPort,
333 zSnmpVer=zSnmpVer
334 ),
335 deviceProperties=dict(
336 tag=tag,
337 serialNumber=serialNumber,
338 rackSlot=rackSlot,
339 productionState=productionState,
340 comments=comments,
341 hwManufacturer=hwManufacturer,
342 hwProductName=hwProductName,
343 osManufacturer=osManufacturer,
344 osProductName=osProductName,
345 locationPath=locationPath,
346 groupPaths=groupPaths,
347 systemPaths=systemPaths,
348 priority=priority
349 ))
350 except (SystemExit, KeyboardInterrupt):
351 raise
352 except ZentinelException, e:
353 log.info(e)
354 if xmlrpc: return 1
355 except DeviceExistsError, e:
356 log.info(e)
357 if xmlrpc: return 2
358 except NoSnmp, e:
359 log.info(e)
360 if xmlrpc: return 3
361 except Exception, e:
362 log.exception(e)
363 log.exception('load of device %s failed' % deviceName)
364 transaction.abort()
365 if device is None:
366 log.error("Unable to add the device %s" % deviceName)
367 else:
368 log.info("Device %s loaded!" % deviceName)
369
370 if REQUEST and not xmlrpc:
371 self.loaderFooter(device, REQUEST.RESPONSE)
372 clearWebLoggingStream(handler)
373 if xmlrpc: return 0
374
375 - def addManufacturer(self, newHWManufacturerName=None,
376 newSWManufacturerName=None, REQUEST=None):
377 """add a manufacturer to the database"""
378 mname = newHWManufacturerName
379 field = 'hwManufacturer'
380 if not mname:
381 mname = newSWManufacturerName
382 field = 'osManufacturer'
383 try:
384 self.getDmdRoot("Manufacturers").createManufacturer(mname)
385 except BadRequest, e:
386 if REQUEST:
387 messaging.IMessageSender(self).sendToBrowser(
388 'Error',
389 str(e),
390 priority=messaging.WARNING
391 )
392 else:
393 raise e
394
395 if REQUEST:
396 REQUEST[field] = mname
397 return self.callZenScreen(REQUEST)
398
399
400 security.declareProtected('Change Device', 'setHWProduct')
402 """set the productName of this device"""
403 if not hwManufacturer and REQUEST:
404 messaging.IMessageSender(self).sendToBrowser(
405 'Error',
406 'Please select a HW Manufacturer',
407 priority=messaging.WARNING
408 )
409 return self.callZenScreen(REQUEST)
410
411 self.getDmdRoot("Manufacturers").createHardwareProduct(
412 newHWProductName, hwManufacturer)
413 if REQUEST:
414 REQUEST['hwProductName'] = newHWProductName
415 return self.callZenScreen(REQUEST)
416
417
418 security.declareProtected('Change Device', 'setOSProduct')
420 """set the productName of this device"""
421 if not osManufacturer and REQUEST:
422 messaging.IMessageSender(self).sendToBrowser(
423 'Error',
424 'Please select an OS Manufacturer.',
425 priority=messaging.WARNING
426 )
427 return self.callZenScreen(REQUEST)
428
429 self.getDmdRoot("Manufacturers").createSoftwareProduct(
430 newOSProductName, osManufacturer, isOS=True)
431 if REQUEST:
432 REQUEST['osProductName'] = newOSProductName
433 return self.callZenScreen(REQUEST)
434
435
436 security.declareProtected('Change Device', 'addLocation')
438 """add a location to the database"""
439 try:
440 self.getDmdRoot("Locations").createOrganizer(newLocationPath)
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 if REQUEST:
452 REQUEST['locationPath'] = newLocationPath
453 return self.callZenScreen(REQUEST)
454
455
456 security.declareProtected('Change Device', 'addSystem')
458 """add a system to the database"""
459 try:
460 self.getDmdRoot("Systems").createOrganizer(newSystemPath)
461 except BadRequest, e:
462 if REQUEST:
463 messaging.IMessageSender(self).sendToBrowser(
464 'Error',
465 str(e),
466 priority=messaging.WARNING
467 )
468 else:
469 raise e
470
471 syss = REQUEST.get('systemPaths', [])
472 syss.append(newSystemPath)
473 if REQUEST:
474 REQUEST['systemPaths'] = syss
475 return self.callZenScreen(REQUEST)
476
477
478 security.declareProtected('Change Device', 'addDeviceGroup')
480 """add a device group to the database"""
481 try:
482 self.getDmdRoot("Groups").createOrganizer(newDeviceGroupPath)
483 except BadRequest, e:
484 if REQUEST:
485 messaging.IMessageSender(self).sendToBrowser(
486 'Error',
487 str(e),
488 priority=messaging.WARNING
489 )
490 else:
491 raise e
492
493 groups = REQUEST.get('groupPaths', [])
494 groups.append(newDeviceGroupPath)
495 if REQUEST:
496 REQUEST['groupPaths'] = groups
497 return self.callZenScreen(REQUEST)
498
499
500 security.declareProtected('Change Device', 'setPerformanceMonitor')
502 """add new performance monitor to the database"""
503 try:
504 self.getDmdRoot("Monitors").getPerformanceMonitor(newPerformanceMonitor)
505 except BadRequest, e:
506 if REQUEST:
507 messaging.IMessageSender(self).sendToBrowser(
508 'Error',
509 str(e),
510 priority=messaging.WARNING
511 )
512 else:
513 raise e
514 if REQUEST:
515 REQUEST['performanceMonitor'] = newPerformanceMonitor
516 return self.callZenScreen(REQUEST)
517
518
520 """setup logging package to send to browser"""
521 root = getLogger()
522 self._v_handler = StreamHandler(response)
523 fmt = Formatter("""<tr class="tablevalues">
524 <td>%(asctime)s</td><td>%(levelname)s</td>
525 <td>%(name)s</td><td>%(message)s</td></tr>
526 """, "%Y-%m-%d %H:%M:%S")
527 self._v_handler.setFormatter(fmt)
528 root.addHandler(self._v_handler)
529 root.setLevel(10)
530
531
533 alog = getLogger()
534 if getattr(self, "_v_handler", False):
535 alog.removeHandler(self._v_handler)
536
537
546
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1.1812 on Tue Oct 11 12:51:53 2011 | http://epydoc.sourceforge.net |