1
2
3
4
5
6
7
8
9
10
11
12
13
14 __doc__ = """Device
15 Base device (remote computer) class
16 """
17
18 import os
19 import shutil
20 import time
21 import types
22 import socket
23 import logging
24 log = logging.getLogger("zen.Device")
25
26 from _mysql_exceptions import OperationalError
27
28 from urllib import quote as urlquote
29
30 from Products.ZenUtils.Utils import isXmlRpc
31 from Products.ZenUtils.Utils import unused
32 from Products.ZenUtils import Time
33 import RRDView
34 from Products.ZenUtils.IpUtil import checkip, IpAddressError, maskToBits
35
36
37 from ManagedEntity import ManagedEntity
38
39 from AccessControl import ClassSecurityInfo
40 from Globals import DTMLFile
41 from Globals import InitializeClass
42 from DateTime import DateTime
43
44 from ZODB.POSException import POSError
45
46
47
48 from Products.DataCollector.ApplyDataMap import ApplyDataMap
49
50 from Products.ZenRelations.RelSchema import *
51 from Commandable import Commandable
52 from Lockable import Lockable
53 from MaintenanceWindowable import MaintenanceWindowable
54 from AdministrativeRoleable import AdministrativeRoleable
55 from ZenMenuable import ZenMenuable
56
57 from OperatingSystem import OperatingSystem
58 from DeviceHW import DeviceHW
59
60 from ZenStatus import ZenStatus
61 from Products.ZenModel.Exceptions import *
62 from ZenossSecurity import *
63 from Products.ZenUtils.FakeRequest import FakeRequest
64 from Products.ZenUtils.Utils import edgesToXML
65 from Products.ZenUtils import NetworkTree
66
67 from zope.interface import implements
68 from EventView import IEventView
69 from Products.ZenWidgets.interfaces import IMessageSender
70 from Products.ZenWidgets import messaging
71 from Products.Jobber.status import SUCCESS, FAILURE
72 from Products.ZenUtils.Utils import binPath
73 from Products.ZenEvents.browser.EventPillsAndSummaries import getEventPillME
74 from OFS.CopySupport import CopyError
75
76
78 """
79 Return the default network root.
80 """
81 return context.getDmdRoot('Networks')
82
83
104
105
106 -def manage_createDevice(context, deviceName, devicePath="/Discovered",
107 tag="", serialNumber="",
108 zSnmpCommunity="", zSnmpPort=161, zSnmpVer="",
109 rackSlot="", productionState=1000, comments="",
110 hwManufacturer="", hwProductName="",
111 osManufacturer="", osProductName="",
112 locationPath="", groupPaths=[], systemPaths=[],
113 performanceMonitor="localhost",
114 discoverProto="snmp", priority=3, manageIp="",
115 zProperties=None):
116 """
117 Device factory creates a device and sets up its relations and collects its
118 configuration. SNMP Community discovery also happens here. If an IP is
119 passed for deviceName it will be used for collection and the device name
120 will be set to the SNMP SysName (or ptr if SNMP Fails and ptr is valid)
121
122 @rtype: Device
123 """
124 checkDeviceExists(context, deviceName, manageIp, performanceMonitor)
125 deviceName = context.prepId(deviceName)
126 log.info("device name '%s' for ip '%s'", deviceName, manageIp)
127 deviceClass = context.getDmdRoot("Devices").createOrganizer(devicePath)
128 deviceName = context.prepId(deviceName)
129 device = deviceClass.createInstance(deviceName)
130 device.setManageIp(manageIp)
131 device.manage_editDevice(
132 tag, serialNumber,
133 zSnmpCommunity, zSnmpPort, zSnmpVer,
134 rackSlot, productionState, comments,
135 hwManufacturer, hwProductName,
136 osManufacturer, osProductName,
137 locationPath, groupPaths, systemPaths,
138 performanceMonitor, priority, zProperties)
139 return device
140
141
144 """
145 Find the SNMP community and version for an ip address using zSnmpCommunities.
146
147 @rtype: tuple of (community, port, version, device name)
148 """
149 from pynetsnmp.SnmpSession import SnmpSession
150
151 devroot = context.getDmdRoot('Devices').createOrganizer(devicePath)
152 communities = []
153 if community: communities.append(community)
154 communities.extend(getattr(devroot, "zSnmpCommunities", []))
155 if not port: port = getattr(devroot, "zSnmpPort", 161)
156 versions = ('v2c', 'v1')
157 if not version: version = getattr(devroot, 'zSnmpVer', None)
158 if version: versions = (version,)
159 timeout = getattr(devroot, "zSnmpTimeout", 2)
160 retries = getattr(devroot, "zSnmpTries", 2)
161 session = SnmpSession(ip, timeout=timeout, port=port, retries=retries)
162 oid = '.1.3.6.1.2.1.1.5.0'
163 goodcommunity = ""
164 goodversion = ""
165 devname = ""
166 for version in versions:
167 session.setVersion(version)
168 for community in communities:
169 session.community = community
170 try:
171 devname = session.get(oid).values()[0]
172 goodcommunity = session.community
173 goodversion = version
174 break
175 except (SystemExit, KeyboardInterrupt, POSError): raise
176 except: pass
177 if goodcommunity:
178 break
179 else:
180 raise NoSnmp("No SNMP found for IP = %s" % ip)
181 return (goodcommunity, port, goodversion, devname)
182
195
196 addDevice = DTMLFile('dtml/addDevice',globals())
197
198
199 -class Device(ManagedEntity, Commandable, Lockable, MaintenanceWindowable,
200 AdministrativeRoleable, ZenMenuable):
201 """
202 Device is a base class that represents the idea of a single computer system
203 that is made up of software running on hardware. It currently must be IP
204 enabled but maybe this will change.
205 """
206
207 implements(IEventView)
208
209 event_key = portal_type = meta_type = 'Device'
210
211 default_catalog = "deviceSearch"
212
213 relationshipManagerPathRestriction = '/Devices'
214
215 manageIp = ""
216 productionState = 1000
217 preMWProductionState = productionState
218 snmpAgent = ""
219 snmpDescr = ""
220 snmpOid = ""
221 snmpContact = ""
222 snmpSysName = ""
223 snmpLocation = ""
224 rackSlot = ""
225 comments = ""
226 sysedgeLicenseMode = ""
227 priority = 3
228
229
230 _temp_device = False
231
232 _properties = ManagedEntity._properties + (
233 {'id':'manageIp', 'type':'string', 'mode':'w'},
234 {'id':'productionState', 'type':'keyedselection', 'mode':'w',
235 'select_variable':'getProdStateConversions','setter':'setProdState'},
236 {'id':'preMWProductionState', 'type':'keyedselection', 'mode':'w',
237 'select_variable':'getProdStateConversions','setter':'setProdState'},
238 {'id':'snmpAgent', 'type':'string', 'mode':'w'},
239 {'id':'snmpDescr', 'type':'string', 'mode':''},
240 {'id':'snmpOid', 'type':'string', 'mode':''},
241 {'id':'snmpContact', 'type':'string', 'mode':''},
242 {'id':'snmpSysName', 'type':'string', 'mode':''},
243 {'id':'snmpLocation', 'type':'string', 'mode':''},
244 {'id':'snmpLastCollection', 'type':'date', 'mode':''},
245 {'id':'snmpAgent', 'type':'string', 'mode':''},
246 {'id':'rackSlot', 'type':'string', 'mode':'w'},
247 {'id':'comments', 'type':'text', 'mode':'w'},
248 {'id':'sysedgeLicenseMode', 'type':'string', 'mode':''},
249 {'id':'priority', 'type':'int', 'mode':'w'},
250 )
251
252 _relations = ManagedEntity._relations + (
253 ("deviceClass", ToOne(ToManyCont, "Products.ZenModel.DeviceClass",
254 "devices")),
255 ("perfServer", ToOne(ToMany, "Products.ZenModel.PerformanceConf",
256 "devices")),
257 ("location", ToOne(ToMany, "Products.ZenModel.Location", "devices")),
258 ("systems", ToMany(ToMany, "Products.ZenModel.System", "devices")),
259 ("groups", ToMany(ToMany, "Products.ZenModel.DeviceGroup", "devices")),
260 ("maintenanceWindows",ToManyCont(ToOne,
261 "Products.ZenModel.MaintenanceWindow", "productionState")),
262 ("adminRoles", ToManyCont(ToOne,"Products.ZenModel.AdministrativeRole",
263 "managedObject")),
264 ('userCommands', ToManyCont(ToOne, 'Products.ZenModel.UserCommand',
265 'commandable')),
266
267 ('monitors', ToMany(ToMany, 'Products.ZenModel.StatusMonitorConf',
268 'devices')),
269 )
270
271
272 factory_type_information = (
273 {
274 'id' : 'Device',
275 'meta_type' : 'Device',
276 'description' : """Base class for all devices""",
277 'icon' : 'Device_icon.gif',
278 'product' : 'ZenModel',
279 'factory' : 'manage_addDevice',
280 'immediate_view' : 'deviceStatus',
281 'actions' :
282 (
283 { 'id' : 'status'
284 , 'name' : 'Status'
285 , 'action' : 'deviceStatus'
286 , 'permissions' : (ZEN_VIEW, )
287 },
288 { 'id' : 'osdetail'
289 , 'name' : 'OS'
290 , 'action' : 'deviceOsDetail'
291 , 'permissions' : (ZEN_VIEW, )
292 },
293 { 'id' : 'hwdetail'
294 , 'name' : 'Hardware'
295 , 'action' : 'deviceHardwareDetail'
296 , 'permissions' : (ZEN_VIEW, )
297 },
298 { 'id' : 'swdetail'
299 , 'name' : 'Software'
300 , 'action' : 'deviceSoftwareDetail'
301 , 'permissions' : (ZEN_VIEW, )
302 },
303 { 'id' : 'events'
304 , 'name' : 'Events'
305 , 'action' : 'viewEvents'
306 , 'permissions' : (ZEN_VIEW, )
307 },
308
309
310
311
312
313 { 'id' : 'perfServer'
314 , 'name' : 'Perf'
315 , 'action' : 'viewDevicePerformance'
316 , 'permissions' : (ZEN_VIEW, )
317 },
318
319
320
321
322
323 { 'id' : 'edit'
324 , 'name' : 'Edit'
325 , 'action' : 'editDevice'
326 , 'permissions' : ("Change Device",)
327 },
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353 )
354 },
355 )
356
357 security = ClassSecurityInfo()
358
359 - def __init__(self, id, buildRelations=True):
369
371 flag = getattr(self, '_temp_device', None)
372 if flag is None:
373 flag = self._temp_device = False
374 return flag
375
376
377 security.declareProtected(ZEN_MANAGE_DMD, 'changeDeviceClass')
379 """
380 Wrapper for DeviceClass.moveDevices. The primary reason to use this
381 method instead of that one is that this one redirects the user to the
382 device in the web interface instead of the new device class.
383
384 @param deviceClassPath: device class in DMD path
385 @type deviceClassPath: string
386 @param REQUEST: Zope REQUEST object
387 @type REQUEST: Zope REQUEST object
388 """
389 self.deviceClass().moveDevices(deviceClassPath, (self.id,))
390 if REQUEST:
391 messaging.IMessageSender(self).sendToBrowser(
392 title='Device Moved',
393 body="%s was moved to %s." % (self.id, deviceClassPath))
394 REQUEST['message'] = "%s moved to %s" % (self.id, deviceClassPath)
395 if isinstance(REQUEST, FakeRequest) and \
396 REQUEST.has_key('oneKeyValueSoInstanceIsntEmptyAndEvalToFalse'):
397 return REQUEST['message']
398 device = self.getDmdRoot('Devices').findDevice(self.id)
399 REQUEST['RESPONSE'].redirect(device.absolute_url())
400 return
401
402
404 """
405 DEPRECATED
406 """
407 import warnings
408 warnings.warn('Device.getRRDTemplate is deprecated',
409 DeprecationWarning)
410 return ManagedEntity.getRRDTemplate(self)
411
413 """
414 Returns all the templates bound to this Device
415
416 @rtype: list
417
418 >>> from Products.ZenModel.Device import manage_addDevice
419 >>> manage_addDevice(devices, 'test')
420 >>> devices.test.getRRDTemplates()
421 [<RRDTemplate at /zport/dmd/Devices/rrdTemplates/Device>]
422 """
423 if not hasattr(self, 'zDeviceTemplates'):
424 return ManagedEntity.getRRDTemplates(self)
425 result = []
426 for name in self.zDeviceTemplates:
427 template = self.getRRDTemplateByName(name)
428 if template:
429 result.append(template)
430 return result
431
432
435
436
438 """
439 Returns the available DataSource options. DataSource options
440 are used to populate the dropdown when adding a new DataSource
441 and is a string. See L{RRDTemplate.RRDTemplate.getDataSourceOptions}
442 for more information.
443
444 @rtype: list
445 @return: [(displayName, dsOption),]
446 """
447
448
449
450
451
452 templates = self.getRRDTemplates()
453 if templates:
454 return templates[0].getDataSourceOptions()
455 return []
456
457
458
459
460
461
462
463
464
466 """
467 Returns the cached sysUpTime for this device
468
469 @rtype: int
470 """
471 try:
472 return self.cacheRRDValue('sysUpTime', -1)
473 except Exception:
474 log.exception("failed getting sysUpTime")
475 return -1
476
477
479 """
480 Returns the uptime of this device
481
482 @rtype: string
483 @todo: Performance enhancement: Should move import outside of method
484 """
485 from Products.ZenEvents import Availability
486 results = Availability.query(self.dmd, device=self.id, *args, **kw)
487 if results:
488 return results[0]
489 else:
490 return None
491
492
493
495 """
496 Override from object to handle lastPollSnmpUpTime and
497 snmpLastCollection
498
499 @todo: Not sure this is needed, see getLastPollSnmpUpTime and
500 getSnmpLastCollection
501 """
502 if name == 'lastPollSnmpUpTime':
503 return self._lastPollSnmpUpTime.getStatus()
504 elif name == 'snmpLastCollection':
505 return DateTime(self._snmpLastCollection)
506 else:
507 raise AttributeError( name )
508
509
511 """
512 Override from PropertyManager to handle checks and ip creation
513
514 @todo: Not sure this is needed, see setSnmpLastCollection
515 """
516 self._wrapperCheck(value)
517 if id == 'snmpLastCollection':
518 self._snmpLastCollection = float(value)
519 else:
520 ManagedEntity._setPropValue(self, id, value)
521
522
523 - def applyDataMap(self, datamap, relname="", compname="", modname=""):
530
531
533 """
534 Return a sequence of path tuples suitable for indexing by
535 a MultiPathIndex.
536 """
537 orgs = (
538 self.systems() +
539 self.groups() +
540 [self.location()] +
541 [self.deviceClass()]
542 )
543 orgs = filter(None, orgs)
544 paths = []
545 for org in orgs:
546 rel = org.primaryAq().devices
547 try:
548 orgself = rel._getOb(self.getPrimaryId())
549 except AttributeError:
550
551 orgself = rel._getOb(self.getId())
552 paths.append(orgself.getPhysicalPath())
553 return paths
554
555
557 """
558 Trace the route to target using our routing table.
559 Wrapper method of OperatingSystem.traceRoute
560
561 @param target: Device name
562 @type target: string
563 @param ippath: IP addesses
564 @type ippath: list
565 @return: IP Addresses
566 @rtype: list
567 """
568 if ippath is None: ippath=[]
569 if type(target) in types.StringTypes:
570 target = self.findDevice(target)
571 if not target: raise ValueError("Target %s not found in DMD" % target)
572 return self.os.traceRoute(target, ippath)
573
574
576 """
577 Return list of monitored DeviceComponents on this device.
578 Wrapper method for getDeviceComponents
579 """
580 return self.getDeviceComponents(monitored=True,
581 collector=collector, type=type)
582
583 security.declareProtected(ZEN_VIEW, 'getDeviceComponents')
585 """
586 Return list of all DeviceComponents on this device.
587
588 @type monitored: boolean
589 @type collector: string
590 @type type: string
591 @permission: ZEN_VIEW
592 @rtype: list
593 """
594
595
596
597
598 if not self.componentSearch._catalog.indexes.has_key('getParentDeviceName'):
599 return self.getDeviceComponentsNoIndexGen()
600
601 query = {
602 'getParentDeviceName':self.id,
603 }
604 if collector is not None:
605 query['getCollectors'] = collector
606 if monitored is not None:
607 query['monitored'] = monitored
608 if type is not None:
609 query['meta_type'] = type
610 brains = self.componentSearch(query)
611 return [c.getObject() for c in brains]
612
613
615 """
616 Return a list of all device components by walking relations. This is
617 much slower then the normal getDeviceComponents method which uses the
618 component index. It is used when rebuilding the device indexes.
619 """
620 from DeviceComponent import DeviceComponent
621 for baseObject in (self, self.os, self.hw):
622 for rel in baseObject.getRelationships():
623 if rel.meta_type != "ToManyContRelationship": continue
624 for obj in rel():
625 if not isinstance(obj, DeviceComponent): break
626 yield obj
627
628
637
638
640 """
641 DEPRECATED - Return the hardware manufacturer name of this device.
642
643 @rtype: string
644 @todo: Remove this method and remove the call from testDevice.py
645 """
646 return self.hw.getManufacturerName()
647
648
650 """
651 Return the hardware product name of this device.
652
653 @rtype: string
654 """
655 return self.hw.getProductName()
656
657
659 """
660 DEPRECATED - Return the productKey of the device hardware.
661
662 @rtype: string
663 @todo: Remove this method and remove the call from testDevice.py
664 """
665 return self.hw.getProductKey()
666
667
669 """
670 DEPRECATED - Return the OS manufacturer name of this device.
671
672 @rtype: string
673 @todo: Remove this method and remove the call from testDevice.py
674 """
675 return self.os.getManufacturerName()
676
677
679 """
680 DEPRECATED - Return the OS product name of this device.
681
682 @rtype: string
683 @todo: Remove this method and remove the call from testDevice.py
684 """
685 return self.os.getProductName()
686
687
689 """
690 DEPRECATED - Return the productKey of the device OS.
691
692 @rtype: string
693 @todo: Remove this method and remove the call from testDevice.py
694 """
695 return self.os.getProductKey()
696
697
699 """
700 Set the productKey of the device OS.
701 """
702 self.os.setProductKey(prodKey, manufacturer)
703
704
706 """
707 DEPRECATED - Return the tag of the device HW.
708
709 @rtype: string
710 @todo: remove this method and remove the call from testDevice.py
711 """
712 return self.hw.tag
713
714
716 """
717 Set the asset tag of the device hardware.
718 """
719 self.hw.tag = assettag
720
721
723 """
724 Set the productKey of the device hardware.
725 """
726 self.hw.setProductKey(prodKey, manufacturer)
727
728
730 """
731 Set the hardware serial number.
732 """
733 self.hw.serialNumber = number
734
735
737 """
738 DEPRECATED - Return the hardware serial number.
739
740 @rtype: string
741 @todo: Remove this method and remove the call from testDevice.py
742 """
743 return self.hw.serialNumber
744
745
747 """
748 Return the ips that our indirect routs point to which aren't currently
749 connected to devices.
750
751 @todo: Can be moved to zendisc.py
752 """
753 ips = []
754 for r in self.os.routes():
755 ipobj = r.nexthop()
756
757 if ipobj: ips.append(ipobj.id)
758 return ips
759
760
761 security.declareProtected(ZEN_VIEW, 'getLocationName')
763 """
764 Return the full location name ie /Location/SubLocation/Rack
765
766 @rtype: string
767 @permission: ZEN_VIEW
768 """
769 loc = self.location()
770 if loc: return loc.getOrganizerName()
771 return ""
772
773 security.declareProtected(ZEN_VIEW, 'getLocationLink')
789
790
791 security.declareProtected(ZEN_VIEW, 'getSystemNames')
793 """
794 Return the system names for this device
795
796 @rtype: list
797 @permission: ZEN_VIEW
798 """
799 return map(lambda x: x.getOrganizerName(), self.systems())
800
801
802 security.declareProtected(ZEN_VIEW, 'getSystemNamesString')
804 """
805 Return the system names for this device as a string
806
807 @rtype: string
808 @permission: ZEN_VIEW
809 """
810 return sep.join(self.getSystemNames())
811
812
813 security.declareProtected(ZEN_VIEW, 'getDeviceGroupNames')
815 """
816 Return the device group names for this device
817
818 @rtype: list
819 @permission: ZEN_VIEW
820 """
821 return map(lambda x: x.getOrganizerName(), self.groups())
822
823
824 security.declareProtected(ZEN_VIEW, 'getPerformanceServer')
833
834
835 security.declareProtected(ZEN_VIEW, 'getPerformanceServerName')
846
847
849 """Return the network root object
850 """
851 return self.getDmdRoot('Networks')
852
853 security.declareProtected(ZEN_VIEW, 'getLastChange')
855 """
856 Return DateTime of last change detected on this device.
857
858 @rtype: DateTime
859 @permission: ZEN_VIEW
860 """
861 return DateTime(float(self._lastChange))
862
863
864 security.declareProtected(ZEN_VIEW, 'getLastChangeString')
866 """
867 Return date string of last change detected on this device.
868
869 @rtype: string
870 @permission: ZEN_VIEW
871 """
872 return Time.LocalDateTimeSecsResolution(float(self._lastChange))
873
874
875 security.declareProtected(ZEN_VIEW, 'getSnmpLastCollection')
877 """
878 Return DateTime of last SNMP collection on this device.
879
880 @rtype: DateTime
881 @permission: ZEN_VIEW
882 """
883 return DateTime(float(self._snmpLastCollection))
884
885
886 security.declareProtected(ZEN_VIEW, 'getSnmpLastCollectionString')
888 """
889 Return date string of last SNMP collection on this device.
890
891 @rtype: string
892 @permission: ZEN_VIEW
893 """
894 return Time.LocalDateTimeSecsResolution(float(self._snmpLastCollection))
895
896
897 security.declareProtected(ZEN_ADMIN_DEVICE, 'setManageIp')
899 """
900 Set the manage IP, if IP is not passed perform DNS lookup.
901
902 @rtype: string
903 @permission: ZEN_ADMIN_DEVICE
904 """
905 origip = ip
906 try:
907 if ip.find("/") > -1:
908 ipWithoutNetmask, netmask = ip.split("/",1)
909 checkip(ipWithoutNetmask)
910
911 if maskToBits(netmask) is None: ip = ""
912 else:
913 checkip(ip)
914 except IpAddressError: ip = ""
915 except ValueError: ip = ""
916 if not ip:
917 try: ip = socket.gethostbyname(self.id)
918 except socket.error: ip = ""
919 self.manageIp = ip
920 self.index_object()
921 if REQUEST:
922 msgr = IMessageSender(self)
923 if ip:
924 msgr.sendToBrowser('Manage IP Set',
925 "%s's IP address has been set to %s." % (self.id, ip))
926 else:
927 msgr.sendToBrowser('Invalid IP',
928 ("%s is an invalid IP address, and no appropriate IP could"
929 " be found via DNS") % origip)
930 return self.callZenScreen(REQUEST)
931 else:
932 return self.manageIp
933
934
935 security.declareProtected(ZEN_VIEW, 'getManageIp')
937 """
938 Return the management ip for this device.
939
940 @rtype: string
941 @permission: ZEN_VIEW
942 """
943 return self.manageIp
944
945
947 """
948 DEPRECATED - Return the management ipobject for this device.
949
950 @rtype: IpAddress
951 @todo: This method may not be called anywhere, remove it.
952 """
953 if self.manageIp:
954 return self.Networks.findIp(self.manageIp)
955
956
957 security.declareProtected(ZEN_VIEW, 'getManageInterface')
959 """
960 Return the management interface of a device based on its manageIp.
961
962 @rtype: IpInterface
963 @permission: ZEN_VIEW
964 """
965 ipobj = self.Networks.findIp(self.manageIp)
966 if ipobj: return ipobj.interface()
967
968
969 security.declareProtected(ZEN_VIEW, 'uptimeStr')
971 """
972 Return the SNMP uptime
973
974 @rtype: string
975 @permission: ZEN_VIEW
976 """
977 ut = self.sysUpTime()
978 if ut < 0:
979 return "Unknown"
980 elif ut == 0:
981 return "0d:0h:0m:0s"
982 ut = float(ut)/100.
983 days = ut/86400
984 hour = (ut%86400)/3600
985 mins = (ut%3600)/60
986 secs = ut%60
987 return "%02dd:%02dh:%02dm:%02ds" % (
988 days, hour, mins, secs)
989
990
992 """
993 Build a list of all device paths that have the python class pyclass
994
995 @rtype: list
996 """
997 dclass = self.getDmdRoot("Devices")
998 return dclass.getPeerDeviceClassNames(self.__class__)
999
1000
1001
1002
1003
1004
1005 security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_snmpCommunity')
1007 """
1008 Reset the snmp community using the zSnmpCommunities variable.
1009
1010 @permission: ZEN_CHANGE_DEVICE
1011 """
1012 try:
1013 zSnmpCommunity, zSnmpPort, zSnmpVer, snmpname = \
1014 findCommunity(self, self.manageIp, self.getDeviceClassPath(),
1015 port=self.zSnmpPort, version=self.zSnmpVer)
1016 except NoSnmp:
1017 pass
1018 else:
1019 if self.zSnmpCommunity != zSnmpCommunity:
1020 self.setZenProperty("zSnmpCommunity", zSnmpCommunity)
1021 if self.zSnmpPort != zSnmpPort:
1022 self.setZenProperty("zSnmpPort", zSnmpPort)
1023 if self.zSnmpVer != zSnmpVer:
1024 self.setZenProperty("zSnmpVer", zSnmpVer)
1025
1026
1027 security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_editDevice')
1028 - def manage_editDevice(self,
1029 tag="", serialNumber="",
1030 zSnmpCommunity="", zSnmpPort=161, zSnmpVer="",
1031 rackSlot="", productionState=1000, comments="",
1032 hwManufacturer="", hwProductName="",
1033 osManufacturer="", osProductName="",
1034 locationPath="", groupPaths=[], systemPaths=[],
1035 performanceMonitor="localhost", priority=3,
1036 zProperties=None, REQUEST=None):
1037 """
1038 Edit the device relation and attributes.
1039
1040 @param locationPath: path to a Location
1041 @type locationPath: string
1042 @param groupPaths: paths to DeviceGroups
1043 @type groupPaths: list
1044 @param systemPaths: paths to Systems
1045 @type systemPaths: list
1046 @param performanceMonitor: name of PerformanceMonitor
1047 @type performanceMonitor: string
1048 @permission: ZEN_CHANGE_DEVICE
1049 """
1050 self.hw.tag = tag
1051 self.hw.serialNumber = serialNumber
1052
1053
1054 if zProperties is None: zProperties = {}
1055 zProperties.update({'zSnmpCommunity':zSnmpCommunity,
1056 'zSnmpPort':zSnmpPort,
1057 'zSnmpVer':zSnmpVer})
1058 for prop, value in zProperties.items():
1059 if value and getattr(self, prop) != value:
1060 self.setZenProperty(prop, value)
1061
1062 self.rackSlot = rackSlot
1063 self.setProdState(productionState)
1064 self.setPriority(priority)
1065 self.comments = comments
1066
1067 if hwManufacturer and hwProductName:
1068 log.info("setting hardware manufacturer to %s productName to %s"
1069 % (hwManufacturer, hwProductName))
1070 self.hw.setProduct(hwProductName, hwManufacturer)
1071 else:
1072 self.hw.productClass.removeRelation()
1073
1074 if osManufacturer and osProductName:
1075 log.info("setting os manufacturer to %s productName to %s"
1076 % (osManufacturer, osProductName))
1077 self.os.setProduct(osProductName, osManufacturer)
1078 self.os.productClass().isOS = True
1079 else:
1080 self.os.productClass.removeRelation()
1081
1082 if locationPath:
1083 log.info("setting location to %s" % locationPath)
1084 self.setLocation(locationPath)
1085
1086 if groupPaths:
1087 log.info("setting group %s" % groupPaths)
1088 self.setGroups(groupPaths)
1089
1090 if systemPaths:
1091 log.info("setting system %s" % systemPaths)
1092 self.setSystems(systemPaths)
1093
1094 if performanceMonitor != self.getPerformanceServerName():
1095 log.info("setting performance monitor to %s" % performanceMonitor)
1096 self.setPerformanceMonitor(performanceMonitor)
1097
1098 self.setLastChange()
1099 self.index_object()
1100 if REQUEST:
1101 from Products.ZenUtils.Time import SaveMessage
1102 IMessageSender(self).sendToBrowser('Saved', SaveMessage())
1103 return self.callZenScreen(REQUEST)
1104
1105
1107 """
1108 Returns true if the device production state >= zProdStateThreshold.
1109
1110 @rtype: boolean
1111 """
1112 return self.productionState >= self.zProdStateThreshold
1113
1114
1116 """
1117 Returns true if the device is subject to SNMP monitoring
1118
1119 @rtype: boolean
1120 """
1121 return (self.monitorDevice()
1122 and self.getManageIp()
1123 and not self.zSnmpMonitorIgnore)
1124
1125
1133
1134
1136 """
1137 Return the numeric device priority.
1138
1139 @rtype: int
1140 """
1141 return self.priority
1142
1143
1145 """
1146 Return the device priority as a string.
1147
1148 @rtype: string
1149 """
1150 return self.convertPriority(self.priority)
1151
1153 """
1154 Return the pingStatus as a string
1155
1156 @rtype: string
1157 """
1158 return self.convertStatus(self.getPingStatus())
1159
1161 """
1162 Return the snmpStatus as a string
1163
1164 @rtype: string
1165 """
1166 return self.convertStatus(self.getSnmpStatus())
1167
1168 security.declareProtected(ZEN_CHANGE_DEVICE, 'setProdState')
1169 - def setProdState(self, state, maintWindowChange=False, REQUEST=None):
1214
1215 security.declareProtected(ZEN_CHANGE_DEVICE, 'setPriority')
1249
1250 security.declareProtected(ZEN_CHANGE_DEVICE, 'setLastChange')
1252 """
1253 Set the changed datetime for this device.
1254
1255 @param value: secs since the epoch, default is now
1256 @type value: float
1257 @permission: ZEN_CHANGE_DEVICE
1258 """
1259 if value is None:
1260 value = time.time()
1261 self._lastChange = float(value)
1262
1263 security.declareProtected(ZEN_CHANGE_DEVICE, 'setSnmpLastCollection')
1265 """
1266 Set the last time snmp collection occurred.
1267
1268 @param value: secs since the epoch, default is now
1269 @type value: float
1270 @permission: ZEN_CHANGE_DEVICE
1271 """
1272 if value is None:
1273 value = time.time()
1274 self._snmpLastCollection = float(value)
1275
1276
1277 security.declareProtected(ZEN_CHANGE_DEVICE, 'addManufacturer')
1278 - def addManufacturer(self, newHWManufacturerName=None,
1279 newSWManufacturerName=None, REQUEST=None):
1280 """
1281 DEPRECATED -
1282 Add either a hardware or software manufacturer to the database.
1283
1284 @permission: ZEN_CHANGE_DEVICE
1285 @todo: Doesn't really do work on a device object.
1286 Already exists on ZDeviceLoader
1287 """
1288 mname = newHWManufacturerName
1289 field = 'hwManufacturer'
1290 if not mname:
1291 mname = newSWManufacturerName
1292 field = 'osManufacturer'
1293 self.getDmdRoot("Manufacturers").createManufacturer(mname)
1294 if REQUEST:
1295 REQUEST[field] = mname
1296 messaging.IMessageSender(self).sendToBrowser(
1297 'Manufacturer Added',
1298 'The %s manufacturer has been created.' % mname
1299 )
1300 return self.callZenScreen(REQUEST)
1301
1302
1303 security.declareProtected(ZEN_CHANGE_DEVICE, 'setHWProduct')
1304 - def setHWProduct(self, newHWProductName=None, hwManufacturer=None,
1305 REQUEST=None):
1306 """
1307 DEPRECATED -
1308 Adds a new hardware product
1309
1310 @permission: ZEN_CHANGE_DEVICE
1311 @todo: Doesn't really do work on a device object.
1312 Already exists on ZDeviceLoader
1313 """
1314 added = False
1315 if newHWProductName and hwManufacturer:
1316 self.getDmdRoot("Manufacturers").createHardwareProduct(
1317 newHWProductName, hwManufacturer)
1318 added = True
1319 if REQUEST:
1320 if added:
1321 messaging.IMessageSender(self).sendToBrowser(
1322 'Product Set',
1323 'Hardware product has been set to %s.' % newHWProductName
1324 )
1325 REQUEST['hwProductName'] = newHWProductName
1326 else:
1327 messaging.IMessageSender(self).sendToBrowser(
1328 'Set Product Failed',
1329 'Hardware product could not be set to %s.'%newHWProductName,
1330 priority=messaging.WARNING
1331 )
1332 return self.callZenScreen(REQUEST)
1333
1334
1335 security.declareProtected(ZEN_CHANGE_DEVICE, 'setOSProduct')
1336 - def setOSProduct(self, newOSProductName=None, osManufacturer=None, REQUEST=None):
1362
1363
1364 security.declareProtected(ZEN_CHANGE_DEVICE, 'setLocation')
1378
1379
1380 - def addLocation(self, newLocationPath, REQUEST=None):
1381 """
1382 DEPRECATED
1383 Add a new location and relate it to this device
1384
1385 @todo: Doesn't really do work on a device object.
1386 Already exists on ZDeviceLoader
1387 """
1388 self.getDmdRoot("Locations").createOrganizer(newLocationPath)
1389 if REQUEST:
1390 REQUEST['locationPath'] = newLocationPath
1391 messaging.IMessageSender(self).sendToBrowser(
1392 'Location Added',
1393 'Location %s has been created.' % newLocationPath
1394 )
1395 return self.callZenScreen(REQUEST)
1396
1397
1398 security.declareProtected(ZEN_CHANGE_DEVICE, 'setPerformanceMonitor')
1423
1424
1425 security.declareProtected(ZEN_CHANGE_DEVICE, 'setGroups')
1427 """
1428 Set the list of groups for this device based on a list of paths
1429
1430 @permission: ZEN_CHANGE_DEVICE
1431 """
1432 objGetter = self.getDmdRoot("Groups").createOrganizer
1433 self._setRelations("groups", objGetter, groupPaths)
1434 self.index_object()
1435
1436
1437 security.declareProtected(ZEN_CHANGE_DEVICE, 'addDeviceGroup')
1454
1455
1456 security.declareProtected(ZEN_CHANGE_DEVICE, 'setSystems')
1458 """
1459 Set a list of systems to this device using their system paths
1460
1461 @permission: ZEN_CHANGE_DEVICE
1462 """
1463 objGetter = self.getDmdRoot("Systems").createOrganizer
1464 self._setRelations("systems", objGetter, systemPaths)
1465 self.index_object()
1466
1467
1468 security.declareProtected(ZEN_CHANGE_DEVICE, 'addSystem')
1469 - def addSystem(self, newSystemPath, REQUEST=None):
1485
1486
1487 security.declareProtected(ZEN_CHANGE_DEVICE, 'setTerminalServer')
1489 """
1490 Set the terminal server of this device
1491
1492 @param termservername: device name of terminal server
1493 @permission: ZEN_CHANGE_DEVICE
1494 """
1495 termserver = self.findDevice(termservername)
1496 if termserver:
1497 self.addRelation('termserver', termserver)
1498
1499
1501 """
1502 Set related objects to this device
1503
1504 @param relName: name of the relation to set
1505 @param objGetter: method to get the relation
1506 @param relPaths: list of relationship paths
1507 """
1508 if type(relPaths) != type([]) and type(relPaths) != type(()):
1509 relPaths = [relPaths,]
1510 relPaths = filter(lambda x: x.strip(), relPaths)
1511 rel = getattr(self, relName, None)
1512 if not rel:
1513 raise AttributeError( "Relation %s not found" % relName)
1514 curRelIds = {}
1515 for value in rel.objectValuesAll():
1516 curRelIds[value.getOrganizerName()] = value
1517 for path in relPaths:
1518 if not curRelIds.has_key(path):
1519 robj = objGetter(path)
1520 self.addRelation(relName, robj)
1521 else:
1522 del curRelIds[path]
1523 for obj in curRelIds.values():
1524 self.removeRelation(relName, obj)
1525 self.setAdminLocalRoles()
1526
1527
1529 """
1530 Return the expanded zComment property
1531
1532 @rtype: HTML output
1533 """
1534 from Products.ZenUtils.ZenTales import talesEval
1535 try:
1536 return talesEval('string:' + self.zLinks, self)
1537 except Exception, ex:
1538 import cgi
1539 return "<i class='errortitle'>%s</i>" % cgi.escape(str(ex))
1540
1541
1542
1543
1544
1545 security.declareProtected(ZEN_VIEW, 'device')
1547 """
1548 Support DeviceResultInt mixin class. Returns itself
1549
1550 @permission: ZEN_VIEW
1551 """
1552 return self
1553
1554
1555
1556
1557
1558
1559
1561 """
1562 Returns true if the device has more SNMP failures
1563 than maxFailures on its status mon.
1564
1565 @rtype: boolean
1566 """
1567 statusmon = self.monitors()
1568 if len(statusmon) > 0:
1569 statusmon = statusmon[0]
1570 return statusmon.maxFailures < self.getSnmpStatusNumber()
1571 return False
1572
1573
1574
1575 security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
1576 'getLastPollSnmpUpTime')
1578 """
1579 Get the value of the snmpUpTime status object
1580
1581 @permission: ZEN_MANAGE_DEVICE_STATUS
1582 """
1583 return self._lastPollSnmpUpTime.getStatus()
1584
1585
1586
1587 security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
1588 'setLastPollSnmpUpTime')
1590 """
1591 Set the value of the snmpUpTime status object
1592
1593 @permission: ZEN_MANAGE_DEVICE_STATUS
1594 """
1595 self._lastPollSnmpUpTime.setStatus(value)
1596
1597
1598 - def snmpAgeCheck(self, hours):
1599 """
1600 Returns True if SNMP data was collected more than 24 hours ago
1601 """
1602 lastcoll = self.getSnmpLastCollection()
1603 hours = hours/24.0
1604 if DateTime() > lastcoll + hours: return 1
1605
1606
1608 """
1609 Apply zProperties inherited from Product Contexts.
1610 """
1611 self._applyProdContext(self.hw.getProductContext())
1612 self._applyProdContext(self.os.getProductContext())
1613 for soft in self.os.software():
1614 self._applyProdContext(soft.getProductContext())
1615
1616
1617 - def _applyProdContext(self, context):
1618 """
1619 Apply zProperties taken for the product context passed in.
1620
1621 @param context: list of tuples returned from
1622 getProductContext on a MEProduct.
1623 """
1624 for name, value in context:
1625 if name == "zDeviceClass" and value:
1626 log.info("move device to %s", value)
1627 self.moveDevices(value, self.id)
1628 elif name == "zDeviceGroup" and value:
1629 log.info("add device to group %s", value)
1630 self.addDeviceGroup(value)
1631 elif name == "zSystem" and value:
1632 log.info("add device to system %s", value)
1633 self.addSystem(value)
1634
1635
1636
1637
1638
1639
1640
1641 security.declareProtected(ZEN_MANAGE_DEVICE, 'collectDevice')
1642 - def collectDevice(self, setlog=True, REQUEST=None, generateEvents=False):
1643 """
1644 Collect the configuration of this device AKA Model Device
1645
1646 @param setlog: If true, set up the output log of this process
1647 @permission: ZEN_MANAGE_DEVICE
1648 @todo: generateEvents param is not being used.
1649 """
1650 unused(generateEvents)
1651 xmlrpc = isXmlRpc(REQUEST)
1652 perfConf = self.getPerformanceServer()
1653 perfConf.collectDevice(self, setlog, REQUEST)
1654
1655 if xmlrpc: return 0
1656
1657
1658 security.declareProtected(ZEN_ADMIN_DEVICE, 'deleteDevice')
1659 - def deleteDevice(self, deleteStatus=False, deleteHistory=False,
1660 deletePerf=False, REQUEST=None):
1687
1688
1689 security.declareProtected(ZEN_MANAGE_DEVICE, 'manage_deleteHeartbeat')
1703
1704
1705 security.declareProtected(ZEN_ADMIN_DEVICE, 'renameDevice')
1707 """
1708 Rename device from the DMD
1709
1710 @permission: ZEN_ADMIN_DEVICE
1711 @param newId: new name
1712 @type newId: string
1713 @param REQUEST: Zope REQUEST object
1714 @type REQUEST: Zope REQUEST object
1715 """
1716 parent = self.getPrimaryParent()
1717 oldId = self.getId()
1718 if newId is None:
1719 if REQUEST:
1720 REQUEST['RESPONSE'].redirect("%s/%s" % (parent.absolute_url(), oldId))
1721 return
1722
1723 if not isinstance(newId, unicode):
1724 newId = self.prepId(newId)
1725
1726 newId = newId.strip()
1727
1728 if newId == '' or newId == oldId:
1729 if REQUEST:
1730 REQUEST['RESPONSE'].redirect("%s/%s" % (parent.absolute_url(), oldId))
1731 return
1732
1733
1734 try:
1735 parent.manage_renameObject(oldId, newId)
1736
1737 self.renameDeviceInEvents(oldId, newId)
1738 self.renameDeviceInPerformance(oldId, newId)
1739 self.setLastChange()
1740
1741 if REQUEST:
1742 messaging.IMessageSender(self).sendToBrowser(
1743 'Device Renamed',
1744 "Device %s was renamed to %s." % (oldId, newId)
1745 )
1746 REQUEST['RESPONSE'].redirect("%s/%s" % (parent.absolute_url(), newId))
1747
1748 except CopyError, e:
1749 if REQUEST:
1750 messaging.IMessageSender(self).sendToBrowser(
1751 'Device Rename Failed', str(e), messaging.CRITICAL)
1752 return self.callZenScreen(REQUEST)
1753
1755 """update the device column in the status and history tables for rows
1756 associated with this device"""
1757 zem=self.dmd.ZenEventManager
1758 query="update %%s set device='%s' where device='%s';"%(new, old)
1759 sqlscript=''.join([query%t for t in ('status', 'history')])
1760 args=['mysql',
1761 '-h%s'%zem.host,
1762 '-P%s'%zem.port,
1763 '-u%s'%zem.username,
1764 '-p%s'%zem.password,
1765 '-e%s'%sqlscript,
1766 zem.database,
1767 ]
1768 if not os.fork(): os.execvp('mysql', args)
1769
1790
1797
1798
1805
1806
1815
1816
1818 """
1819 IpAddresses aren't contained underneath Device, so manage_beforeDelete
1820 won't propagate. Thus we must remove those links explicitly.
1821 """
1822 cat = self.dmd.ZenLinkManager._getCatalog(layer=3)
1823 brains = cat(deviceId=self.id)
1824 for brain in brains:
1825 brain.getObject().index_links()
1826
1827
1847
1848
1850 """
1851 Called by Commandable.doCommand() to ascertain objects on which
1852 a UserCommand should be executed.
1853 """
1854 return [self]
1855
1864
1866 """
1867 Returns a URL to redirect to after a command has executed
1868 used by Commandable
1869 """
1870 return self.getPrimaryUrlPath() + '/deviceManagement'
1871
1873 """
1874 Returns HTML Event Summary of a device
1875 """
1876 html = []
1877 html.append("<table width='100%' cellspacing='1' cellpadding='3'>")
1878 html.append("<tr>")
1879 def evsummarycell(ev):
1880 if ev[1]-ev[2]>=0: klass = '%s empty thin' % ev[0]
1881 else: klass = '%s thin' % ev[0]
1882 h = '<th align="center" width="16%%" class="%s">%s/%s</th>' % (
1883 klass, ev[1], ev[2])
1884 return h
1885 info = self.getEventSummary(severity)
1886 html += map(evsummarycell, info)
1887 html.append('</tr></table>')
1888 return '\n'.join(html)
1889
1891 """
1892 Returns data ready for serialization
1893 """
1894 url, classurl = map(urlquote,
1895 (self.getDeviceUrl(), self.getDeviceClassPath()))
1896 id = '<a class="tablevalues" href="%s">%s</a>' % (
1897 url, self.getId())
1898 ip = self.getDeviceIp()
1899 if self.checkRemotePerm(ZEN_VIEW, self.deviceClass()):
1900 path = '<a href="/zport/dmd/Devices%s">%s</a>' % (classurl,classurl)
1901 else:
1902 path = classurl
1903 prod = self.getProdState()
1904 zem = self.dmd.ZenEventManager
1905 evsum = getEventPillME(zem, self, 1, minSeverity)[0]
1906 return [id, ip, path, prod, evsum, self.getId()]
1907
1909 """
1910 Add export of our child objects.
1911 """
1912 map(lambda o: o.exportXml(ofile, ignorerels), (self.hw, self.os))
1913
1915 """
1916 Returns a list of possible options for a given zProperty
1917 """
1918 if propname == 'zCollectorPlugins':
1919 from Products.DataCollector.Plugins import loadPlugins
1920 names = [ldr.pluginName for ldr in loadPlugins(self.dmd)]
1921 names.sort()
1922 return names
1923 if propname == 'zCommandProtocol':
1924 return ['ssh', 'telnet']
1925 if propname == 'zSnmpVer':
1926 return ['v1', 'v2c', 'v3']
1927 if propname == 'zSnmpAuthType':
1928 return ['', 'MD5', 'SHA']
1929 if propname == 'zSnmpPrivType':
1930 return ['', 'DES', 'AES']
1931 return ManagedEntity.zenPropertyOptions(self, propname)
1932
1933 security.declareProtected(ZEN_MANAGE_DEVICE, 'pushConfig')
1935 """
1936 This will result in a push of all the devices to live collectors
1937
1938 @permission: ZEN_MANAGE_DEVICE
1939 """
1940 self._p_changed = True
1941 if REQUEST:
1942 messaging.IMessageSender(self).sendToBrowser(
1943 'Changes Pushed',
1944 'Changes to %s pushed to collectors.' % self.id
1945 )
1946 return self.callZenScreen(REQUEST)
1947
1948 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'bindTemplates')
1950 """
1951 This will bind available templates to the zDeviceTemplates
1952
1953 @permission: ZEN_EDIT_LOCAL_TEMPLATES
1954 """
1955 return self.setZenProperty('zDeviceTemplates', ids, REQUEST)
1956
1957 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'removeZDeviceTemplates')
1959 """
1960 Deletes the local zProperty, zDeviceTemplates
1961
1962 @permission: ZEN_EDIT_LOCAL_TEMPLATES
1963 """
1964 for id in self.zDeviceTemplates:
1965 self.removeLocalRRDTemplate(id)
1966 return self.deleteZenProperty('zDeviceTemplates', REQUEST)
1967
1968 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'addLocalTemplate')
1985
1987 """
1988 Returns all available templates for this device
1989 """
1990
1991 templates = self.objectValues('RRDTemplate')
1992
1993
1994 templates += [t for t in self.deviceClass().getRRDTemplates()
1995 if t.id not in [r.id for r in templates]]
1996 def cmpTemplates(a, b):
1997 return cmp(a.id.lower(), b.id.lower())
1998 templates.sort(cmpTemplates)
1999 return [ t for t in templates
2000 if isinstance(self, t.getTargetPythonClass()) ]
2001
2002
2003 security.declareProtected(ZEN_VIEW, 'getLinks')
2018
2019 security.declareProtected(ZEN_VIEW, 'getXMLEdges')
2020 - def getXMLEdges(self, depth=3, filter="/", start=()):
2028
2029 security.declareProtected(ZEN_VIEW, 'getPrettyLink')
2031 """
2032 Gets a link to this device, plus an icon
2033
2034 @rtype: HTML text
2035 @permission: ZEN_VIEW
2036 """
2037 template = ("<div class='device-icon-container'>"
2038 "<img class='device-icon' src='%s'/> "
2039 "</div>%s")
2040 icon = self.getIconPath()
2041 href = self.getPrimaryUrlPath().replace('%','%%')
2042 name = self.id
2043 linktemplate = "<a href='"+href+"' class='prettylink'>%s</a>"
2044 rendered = template % (icon, name)
2045 if not self.checkRemotePerm(ZEN_VIEW, self):
2046 return rendered
2047 else:
2048 return linktemplate % rendered
2049
2050
2113
2114 InitializeClass(Device)
2115