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 REQUEST['RESPONSE'].redirect(self.primaryAq().absolute_url())
399 return
400
401
403 """
404 DEPRECATED
405 """
406 import warnings
407 warnings.warn('Device.getRRDTemplate is deprecated',
408 DeprecationWarning)
409 return ManagedEntity.getRRDTemplate(self)
410
412 """
413 Returns all the templates bound to this Device
414
415 @rtype: list
416
417 >>> from Products.ZenModel.Device import manage_addDevice
418 >>> manage_addDevice(devices, 'test')
419 >>> devices.test.getRRDTemplates()
420 [<RRDTemplate at /zport/dmd/Devices/rrdTemplates/Device>]
421 """
422 if not hasattr(self, 'zDeviceTemplates'):
423 return ManagedEntity.getRRDTemplates(self)
424 result = []
425 for name in self.zDeviceTemplates:
426 template = self.getRRDTemplateByName(name)
427 if template:
428 result.append(template)
429 return result
430
431
434
435
437 """
438 Returns the available DataSource options. DataSource options
439 are used to populate the dropdown when adding a new DataSource
440 and is a string. See L{RRDTemplate.RRDTemplate.getDataSourceOptions}
441 for more information.
442
443 @rtype: list
444 @return: [(displayName, dsOption),]
445 """
446
447
448
449
450
451 templates = self.getRRDTemplates()
452 if templates:
453 return templates[0].getDataSourceOptions()
454 return []
455
456
457
458
459
460
461
462
463
465 """
466 Returns the cached sysUpTime for this device
467
468 @rtype: int
469 """
470 try:
471 return self.cacheRRDValue('sysUpTime', -1)
472 except Exception:
473 log.exception("failed getting sysUpTime")
474 return -1
475
476
478 """
479 Returns the uptime of this device
480
481 @rtype: string
482 @todo: Performance enhancement: Should move import outside of method
483 """
484 from Products.ZenEvents import Availability
485 results = Availability.query(self.dmd, device=self.id, *args, **kw)
486 if results:
487 return results[0]
488 else:
489 return None
490
491
492
494 """
495 Override from object to handle lastPollSnmpUpTime and
496 snmpLastCollection
497
498 @todo: Not sure this is needed, see getLastPollSnmpUpTime and
499 getSnmpLastCollection
500 """
501 if name == 'lastPollSnmpUpTime':
502 return self._lastPollSnmpUpTime.getStatus()
503 elif name == 'snmpLastCollection':
504 return DateTime(self._snmpLastCollection)
505 else:
506 raise AttributeError( name )
507
508
510 """
511 Override from PropertyManager to handle checks and ip creation
512
513 @todo: Not sure this is needed, see setSnmpLastCollection
514 """
515 self._wrapperCheck(value)
516 if id == 'snmpLastCollection':
517 self._snmpLastCollection = float(value)
518 else:
519 ManagedEntity._setPropValue(self, id, value)
520
521
522 - def applyDataMap(self, datamap, relname="", compname="", modname=""):
529
530
532 """
533 Return a sequence of path tuples suitable for indexing by
534 a MultiPathIndex.
535 """
536 orgs = (
537 self.systems() +
538 self.groups() +
539 [self.location()] +
540 [self.deviceClass()]
541 )
542 orgs = filter(None, orgs)
543 paths = []
544 for org in orgs:
545 rel = org.primaryAq().devices
546 try:
547 orgself = rel._getOb(self.getPrimaryId())
548 except AttributeError:
549
550 orgself = rel._getOb(self.getId())
551 paths.append(orgself.getPhysicalPath())
552 return paths
553
554
556 """
557 Trace the route to target using our routing table.
558 Wrapper method of OperatingSystem.traceRoute
559
560 @param target: Device name
561 @type target: string
562 @param ippath: IP addesses
563 @type ippath: list
564 @return: IP Addresses
565 @rtype: list
566 """
567 if ippath is None: ippath=[]
568 if type(target) in types.StringTypes:
569 target = self.findDevice(target)
570 if not target: raise ValueError("Target %s not found in DMD" % target)
571 return self.os.traceRoute(target, ippath)
572
573
575 """
576 Return list of monitored DeviceComponents on this device.
577 Wrapper method for getDeviceComponents
578 """
579 return self.getDeviceComponents(monitored=True,
580 collector=collector, type=type)
581
582 security.declareProtected(ZEN_VIEW, 'getDeviceComponents')
584 """
585 Return list of all DeviceComponents on this device.
586
587 @type monitored: boolean
588 @type collector: string
589 @type type: string
590 @permission: ZEN_VIEW
591 @rtype: list
592 """
593
594
595
596
597 if not self.componentSearch._catalog.indexes.has_key('getParentDeviceName'):
598 return self.getDeviceComponentsNoIndexGen()
599
600 query = {
601 'getParentDeviceName':self.id,
602 }
603 if collector is not None:
604 query['getCollectors'] = collector
605 if monitored is not None:
606 query['monitored'] = monitored
607 if type is not None:
608 query['meta_type'] = type
609 brains = self.componentSearch(query)
610 return [c.getObject() for c in brains]
611
612
614 """
615 Return a list of all device components by walking relations. This is
616 much slower then the normal getDeviceComponents method which uses the
617 component index. It is used when rebuilding the device indexes.
618 """
619 from DeviceComponent import DeviceComponent
620 for baseObject in (self, self.os, self.hw):
621 for rel in baseObject.getRelationships():
622 if rel.meta_type != "ToManyContRelationship": continue
623 for obj in rel():
624 if not isinstance(obj, DeviceComponent): break
625 yield obj
626
627
636
637
639 """
640 DEPRECATED - Return the hardware manufacturer name of this device.
641
642 @rtype: string
643 @todo: Remove this method and remove the call from testDevice.py
644 """
645 return self.hw.getManufacturerName()
646
647
649 """
650 Return the hardware product name of this device.
651
652 @rtype: string
653 """
654 return self.hw.getProductName()
655
656
658 """
659 DEPRECATED - Return the productKey of the device hardware.
660
661 @rtype: string
662 @todo: Remove this method and remove the call from testDevice.py
663 """
664 return self.hw.getProductKey()
665
666
668 """
669 DEPRECATED - Return the OS manufacturer name of this device.
670
671 @rtype: string
672 @todo: Remove this method and remove the call from testDevice.py
673 """
674 return self.os.getManufacturerName()
675
676
678 """
679 DEPRECATED - Return the OS product name of this device.
680
681 @rtype: string
682 @todo: Remove this method and remove the call from testDevice.py
683 """
684 return self.os.getProductName()
685
686
688 """
689 DEPRECATED - Return the productKey of the device OS.
690
691 @rtype: string
692 @todo: Remove this method and remove the call from testDevice.py
693 """
694 return self.os.getProductKey()
695
696
698 """
699 Set the productKey of the device OS.
700 """
701 self.os.setProductKey(prodKey, manufacturer)
702
703
705 """
706 DEPRECATED - Return the tag of the device HW.
707
708 @rtype: string
709 @todo: remove this method and remove the call from testDevice.py
710 """
711 return self.hw.tag
712
713
715 """
716 Set the asset tag of the device hardware.
717 """
718 self.hw.tag = assettag
719
720
722 """
723 Set the productKey of the device hardware.
724 """
725 self.hw.setProductKey(prodKey, manufacturer)
726
727
729 """
730 Set the hardware serial number.
731 """
732 self.hw.serialNumber = number
733
734
736 """
737 DEPRECATED - Return the hardware serial number.
738
739 @rtype: string
740 @todo: Remove this method and remove the call from testDevice.py
741 """
742 return self.hw.serialNumber
743
744
746 """
747 Return the ips that our indirect routs point to which aren't currently
748 connected to devices.
749
750 @todo: Can be moved to zendisc.py
751 """
752 ips = []
753 for r in self.os.routes():
754 ipobj = r.nexthop()
755
756 if ipobj: ips.append(ipobj.id)
757 return ips
758
759
760 security.declareProtected(ZEN_VIEW, 'getLocationName')
762 """
763 Return the full location name ie /Location/SubLocation/Rack
764
765 @rtype: string
766 @permission: ZEN_VIEW
767 """
768 loc = self.location()
769 if loc: return loc.getOrganizerName()
770 return ""
771
772 security.declareProtected(ZEN_VIEW, 'getLocationLink')
788
789
790 security.declareProtected(ZEN_VIEW, 'getSystemNames')
792 """
793 Return the system names for this device
794
795 @rtype: list
796 @permission: ZEN_VIEW
797 """
798 return map(lambda x: x.getOrganizerName(), self.systems())
799
800
801 security.declareProtected(ZEN_VIEW, 'getSystemNamesString')
803 """
804 Return the system names for this device as a string
805
806 @rtype: string
807 @permission: ZEN_VIEW
808 """
809 return sep.join(self.getSystemNames())
810
811
812 security.declareProtected(ZEN_VIEW, 'getDeviceGroupNames')
814 """
815 Return the device group names for this device
816
817 @rtype: list
818 @permission: ZEN_VIEW
819 """
820 return map(lambda x: x.getOrganizerName(), self.groups())
821
822
823 security.declareProtected(ZEN_VIEW, 'getPerformanceServer')
832
833
834 security.declareProtected(ZEN_VIEW, 'getPerformanceServerName')
845
846
848 """Return the network root object
849 """
850 return self.getDmdRoot('Networks')
851
852 security.declareProtected(ZEN_VIEW, 'getLastChange')
854 """
855 Return DateTime of last change detected on this device.
856
857 @rtype: DateTime
858 @permission: ZEN_VIEW
859 """
860 return DateTime(float(self._lastChange))
861
862
863 security.declareProtected(ZEN_VIEW, 'getLastChangeString')
865 """
866 Return date string of last change detected on this device.
867
868 @rtype: string
869 @permission: ZEN_VIEW
870 """
871 return Time.LocalDateTimeSecsResolution(float(self._lastChange))
872
873
874 security.declareProtected(ZEN_VIEW, 'getSnmpLastCollection')
876 """
877 Return DateTime of last SNMP collection on this device.
878
879 @rtype: DateTime
880 @permission: ZEN_VIEW
881 """
882 return DateTime(float(self._snmpLastCollection))
883
884
885 security.declareProtected(ZEN_VIEW, 'getSnmpLastCollectionString')
887 """
888 Return date string of last SNMP collection on this device.
889
890 @rtype: string
891 @permission: ZEN_VIEW
892 """
893 return Time.LocalDateTimeSecsResolution(float(self._snmpLastCollection))
894
895
896 security.declareProtected(ZEN_ADMIN_DEVICE, 'setManageIp')
898 """
899 Set the manage IP, if IP is not passed perform DNS lookup.
900
901 @rtype: string
902 @permission: ZEN_ADMIN_DEVICE
903 """
904 origip = ip
905 try:
906 if ip.find("/") > -1:
907 ipWithoutNetmask, netmask = ip.split("/",1)
908 checkip(ipWithoutNetmask)
909
910 if maskToBits(netmask) is None: ip = ""
911 else:
912 checkip(ip)
913 except IpAddressError: ip = ""
914 except ValueError: ip = ""
915 if not ip:
916 try: ip = socket.gethostbyname(self.id)
917 except socket.error: ip = ""
918 self.manageIp = ip
919 self.index_object()
920 if REQUEST:
921 msgr = IMessageSender(self)
922 if ip:
923 msgr.sendToBrowser('Manage IP Set',
924 "%s's IP address has been set to %s." % (self.id, ip))
925 else:
926 msgr.sendToBrowser('Invalid IP',
927 ("%s is an invalid IP address, and no appropriate IP could"
928 " be found via DNS") % origip)
929 return self.callZenScreen(REQUEST)
930 else:
931 return self.manageIp
932
933
934 security.declareProtected(ZEN_VIEW, 'getManageIp')
936 """
937 Return the management ip for this device.
938
939 @rtype: string
940 @permission: ZEN_VIEW
941 """
942 return self.manageIp
943
944
946 """
947 DEPRECATED - Return the management ipobject for this device.
948
949 @rtype: IpAddress
950 @todo: This method may not be called anywhere, remove it.
951 """
952 if self.manageIp:
953 return self.Networks.findIp(self.manageIp)
954
955
956 security.declareProtected(ZEN_VIEW, 'getManageInterface')
958 """
959 Return the management interface of a device based on its manageIp.
960
961 @rtype: IpInterface
962 @permission: ZEN_VIEW
963 """
964 ipobj = self.Networks.findIp(self.manageIp)
965 if ipobj: return ipobj.interface()
966
967
968 security.declareProtected(ZEN_VIEW, 'uptimeStr')
970 """
971 Return the SNMP uptime
972
973 @rtype: string
974 @permission: ZEN_VIEW
975 """
976 ut = self.sysUpTime()
977 if ut < 0:
978 return "Unknown"
979 elif ut == 0:
980 return "0d:0h:0m:0s"
981 ut = float(ut)/100.
982 days = ut/86400
983 hour = (ut%86400)/3600
984 mins = (ut%3600)/60
985 secs = ut%60
986 return "%02dd:%02dh:%02dm:%02ds" % (
987 days, hour, mins, secs)
988
989
991 """
992 Build a list of all device paths that have the python class pyclass
993
994 @rtype: list
995 """
996 dclass = self.getDmdRoot("Devices")
997 return dclass.getPeerDeviceClassNames(self.__class__)
998
999
1000
1001
1002
1003
1004 security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_snmpCommunity')
1006 """
1007 Reset the snmp community using the zSnmpCommunities variable.
1008
1009 @permission: ZEN_CHANGE_DEVICE
1010 """
1011 try:
1012 zSnmpCommunity, zSnmpPort, zSnmpVer, snmpname = \
1013 findCommunity(self, self.manageIp, self.getDeviceClassPath(),
1014 port=self.zSnmpPort, version=self.zSnmpVer)
1015 except NoSnmp:
1016 pass
1017 else:
1018 if self.zSnmpCommunity != zSnmpCommunity:
1019 self.setZenProperty("zSnmpCommunity", zSnmpCommunity)
1020 if self.zSnmpPort != zSnmpPort:
1021 self.setZenProperty("zSnmpPort", zSnmpPort)
1022 if self.zSnmpVer != zSnmpVer:
1023 self.setZenProperty("zSnmpVer", zSnmpVer)
1024
1025
1026 security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_editDevice')
1027 - def manage_editDevice(self,
1028 tag="", serialNumber="",
1029 zSnmpCommunity="", zSnmpPort=161, zSnmpVer="",
1030 rackSlot="", productionState=1000, comments="",
1031 hwManufacturer="", hwProductName="",
1032 osManufacturer="", osProductName="",
1033 locationPath="", groupPaths=[], systemPaths=[],
1034 performanceMonitor="localhost", priority=3,
1035 zProperties=None, REQUEST=None):
1036 """
1037 Edit the device relation and attributes.
1038
1039 @param locationPath: path to a Location
1040 @type locationPath: string
1041 @param groupPaths: paths to DeviceGroups
1042 @type groupPaths: list
1043 @param systemPaths: paths to Systems
1044 @type systemPaths: list
1045 @param performanceMonitor: name of PerformanceMonitor
1046 @type performanceMonitor: string
1047 @permission: ZEN_CHANGE_DEVICE
1048 """
1049 self.hw.tag = tag
1050 self.hw.serialNumber = serialNumber
1051
1052
1053 if zProperties is None: zProperties = {}
1054 zProperties.update({'zSnmpCommunity':zSnmpCommunity,
1055 'zSnmpPort':zSnmpPort,
1056 'zSnmpVer':zSnmpVer})
1057 for prop, value in zProperties.items():
1058 if value and getattr(self, prop) != value:
1059 self.setZenProperty(prop, value)
1060
1061 self.rackSlot = rackSlot
1062 self.setProdState(productionState)
1063 self.setPriority(priority)
1064 self.comments = comments
1065
1066 if hwManufacturer and hwProductName:
1067 log.info("setting hardware manufacturer to %s productName to %s"
1068 % (hwManufacturer, hwProductName))
1069 self.hw.setProduct(hwProductName, hwManufacturer)
1070 else:
1071 self.hw.productClass.removeRelation()
1072
1073 if osManufacturer and osProductName:
1074 log.info("setting os manufacturer to %s productName to %s"
1075 % (osManufacturer, osProductName))
1076 self.os.setProduct(osProductName, osManufacturer)
1077 self.os.productClass().isOS = True
1078 else:
1079 self.os.productClass.removeRelation()
1080
1081 if locationPath:
1082 log.info("setting location to %s" % locationPath)
1083 self.setLocation(locationPath)
1084
1085 if groupPaths:
1086 log.info("setting group %s" % groupPaths)
1087 self.setGroups(groupPaths)
1088
1089 if systemPaths:
1090 log.info("setting system %s" % systemPaths)
1091 self.setSystems(systemPaths)
1092
1093 if performanceMonitor != self.getPerformanceServerName():
1094 log.info("setting performance monitor to %s" % performanceMonitor)
1095 self.setPerformanceMonitor(performanceMonitor)
1096
1097 self.setLastChange()
1098 self.index_object()
1099 if REQUEST:
1100 from Products.ZenUtils.Time import SaveMessage
1101 IMessageSender(self).sendToBrowser('Saved', SaveMessage())
1102 return self.callZenScreen(REQUEST)
1103
1104
1106 """
1107 Returns true if the device production state >= zProdStateThreshold.
1108
1109 @rtype: boolean
1110 """
1111 return self.productionState >= self.zProdStateThreshold
1112
1113
1115 """
1116 Returns true if the device is subject to SNMP monitoring
1117
1118 @rtype: boolean
1119 """
1120 return (self.monitorDevice()
1121 and self.getManageIp()
1122 and not self.zSnmpMonitorIgnore)
1123
1124
1132
1133
1135 """
1136 Return the numeric device priority.
1137
1138 @rtype: int
1139 """
1140 return self.priority
1141
1142
1144 """
1145 Return the device priority as a string.
1146
1147 @rtype: string
1148 """
1149 return self.convertPriority(self.priority)
1150
1152 """
1153 Return the pingStatus as a string
1154
1155 @rtype: string
1156 """
1157 return self.convertStatus(self.getPingStatus())
1158
1160 """
1161 Return the snmpStatus as a string
1162
1163 @rtype: string
1164 """
1165 return self.convertStatus(self.getSnmpStatus())
1166
1167 security.declareProtected(ZEN_CHANGE_DEVICE, 'setProdState')
1168 - def setProdState(self, state, maintWindowChange=False, REQUEST=None):
1213
1214 security.declareProtected(ZEN_CHANGE_DEVICE, 'setPriority')
1248
1249 security.declareProtected(ZEN_CHANGE_DEVICE, 'setLastChange')
1251 """
1252 Set the changed datetime for this device.
1253
1254 @param value: secs since the epoch, default is now
1255 @type value: float
1256 @permission: ZEN_CHANGE_DEVICE
1257 """
1258 if value is None:
1259 value = time.time()
1260 self._lastChange = float(value)
1261
1262 security.declareProtected(ZEN_CHANGE_DEVICE, 'setSnmpLastCollection')
1264 """
1265 Set the last time snmp collection occurred.
1266
1267 @param value: secs since the epoch, default is now
1268 @type value: float
1269 @permission: ZEN_CHANGE_DEVICE
1270 """
1271 if value is None:
1272 value = time.time()
1273 self._snmpLastCollection = float(value)
1274
1275
1276 security.declareProtected(ZEN_CHANGE_DEVICE, 'addManufacturer')
1277 - def addManufacturer(self, newHWManufacturerName=None,
1278 newSWManufacturerName=None, REQUEST=None):
1279 """
1280 DEPRECATED -
1281 Add either a hardware or software manufacturer to the database.
1282
1283 @permission: ZEN_CHANGE_DEVICE
1284 @todo: Doesn't really do work on a device object.
1285 Already exists on ZDeviceLoader
1286 """
1287 mname = newHWManufacturerName
1288 field = 'hwManufacturer'
1289 if not mname:
1290 mname = newSWManufacturerName
1291 field = 'osManufacturer'
1292 self.getDmdRoot("Manufacturers").createManufacturer(mname)
1293 if REQUEST:
1294 REQUEST[field] = mname
1295 messaging.IMessageSender(self).sendToBrowser(
1296 'Manufacturer Added',
1297 'The %s manufacturer has been created.' % mname
1298 )
1299 return self.callZenScreen(REQUEST)
1300
1301
1302 security.declareProtected(ZEN_CHANGE_DEVICE, 'setHWProduct')
1303 - def setHWProduct(self, newHWProductName=None, hwManufacturer=None,
1304 REQUEST=None):
1305 """
1306 DEPRECATED -
1307 Adds a new hardware product
1308
1309 @permission: ZEN_CHANGE_DEVICE
1310 @todo: Doesn't really do work on a device object.
1311 Already exists on ZDeviceLoader
1312 """
1313 added = False
1314 if newHWProductName and hwManufacturer:
1315 self.getDmdRoot("Manufacturers").createHardwareProduct(
1316 newHWProductName, hwManufacturer)
1317 added = True
1318 if REQUEST:
1319 if added:
1320 messaging.IMessageSender(self).sendToBrowser(
1321 'Product Set',
1322 'Hardware product has been set to %s.' % newHWProductName
1323 )
1324 REQUEST['hwProductName'] = newHWProductName
1325 else:
1326 messaging.IMessageSender(self).sendToBrowser(
1327 'Set Product Failed',
1328 'Hardware product could not be set to %s.'%newHWProductName,
1329 priority=messaging.WARNING
1330 )
1331 return self.callZenScreen(REQUEST)
1332
1333
1334 security.declareProtected(ZEN_CHANGE_DEVICE, 'setOSProduct')
1335 - def setOSProduct(self, newOSProductName=None, osManufacturer=None, REQUEST=None):
1361
1362
1363 security.declareProtected(ZEN_CHANGE_DEVICE, 'setLocation')
1377
1378
1379 - def addLocation(self, newLocationPath, REQUEST=None):
1380 """
1381 DEPRECATED
1382 Add a new location and relate it to this device
1383
1384 @todo: Doesn't really do work on a device object.
1385 Already exists on ZDeviceLoader
1386 """
1387 self.getDmdRoot("Locations").createOrganizer(newLocationPath)
1388 if REQUEST:
1389 REQUEST['locationPath'] = newLocationPath
1390 messaging.IMessageSender(self).sendToBrowser(
1391 'Location Added',
1392 'Location %s has been created.' % newLocationPath
1393 )
1394 return self.callZenScreen(REQUEST)
1395
1396
1397 security.declareProtected(ZEN_CHANGE_DEVICE, 'setPerformanceMonitor')
1422
1423
1424 security.declareProtected(ZEN_CHANGE_DEVICE, 'setGroups')
1426 """
1427 Set the list of groups for this device based on a list of paths
1428
1429 @permission: ZEN_CHANGE_DEVICE
1430 """
1431 objGetter = self.getDmdRoot("Groups").createOrganizer
1432 self._setRelations("groups", objGetter, groupPaths)
1433 self.index_object()
1434
1435
1436 security.declareProtected(ZEN_CHANGE_DEVICE, 'addDeviceGroup')
1453
1454
1455 security.declareProtected(ZEN_CHANGE_DEVICE, 'setSystems')
1457 """
1458 Set a list of systems to this device using their system paths
1459
1460 @permission: ZEN_CHANGE_DEVICE
1461 """
1462 objGetter = self.getDmdRoot("Systems").createOrganizer
1463 self._setRelations("systems", objGetter, systemPaths)
1464 self.index_object()
1465
1466
1467 security.declareProtected(ZEN_CHANGE_DEVICE, 'addSystem')
1468 - def addSystem(self, newSystemPath, REQUEST=None):
1484
1485
1486 security.declareProtected(ZEN_CHANGE_DEVICE, 'setTerminalServer')
1488 """
1489 Set the terminal server of this device
1490
1491 @param termservername: device name of terminal server
1492 @permission: ZEN_CHANGE_DEVICE
1493 """
1494 termserver = self.findDevice(termservername)
1495 if termserver:
1496 self.addRelation('termserver', termserver)
1497
1498
1500 """
1501 Set related objects to this device
1502
1503 @param relName: name of the relation to set
1504 @param objGetter: method to get the relation
1505 @param relPaths: list of relationship paths
1506 """
1507 if type(relPaths) != type([]) and type(relPaths) != type(()):
1508 relPaths = [relPaths,]
1509 relPaths = filter(lambda x: x.strip(), relPaths)
1510 rel = getattr(self, relName, None)
1511 if not rel:
1512 raise AttributeError( "Relation %s not found" % relName)
1513 curRelIds = {}
1514 for value in rel.objectValuesAll():
1515 curRelIds[value.getOrganizerName()] = value
1516 for path in relPaths:
1517 if not curRelIds.has_key(path):
1518 robj = objGetter(path)
1519 self.addRelation(relName, robj)
1520 else:
1521 del curRelIds[path]
1522 for obj in curRelIds.values():
1523 self.removeRelation(relName, obj)
1524 self.setAdminLocalRoles()
1525
1526
1528 """
1529 Return the expanded zComment property
1530
1531 @rtype: HTML output
1532 """
1533 from Products.ZenUtils.ZenTales import talesEval
1534 try:
1535 return talesEval('string:' + self.zLinks, self)
1536 except Exception, ex:
1537 import cgi
1538 return "<i class='errortitle'>%s</i>" % cgi.escape(str(ex))
1539
1540
1541
1542
1543
1544 security.declareProtected(ZEN_VIEW, 'device')
1546 """
1547 Support DeviceResultInt mixin class. Returns itself
1548
1549 @permission: ZEN_VIEW
1550 """
1551 return self
1552
1553
1554
1555
1556
1557
1558
1560 """
1561 Returns true if the device has more SNMP failures
1562 than maxFailures on its status mon.
1563
1564 @rtype: boolean
1565 """
1566 statusmon = self.monitors()
1567 if len(statusmon) > 0:
1568 statusmon = statusmon[0]
1569 return statusmon.maxFailures < self.getSnmpStatusNumber()
1570 return False
1571
1572
1573
1574 security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
1575 'getLastPollSnmpUpTime')
1577 """
1578 Get the value of the snmpUpTime status object
1579
1580 @permission: ZEN_MANAGE_DEVICE_STATUS
1581 """
1582 return self._lastPollSnmpUpTime.getStatus()
1583
1584
1585
1586 security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
1587 'setLastPollSnmpUpTime')
1589 """
1590 Set the value of the snmpUpTime status object
1591
1592 @permission: ZEN_MANAGE_DEVICE_STATUS
1593 """
1594 self._lastPollSnmpUpTime.setStatus(value)
1595
1596
1597 - def snmpAgeCheck(self, hours):
1598 """
1599 Returns True if SNMP data was collected more than 24 hours ago
1600 """
1601 lastcoll = self.getSnmpLastCollection()
1602 hours = hours/24.0
1603 if DateTime() > lastcoll + hours: return 1
1604
1605
1607 """
1608 Apply zProperties inherited from Product Contexts.
1609 """
1610 self._applyProdContext(self.hw.getProductContext())
1611 self._applyProdContext(self.os.getProductContext())
1612 for soft in self.os.software():
1613 self._applyProdContext(soft.getProductContext())
1614
1615
1616 - def _applyProdContext(self, context):
1617 """
1618 Apply zProperties taken for the product context passed in.
1619
1620 @param context: list of tuples returned from
1621 getProductContext on a MEProduct.
1622 """
1623 for name, value in context:
1624 if name == "zDeviceClass" and value:
1625 log.info("move device to %s", value)
1626 self.moveDevices(value, self.id)
1627 elif name == "zDeviceGroup" and value:
1628 log.info("add device to group %s", value)
1629 self.addDeviceGroup(value)
1630 elif name == "zSystem" and value:
1631 log.info("add device to system %s", value)
1632 self.addSystem(value)
1633
1634
1635
1636
1637
1638
1639
1640 security.declareProtected(ZEN_MANAGE_DEVICE, 'collectDevice')
1641 - def collectDevice(self, setlog=True, REQUEST=None, generateEvents=False):
1642 """
1643 Collect the configuration of this device AKA Model Device
1644
1645 @param setlog: If true, set up the output log of this process
1646 @permission: ZEN_MANAGE_DEVICE
1647 @todo: generateEvents param is not being used.
1648 """
1649 unused(generateEvents)
1650 xmlrpc = isXmlRpc(REQUEST)
1651 perfConf = self.getPerformanceServer()
1652 perfConf.collectDevice(self, setlog, REQUEST)
1653
1654 if xmlrpc: return 0
1655
1656
1657 security.declareProtected(ZEN_ADMIN_DEVICE, 'deleteDevice')
1658 - def deleteDevice(self, deleteStatus=False, deleteHistory=False,
1659 deletePerf=False, REQUEST=None):
1686
1687
1688 security.declareProtected(ZEN_MANAGE_DEVICE, 'manage_deleteHeartbeat')
1702
1703
1704 security.declareProtected(ZEN_ADMIN_DEVICE, 'renameDevice')
1706 """
1707 Rename device from the DMD
1708
1709 @permission: ZEN_ADMIN_DEVICE
1710 @param newId: new name
1711 @type newId: string
1712 @param REQUEST: Zope REQUEST object
1713 @type REQUEST: Zope REQUEST object
1714 """
1715 parent = self.getPrimaryParent()
1716 oldId = self.getId()
1717 if newId is None:
1718 if REQUEST:
1719 REQUEST['RESPONSE'].redirect("%s/%s" % (parent.absolute_url(), oldId))
1720 return
1721
1722 if not isinstance(newId, unicode):
1723 newId = self.prepId(newId)
1724
1725 newId = newId.strip()
1726
1727 if newId == '' or newId == oldId:
1728 if REQUEST:
1729 REQUEST['RESPONSE'].redirect("%s/%s" % (parent.absolute_url(), oldId))
1730 return
1731
1732
1733 try:
1734 parent.manage_renameObject(oldId, newId)
1735
1736 self.renameDeviceInEvents(oldId, newId)
1737 self.renameDeviceInPerformance(oldId, newId)
1738 self.setLastChange()
1739
1740 if REQUEST:
1741 messaging.IMessageSender(self).sendToBrowser(
1742 'Device Renamed',
1743 "Device %s was renamed to %s." % (oldId, newId)
1744 )
1745 REQUEST['RESPONSE'].redirect("%s/%s" % (parent.absolute_url(), newId))
1746
1747 except CopyError, e:
1748 if REQUEST:
1749 messaging.IMessageSender(self).sendToBrowser(
1750 'Device Rename Failed', str(e), messaging.CRITICAL)
1751 return self.callZenScreen(REQUEST)
1752
1754 """update the device column in the status and history tables for rows
1755 associated with this device"""
1756 zem=self.dmd.ZenEventManager
1757 query="update %%s set device='%s' where device='%s';"%(new, old)
1758 sqlscript=''.join([query%t for t in ('status', 'history')])
1759 args=['mysql',
1760 '-h%s'%zem.host,
1761 '-P%s'%zem.port,
1762 '-u%s'%zem.username,
1763 '-p%s'%zem.password,
1764 '-e%s'%sqlscript,
1765 zem.database,
1766 ]
1767 if not os.fork(): os.execvp('mysql', args)
1768
1789
1796
1797
1804
1805
1814
1815
1817 """
1818 IpAddresses aren't contained underneath Device, so manage_beforeDelete
1819 won't propagate. Thus we must remove those links explicitly.
1820 """
1821 cat = self.dmd.ZenLinkManager._getCatalog(layer=3)
1822 brains = cat(deviceId=self.id)
1823 for brain in brains:
1824 brain.getObject().index_links()
1825
1826
1846
1847
1849 """
1850 Called by Commandable.doCommand() to ascertain objects on which
1851 a UserCommand should be executed.
1852 """
1853 return [self]
1854
1863
1865 """
1866 Returns a URL to redirect to after a command has executed
1867 used by Commandable
1868 """
1869 return self.getPrimaryUrlPath() + '/deviceManagement'
1870
1872 """
1873 Returns HTML Event Summary of a device
1874 """
1875 html = []
1876 html.append("<table width='100%' cellspacing='1' cellpadding='3'>")
1877 html.append("<tr>")
1878 def evsummarycell(ev):
1879 if ev[1]-ev[2]>=0: klass = '%s empty thin' % ev[0]
1880 else: klass = '%s thin' % ev[0]
1881 h = '<th align="center" width="16%%" class="%s">%s/%s</th>' % (
1882 klass, ev[1], ev[2])
1883 return h
1884 info = self.getEventSummary(severity)
1885 html += map(evsummarycell, info)
1886 html.append('</tr></table>')
1887 return '\n'.join(html)
1888
1890 """
1891 Returns data ready for serialization
1892 """
1893 url, classurl = map(urlquote,
1894 (self.getDeviceUrl(), self.getDeviceClassPath()))
1895 id = '<a class="tablevalues" href="%s">%s</a>' % (
1896 url, self.getId())
1897 ip = self.getDeviceIp()
1898 if self.checkRemotePerm(ZEN_VIEW, self.deviceClass()):
1899 path = '<a href="/zport/dmd/Devices%s">%s</a>' % (classurl,classurl)
1900 else:
1901 path = classurl
1902 prod = self.getProdState()
1903 zem = self.dmd.ZenEventManager
1904 evsum = getEventPillME(zem, self, 1, minSeverity)[0]
1905 return [id, ip, path, prod, evsum, self.getId()]
1906
1908 """
1909 Add export of our child objects.
1910 """
1911 map(lambda o: o.exportXml(ofile, ignorerels), (self.hw, self.os))
1912
1914 """
1915 Returns a list of possible options for a given zProperty
1916 """
1917 if propname == 'zCollectorPlugins':
1918 from Products.DataCollector.Plugins import loadPlugins
1919 names = [ldr.pluginName() for ldr in loadPlugins(self.dmd)]
1920 names.sort()
1921 return names
1922 if propname == 'zCommandProtocol':
1923 return ['ssh', 'telnet']
1924 if propname == 'zSnmpVer':
1925 return ['v1', 'v2c', 'v3']
1926 if propname == 'zSnmpAuthType':
1927 return ['', 'MD5', 'SHA']
1928 if propname == 'zSnmpPrivType':
1929 return ['', 'DES', 'AES']
1930 return ManagedEntity.zenPropertyOptions(self, propname)
1931
1932 security.declareProtected(ZEN_MANAGE_DEVICE, 'pushConfig')
1934 """
1935 This will result in a push of all the devices to live collectors
1936
1937 @permission: ZEN_MANAGE_DEVICE
1938 """
1939 self._p_changed = True
1940 if REQUEST:
1941 messaging.IMessageSender(self).sendToBrowser(
1942 'Changes Pushed',
1943 'Changes to %s pushed to collectors.' % self.id
1944 )
1945 return self.callZenScreen(REQUEST)
1946
1947 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'bindTemplates')
1949 """
1950 This will bind available templates to the zDeviceTemplates
1951
1952 @permission: ZEN_EDIT_LOCAL_TEMPLATES
1953 """
1954 return self.setZenProperty('zDeviceTemplates', ids, REQUEST)
1955
1956 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'removeZDeviceTemplates')
1958 """
1959 Deletes the local zProperty, zDeviceTemplates
1960
1961 @permission: ZEN_EDIT_LOCAL_TEMPLATES
1962 """
1963 for id in self.zDeviceTemplates:
1964 self.removeLocalRRDTemplate(id)
1965 return self.deleteZenProperty('zDeviceTemplates', REQUEST)
1966
1967 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'addLocalTemplate')
1984
1986 """
1987 Returns all available templates for this device
1988 """
1989
1990 templates = self.objectValues('RRDTemplate')
1991
1992
1993 templates += [t for t in self.deviceClass().getRRDTemplates()
1994 if t.id not in [r.id for r in templates]]
1995 def cmpTemplates(a, b):
1996 return cmp(a.id.lower(), b.id.lower())
1997 templates.sort(cmpTemplates)
1998 return [ t for t in templates
1999 if isinstance(self, t.getTargetPythonClass()) ]
2000
2001
2002 security.declareProtected(ZEN_VIEW, 'getLinks')
2017
2018 security.declareProtected(ZEN_VIEW, 'getXMLEdges')
2019 - def getXMLEdges(self, depth=3, filter="/", start=()):
2027
2028 security.declareProtected(ZEN_VIEW, 'getPrettyLink')
2030 """
2031 Gets a link to this device, plus an icon
2032
2033 @rtype: HTML text
2034 @permission: ZEN_VIEW
2035 """
2036 template = ("<div class='device-icon-container'>"
2037 "<img class='device-icon' src='%s'/> "
2038 "</div>%s")
2039 icon = self.getIconPath()
2040 href = self.getPrimaryUrlPath().replace('%','%%')
2041 name = self.id
2042 linktemplate = "<a href='"+href+"' class='prettylink'>%s</a>"
2043 rendered = template % (icon, name)
2044 if not self.checkRemotePerm(ZEN_VIEW, self):
2045 return rendered
2046 else:
2047 return linktemplate % rendered
2048
2049
2112
2113 InitializeClass(Device)
2114