1
2
3
4
5
6
7
8
9
10
11 __doc__="""ZDeviceLoader.py
12
13 load devices from a GUI screen in the ZMI
14
15 """
16
17 import socket
18 from logging import StreamHandler, Formatter, getLogger
19 log = getLogger("zen.DeviceLoader")
20
21 from ipaddr import IPAddress
22
23 import transaction
24 from ZODB.transact import transact
25 from zope.interface import implements
26 from AccessControl import ClassSecurityInfo
27 from AccessControl import Permissions as permissions
28
29 from OFS.SimpleItem import SimpleItem
30
31 from Products.ZenUtils.Utils import isXmlRpc, setupLoggingHeader
32 from Products.ZenUtils.Utils import binPath, clearWebLoggingStream
33 from Products.ZenUtils.IpUtil import getHostByName, ipwrap
34
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.jobs import SubprocessJob
40 from ZenModelItem import ZenModelItem
41 from zExceptions import BadRequest
42 from Products.ZenModel.interfaces import IDeviceLoader
43 from Products.ZenEvents.Event import Event
55
57 implements(IDeviceLoader)
58
59 context = None
60 request = None
61 deviceobj = None
62
65
66 - def run_zendisc(self, deviceName, devicePath, performanceMonitor, productionState):
67 """
68 Various ways of doing this should be implemented in subclasses.
69 """
70 raise NotImplementedError
71
87
88 - def load_device(self, deviceName, devicePath='/Discovered',
89 discoverProto='snmp', performanceMonitor='localhost',
90 manageIp="", zProperties=None, deviceProperties=None):
91 """
92 Load a single device into the database.
93 """
94
95 try:
96 if zProperties is None:
97 zProperties = {}
98 if deviceProperties is None:
99 deviceProperties = {}
100
101
102 deviceName = deviceName.replace(' ', '')
103 manageIp = manageIp.replace(' ', '')
104
105
106 try:
107 ipv6addr = IPAddress(deviceName)
108 manageIp = deviceName
109 deviceName = ipwrap(deviceName)
110 deviceProperties.setdefault('title', manageIp)
111 except ValueError:
112 pass
113
114
115
116 if discoverProto=='none':
117 if not manageIp:
118 try:
119 manageIp = getHostByName(deviceName)
120 except socket.error:
121 pass
122
123
124
125 for key in 'zSnmpCommunity', 'zSnmpPort', 'zSnmpVer':
126 if key in zProperties:
127 deviceProperties[key] = zProperties.pop(key)
128
129
130 self.deviceobj = manage_createDevice(self.context, deviceName,
131 devicePath,
132 performanceMonitor=performanceMonitor,
133 manageIp=manageIp,
134 zProperties=zProperties,
135 **deviceProperties)
136
137
138
139 self.deviceobj._temp_device = True
140
141
142 if discoverProto=='none':
143 return self.deviceobj
144
145
146 productionState = deviceProperties.get('productionState', 1000)
147
148
149 self.run_zendisc(deviceName, devicePath, performanceMonitor, productionState)
150
151 finally:
152
153 self.cleanup()
154
155 return self.deviceobj
156
159 implements(IDeviceLoader)
160
161 - def run_zendisc(self, deviceName, devicePath, performanceMonitor, productionState):
162 """
163 In this subclass, just commit to database,
164 so everybody can find the new device
165 """
166 pass
167
169 """
170 Delegate cleanup to the Job itself.
171 """
172 pass
173
176
177 @classmethod
180
181 @classmethod
183 return "Add %(deviceName)s under %(devicePath)s" % kwargs
184
185 - def _run(self, deviceName, devicePath="/Discovered", tag="",
186 serialNumber="", rackSlot=0, productionState=1000, comments="",
187 hwManufacturer="", hwProductName="", osManufacturer="",
188 osProductName="", locationPath="", groupPaths=[], systemPaths=[],
189 performanceMonitor="localhost", discoverProto="snmp", priority=3,
190 manageIp="", zProperties=None, title="", zendiscCmd=[]):
191
192 loader = JobDeviceLoader(self.dmd)
193
194
195 self.deviceName = deviceName
196 self.devicePath = devicePath
197 self.performanceMonitor = performanceMonitor
198 self.discoverProto = discoverProto
199 self.manageIp = manageIp.replace(' ', '')
200
201
202 deviceProps = dict(tag=tag,
203 serialNumber=serialNumber,
204 rackSlot=rackSlot,
205 productionState=productionState,
206 comments=comments,
207 hwManufacturer=hwManufacturer,
208 hwProductName = hwProductName,
209 osManufacturer = osManufacturer,
210 osProductName = osProductName,
211 locationPath = locationPath,
212 groupPaths = groupPaths,
213 systemPaths = systemPaths,
214 priority = priority,
215 title= title)
216 zendiscCmd.extend(['--job', self.request.id])
217
218 @transact
219 def createDevice():
220
221
222 self.setProperties(**zProperties)
223 self.setProperties(**deviceProps)
224
225 loader.load_device(deviceName, devicePath, discoverProto,
226 performanceMonitor, manageIp, zProperties,
227 deviceProps)
228
229
230 try:
231 createDevice()
232 except Exception, e:
233 transaction.abort()
234 self.log.exception("Encountered error. Rolling back initial device add.")
235 raise
236 else:
237 if self.discoverProto != 'none':
238 return SubprocessJob._run(self, zendiscCmd)
239 else:
240 self.log.info("Device added without modeling")
241
242
243 -class WeblogDeviceLoader(BaseDeviceLoader):
244 - def __init__(self, context, request):
247
248 - def run_zendisc(self, deviceName, devicePath, performanceMonitor, productionState):
249
250 transaction.commit()
251 collector = self.deviceobj.getPerformanceServer()
252 collector._executeZenDiscCommand(deviceName, devicePath,
253 performanceMonitor, productionState,
254 REQUEST=self.request)
255
258 """Load devices into the DMD database"""
259
260 portal_type = meta_type = 'DeviceLoader'
261
262 manage_options = ((
263 {'label':'ManualDeviceLoader', 'action':'manualDeviceLoader'},
264 ) + SimpleItem.manage_options)
265
266
267 security = ClassSecurityInfo()
268
269 factory_type_information = (
270 {
271 'immediate_view' : 'addDevice',
272 'actions' :
273 (
274 { 'id' : 'status'
275 , 'name' : 'Status'
276 , 'action' : 'addDevice'
277 , 'permissions' : (
278 permissions.view, )
279 },
280 )
281 },
282 )
283
286
287
288 - def loadDevice(self, deviceName, devicePath="/Discovered",
289 tag="", serialNumber="",
290 zSnmpCommunity="", zSnmpPort=161, zSnmpVer=None,
291 rackSlot=0, productionState=1000, comments="",
292 hwManufacturer="", hwProductName="",
293 osManufacturer="", osProductName="",
294 locationPath="", groupPaths=[], systemPaths=[],
295 performanceMonitor="localhost",
296 discoverProto="snmp",priority=3, title=None, REQUEST=None):
297 """
298 Load a device into the database connecting its major relations
299 and collecting its configuration.
300 """
301 device = None
302 if not deviceName: return self.callZenScreen(REQUEST)
303 xmlrpc = isXmlRpc(REQUEST)
304 if REQUEST and not xmlrpc:
305 handler = setupLoggingHeader(self, REQUEST)
306
307 loader = WeblogDeviceLoader(self, REQUEST)
308
309 try:
310 device = loader.load_device(deviceName, devicePath, discoverProto,
311 performanceMonitor,
312 zProperties=dict(
313 zSnmpCommunity=zSnmpCommunity,
314 zSnmpPort=zSnmpPort,
315 zSnmpVer=zSnmpVer
316 ),
317 deviceProperties=dict(
318 tag=tag,
319 serialNumber=serialNumber,
320 rackSlot=rackSlot,
321 productionState=productionState,
322 comments=comments,
323 hwManufacturer=hwManufacturer,
324 hwProductName=hwProductName,
325 osManufacturer=osManufacturer,
326 osProductName=osProductName,
327 locationPath=locationPath,
328 groupPaths=groupPaths,
329 systemPaths=systemPaths,
330 priority=priority,
331 title=title
332 ))
333 except (SystemExit, KeyboardInterrupt):
334 raise
335 except ZentinelException, e:
336 log.info(e)
337 if xmlrpc: return 1
338 except DeviceExistsError, e:
339 log.info(e)
340 if xmlrpc: return 2
341 except NoSnmp, e:
342 log.info(e)
343 if xmlrpc: return 3
344 except Exception, e:
345 log.exception(e)
346 log.exception('load of device %s failed' % deviceName)
347 transaction.abort()
348 if device is None:
349 log.error("Unable to add the device %s" % deviceName)
350 else:
351 log.info("Device %s loaded!" % deviceName)
352
353 if REQUEST and not xmlrpc:
354 self.loaderFooter(device, REQUEST.RESPONSE)
355 clearWebLoggingStream(handler)
356 if xmlrpc: return 0
357
358 - def addManufacturer(self, newHWManufacturerName=None,
359 newSWManufacturerName=None, REQUEST=None):
381
382
383 security.declareProtected('Change Device', 'setHWProduct')
384 - def setHWProduct(self, newHWProductName, hwManufacturer, REQUEST=None):
399
400
401 security.declareProtected('Change Device', 'setOSProduct')
402 - def setOSProduct(self, newOSProductName, osManufacturer, REQUEST=None):
417
418
419 security.declareProtected('Change Device', 'addLocation')
437
438
439 security.declareProtected('Change Device', 'addSystem')
440 - def addSystem(self, newSystemPath, REQUEST=None):
459
460
461 security.declareProtected('Change Device', 'addDeviceGroup')
481
482
483 security.declareProtected('Change Device', 'setPerformanceMonitor')
500
501
503 """setup logging package to send to browser"""
504 root = getLogger()
505 self._v_handler = StreamHandler(response)
506 fmt = Formatter("""<tr class="tablevalues">
507 <td>%(asctime)s</td><td>%(levelname)s</td>
508 <td>%(name)s</td><td>%(message)s</td></tr>
509 """, "%Y-%m-%d %H:%M:%S")
510 self._v_handler.setFormatter(fmt)
511 root.addHandler(self._v_handler)
512 root.setLevel(10)
513
514
516 alog = getLogger()
517 if getattr(self, "_v_handler", False):
518 alog.removeHandler(self._v_handler)
519
520
529