1
2
3
4
5
6
7
8
9
10
11
12 __doc__ = """Device
13 Base device (remote computer) class
14 """
15
16 import os
17 import shutil
18 import time
19 import socket
20 import logging
21 log = logging.getLogger("zen.Device")
22
23 from urllib import quote as urlquote
24 from ipaddr import IPAddress
25 from Acquisition import aq_base
26 from zope.event import notify
27 from AccessControl.PermissionRole import rolesForPermissionOn
28 from Products.Zuul.catalog.events import IndexingEvent
29 from Products.ZenUtils.Utils import isXmlRpc, unused, getObjectsFromCatalog
30 from Products.ZenUtils import Time
31 from Products.ZenUtils.deprecated import deprecated
32
33 import RRDView
34 from Products import Zuul
35 from Products.Zuul.interfaces import IInfo
36 from Products.ZenUtils.jsonutils import json
37 from Products.ZenUtils.IpUtil import checkip, IpAddressError, maskToBits, \
38 ipunwrap, getHostByName
39 from Products.ZenModel.interfaces import IIndexed
40 from Products.ZenUtils.guid.interfaces import IGloballyIdentifiable, IGlobalIdentifier
41 from Products.PluginIndexes.FieldIndex.FieldIndex import FieldIndex
42
43 from ManagedEntity import ManagedEntity
44
45 from AccessControl import ClassSecurityInfo
46 from Globals import DTMLFile
47 from Globals import InitializeClass
48 from DateTime import DateTime
49 from zExceptions import NotFound
50 from ZODB.POSException import POSError
51 from ZODB.transact import transact
52
53
54 from Products.DataCollector.ApplyDataMap import ApplyDataMap
55
56 from Products.ZenRelations.RelSchema import *
57 from Commandable import Commandable
58 from Lockable import Lockable
59 from MaintenanceWindowable import MaintenanceWindowable
60 from AdministrativeRoleable import AdministrativeRoleable
61 from ZenMenuable import ZenMenuable
62
63 from OperatingSystem import OperatingSystem
64 from DeviceHW import DeviceHW
65
66 from ZenStatus import ZenStatus
67 from Products.ZenModel.Exceptions import *
68 from ZenossSecurity import *
69 from Products.ZenUtils.Utils import edgesToXML
70 from Products.ZenUtils import NetworkTree
71
72 from zope.interface import implements
73 from zope.component import subscribers
74 from EventView import IEventView
75 from Products.ZenWidgets.interfaces import IMessageSender
76 from Products.ZenWidgets import messaging
77 from Products.ZenEvents.browser.EventPillsAndSummaries import getEventPillME
78 from OFS.CopySupport import CopyError
79 from Products.Zuul import getFacade
80 from Products.ZenUtils.IpUtil import numbip
81 from Products.ZenMessaging.audit import audit
82 from Products.ZenModel.interfaces import IExpandedLinkProvider
83 from Products.ZenUtils.Search import makeCaseInsensitiveFieldIndex, makeCaseInsensitiveFieldIndex
84 from Products.ZenUtils.Search import makeCaseInsensitiveKeywordIndex
85 from Products.ZenUtils.Search import makePathIndex, makeMultiPathIndex
88 """
89 Return the default network root.
90 """
91 return context.getDmdRoot('Networks')
92
114
115
116 -def manage_createDevice(context, deviceName, devicePath="/Discovered",
117 tag="", serialNumber="",
118 zSnmpCommunity="", zSnmpPort=161, zSnmpVer="",
119 rackSlot="", productionState=1000, comments="",
120 hwManufacturer="", hwProductName="",
121 osManufacturer="", osProductName="",
122 locationPath="", groupPaths=[], systemPaths=[],
123 performanceMonitor="localhost",
124 discoverProto="snmp", priority=3, manageIp="",
125 zProperties=None, title=None):
126 """
127 Device factory creates a device and sets up its relations and collects its
128 configuration. SNMP Community discovery also happens here. If an IP is
129 passed for deviceName it will be used for collection and the device name
130 will be set to the SNMP SysName (or ptr if SNMP Fails and ptr is valid)
131
132 @rtype: Device
133 """
134 manageIp = manageIp.replace(' ', '')
135 checkDeviceExists(context, deviceName, manageIp, performanceMonitor)
136 deviceName = context.prepId(deviceName)
137 log.info("device name '%s' for ip '%s'", deviceName, manageIp)
138 deviceClass = context.getDmdRoot("Devices").createOrganizer(devicePath)
139 device = deviceClass.createInstance(deviceName)
140 device.setManageIp(manageIp)
141 device.manage_editDevice(
142 tag, serialNumber,
143 zSnmpCommunity, zSnmpPort, zSnmpVer,
144 rackSlot, productionState, comments,
145 hwManufacturer, hwProductName,
146 osManufacturer, osProductName,
147 locationPath, groupPaths, systemPaths,
148 performanceMonitor, priority, zProperties,
149 title)
150 return device
151
155 """
156 Find the SNMP community and version for an ip address using zSnmpCommunities.
157
158 @rtype: tuple of (community, port, version, device name)
159 """
160 from pynetsnmp.SnmpSession import SnmpSession
161
162 devroot = context.getDmdRoot('Devices').createOrganizer(devicePath)
163 communities = []
164 if community: communities.append(community)
165 communities.extend(getattr(devroot, "zSnmpCommunities", []))
166 if not port: port = getattr(devroot, "zSnmpPort", 161)
167 versions = ('v2c', 'v1')
168 if not version: version = getattr(devroot, 'zSnmpVer', None)
169 if version: versions = (version,)
170 timeout = getattr(devroot, "zSnmpTimeout", 2)
171 retries = getattr(devroot, "zSnmpTries", 2)
172 session = SnmpSession(ip, timeout=timeout, port=port, retries=retries)
173 oid = '.1.3.6.1.2.1.1.5.0'
174 goodcommunity = ""
175 goodversion = ""
176 devname = ""
177 for version in versions:
178 session.setVersion(version)
179 for community in communities:
180 session.community = community
181 try:
182 devname = session.get(oid).values()[0]
183 goodcommunity = session.community
184 goodversion = version
185 break
186 except (SystemExit, KeyboardInterrupt, POSError): raise
187 except: pass
188 if goodcommunity:
189 break
190 else:
191 raise NoSnmp("No SNMP found for IP = %s" % ip)
192 return (goodcommunity, port, goodversion, devname)
193
212
213 addDevice = DTMLFile('dtml/addDevice',globals())
217
218 -class Device(ManagedEntity, Commandable, Lockable, MaintenanceWindowable,
219 AdministrativeRoleable, ZenMenuable):
220 """
221 Device is a base class that represents the idea of a single computer system
222 that is made up of software running on hardware. It currently must be IP
223 enabled but maybe this will change.
224 """
225
226 implements(IEventView, IIndexed, IGloballyIdentifiable)
227
228 event_key = portal_type = meta_type = 'Device'
229
230 default_catalog = "deviceSearch"
231
232 relationshipManagerPathRestriction = '/Devices'
233 title = ""
234 manageIp = ""
235 productionState = 1000
236 preMWProductionState = productionState
237 snmpAgent = ""
238 snmpDescr = ""
239 snmpOid = ""
240 snmpContact = ""
241 snmpSysName = ""
242 snmpLocation = ""
243 rackSlot = ""
244 comments = ""
245 sysedgeLicenseMode = ""
246 priority = 3
247
248
249
250 _temp_device = False
251
252 _properties = ManagedEntity._properties + (
253 {'id':'title', 'type':'string', 'mode':'w'},
254 {'id':'manageIp', 'type':'string', 'mode':'w'},
255 {'id':'snmpAgent', 'type':'string', 'mode':'w'},
256 {'id':'snmpDescr', 'type':'string', 'mode':''},
257 {'id':'snmpOid', 'type':'string', 'mode':''},
258 {'id':'snmpContact', 'type':'string', 'mode':''},
259 {'id':'snmpSysName', 'type':'string', 'mode':''},
260 {'id':'snmpLocation', 'type':'string', 'mode':''},
261 {'id':'snmpLastCollection', 'type':'date', 'mode':''},
262 {'id':'snmpAgent', 'type':'string', 'mode':''},
263 {'id':'rackSlot', 'type':'string', 'mode':'w'},
264 {'id':'comments', 'type':'text', 'mode':'w'},
265 {'id':'sysedgeLicenseMode', 'type':'string', 'mode':''},
266 {'id':'priority', 'type':'int', 'mode':'w'},
267 )
268
269 _relations = ManagedEntity._relations + (
270 ("deviceClass", ToOne(ToManyCont, "Products.ZenModel.DeviceClass",
271 "devices")),
272 ("perfServer", ToOne(ToMany, "Products.ZenModel.PerformanceConf",
273 "devices")),
274 ("location", ToOne(ToMany, "Products.ZenModel.Location", "devices")),
275 ("systems", ToMany(ToMany, "Products.ZenModel.System", "devices")),
276 ("groups", ToMany(ToMany, "Products.ZenModel.DeviceGroup", "devices")),
277 ("maintenanceWindows",ToManyCont(ToOne,
278 "Products.ZenModel.MaintenanceWindow", "productionState")),
279 ("adminRoles", ToManyCont(ToOne,"Products.ZenModel.AdministrativeRole",
280 "managedObject")),
281 ('userCommands', ToManyCont(ToOne, 'Products.ZenModel.UserCommand',
282 'commandable')),
283
284 ('monitors', ToMany(ToMany, 'Products.ZenModel.StatusMonitorConf',
285 'devices')),
286 )
287
288
289 factory_type_information = (
290 {
291 'id' : 'Device',
292 'meta_type' : 'Device',
293 'description' : """Base class for all devices""",
294 'icon' : 'Device_icon.gif',
295 'product' : 'ZenModel',
296 'factory' : 'manage_addDevice',
297 'immediate_view' : 'devicedetail',
298 'actions' :
299 (
300 {'id' : 'swdetail'
301 , 'name' : 'Software'
302 , 'action' : 'deviceSoftwareDetail'
303 , 'permissions': (ZEN_VIEW, )
304 },
305 { 'id' : 'events'
306 , 'name' : 'Events'
307 , 'action' : 'viewEvents'
308 , 'permissions' : (ZEN_VIEW, )
309 },
310 { 'id' : 'perfServer'
311 , 'name' : 'Graphs'
312 , 'action' : 'viewDevicePerformance'
313 , 'permissions' : (ZEN_VIEW, )
314 },
315 { 'id' : 'edit'
316 , 'name' : 'Edit'
317 , 'action' : 'editDevice'
318 , 'permissions' : ("Change Device",)
319 },
320 )
321 },
322 )
323
324 security = ClassSecurityInfo()
325
326 - def __init__(self, id, buildRelations=True):
337
339 flag = getattr(self, '_temp_device', None)
340 if flag is None:
341 flag = self._temp_device = False
342 return flag
343
345 """
346 Return the name of this device. Default is titleOrId.
347 """
348 return self.titleOrId()
349
350
351 security.declareProtected(ZEN_MANAGE_DMD, 'changeDeviceClass')
353 """
354 Wrapper for DeviceClass.moveDevices. The primary reason to use this
355 method instead of that one is that this one returns the new path to the
356 device.
357
358 @param deviceClassPath: device class in DMD path
359 @type deviceClassPath: string
360 @param REQUEST: Zope REQUEST object
361 @type REQUEST: Zope REQUEST object
362 """
363 self.deviceClass().moveDevices(deviceClassPath, (self.id,))
364 device = self.getDmdRoot('Devices').findDevice(self.id)
365 if REQUEST:
366 audit('UI.Device.ChangeDeviceClass', self, deviceClass=deviceClassPath)
367 return device.absolute_url_path()
368
370 """
371 DEPRECATED
372 """
373 import warnings
374 warnings.warn('Device.getRRDTemplate is deprecated',
375 DeprecationWarning)
376 return ManagedEntity.getRRDTemplate(self)
377
379 """
380 Returns all the templates bound to this Device
381
382 @rtype: list
383
384 >>> from Products.ZenModel.Device import manage_addDevice
385 >>> manage_addDevice(devices, 'test')
386 >>> devices.test.getRRDTemplates()
387 [<RRDTemplate at /zport/dmd/Devices/rrdTemplates/Device>]
388 """
389 if not hasattr(self, 'zDeviceTemplates'):
390 return ManagedEntity.getRRDTemplates(self)
391 result = []
392 for name in self.zDeviceTemplates:
393 template = self.getRRDTemplateByName(name)
394 if template:
395 result.append(template)
396 return result
397
398
401
402
404 """
405 Returns the available DataSource options. DataSource options
406 are used to populate the dropdown when adding a new DataSource
407 and is a string. See L{RRDTemplate.RRDTemplate.getDataSourceOptions}
408 for more information.
409
410 @rtype: list
411 @return: [(displayName, dsOption),]
412 """
413
414
415
416
417
418 templates = self.getRRDTemplates()
419 if templates:
420 return templates[0].getDataSourceOptions()
421 return []
422
423
425 """
426 Returns the cached sysUpTime for this device
427
428 @rtype: int
429 """
430 try:
431 return self.cacheRRDValue('sysUpTime', -1)
432 except Exception:
433 log.exception("failed getting sysUpTime")
434 return -1
435
436
438 """
439 Returns the uptime of this device
440
441 @rtype: string
442 @todo: Performance enhancement: Should move import outside of method
443 """
444 from Products.ZenEvents import Availability
445 results = Availability.query(self.dmd, device=self.id, *args, **kw)
446 if results:
447 return results[0]
448 else:
449 return None
450
451
452
454 """
455 Override from object to handle lastPollSnmpUpTime and
456 snmpLastCollection
457
458 @todo: Not sure this is needed, see getLastPollSnmpUpTime and
459 getSnmpLastCollection
460 """
461 if name == 'lastPollSnmpUpTime':
462 return self._lastPollSnmpUpTime.getStatus()
463 elif name == 'snmpLastCollection':
464 return DateTime(self._snmpLastCollection)
465 else:
466 raise AttributeError( name )
467
468
470 """
471 Override from PropertyManager to handle checks and ip creation
472
473 @todo: Not sure this is needed, see setSnmpLastCollection
474 """
475 self._wrapperCheck(value)
476 if id == 'snmpLastCollection':
477 self._snmpLastCollection = float(value)
478 else:
479 ManagedEntity._setPropValue(self, id, value)
480
481
482 - def applyDataMap(self, datamap, relname="", compname="", modname=""):
489
490
492 """
493 Return a sequence of path tuples suitable for indexing by
494 a MultiPathIndex.
495 """
496 orgs = (
497 self.systems() +
498 self.groups() +
499 [self.location()] +
500 [self.deviceClass()]
501 )
502 return [ aq_base(self).__of__(o.primaryAq()).getPhysicalPath() \
503 for o in orgs if o is not None ]
504
505
507 """
508 Trace the route to target using our routing table.
509 Wrapper method of OperatingSystem.traceRoute
510
511 @param target: Device name
512 @type target: string
513 @param ippath: IP addesses
514 @type ippath: list
515 @return: IP Addresses
516 @rtype: list
517 """
518 if ippath is None: ippath=[]
519 if isinstance(target, basestring):
520 target = self.findDevice(target)
521 if not target: raise ValueError("Target %s not found in DMD" % target)
522 return self.os.traceRoute(target, ippath)
523
524
526 """
527 Return list of monitored DeviceComponents on this device.
528 Wrapper method for getDeviceComponents
529 """
530 return self.getDeviceComponents(monitored=True,
531 collector=collector, type=type)
532
533
534 security.declareProtected(ZEN_VIEW, 'getReportableComponents')
536 """
537 Return a list of DeviceComponents on this device that should be
538 considered for reporting.
539
540 @type collector: string
541 @type type: string
542 @permission: ZEN_VIEW
543 @rtype: list
544 """
545 return self.getMonitoredComponents(collector=collector, type=type);
546
548 from Products.ZCatalog.ZCatalog import manage_addZCatalog
549 manage_addZCatalog(self, "componentSearch", "componentSearch")
550 zcat = self._getOb("componentSearch")
551 cat = zcat._catalog
552 cat.addIndex('meta_type', makeCaseInsensitiveFieldIndex('meta_type'))
553 cat.addIndex('getCollectors',
554 makeCaseInsensitiveKeywordIndex('getCollectors'))
555
556 zcat.addIndex('monitored', FieldIndex('monitored'))
557 zcat.addColumn('meta_type')
558 zcat.addColumn('getUUID')
559 for c in self.getDeviceComponentsNoIndexGen():
560 c.index_object()
561
562 security.declareProtected(ZEN_VIEW, 'getDeviceComponents')
564 """
565 Return list of all DeviceComponents on this device.
566
567 @type monitored: boolean
568 @type collector: string
569 @type type: string
570 @permission: ZEN_VIEW
571 @rtype: list
572 """
573
574
575 if getattr(aq_base(self), 'componentSearch', None) is None:
576 self._create_componentSearch()
577
578 query = {}
579 if collector is not None:
580 query['getCollectors'] = collector
581 if monitored is not None:
582 query['monitored'] = monitored
583 if type is not None:
584 query['meta_type'] = type
585
586 return list(getObjectsFromCatalog(self.componentSearch, query, log))
587
588
590 """
591 Return a list of all device components by walking relations. This is
592 much slower then the normal getDeviceComponents method which uses the
593 component index. It is used when rebuilding the device indexes.
594 """
595 from DeviceComponent import DeviceComponent
596 for baseObject in (self, self.os, self.hw):
597 for rel in baseObject.getRelationships():
598 if rel.meta_type != "ToManyContRelationship": continue
599 for obj in rel():
600 if not isinstance(obj, DeviceComponent): break
601 for subComp in obj.getSubComponentsNoIndexGen():
602 yield subComp
603 yield obj
604
605
614
615
617 """
618 DEPRECATED - Return the hardware manufacturer name of this device.
619
620 @rtype: string
621 @todo: Remove this method and remove the call from testDevice.py
622 """
623 return self.hw.getManufacturerName()
624
625
627 """
628 Return the hardware product name of this device.
629
630 @rtype: string
631 """
632 return self.hw.getProductName()
633
635 """
636 Return the hardware product class of this device.
637
638 @rtype: string
639 """
640 cls = self.hw.productClass()
641 if cls:
642 return cls.titleOrId()
643
645 """
646 DEPRECATED - Return the productKey of the device hardware.
647
648 @rtype: string
649 @todo: Remove this method and remove the call from testDevice.py
650 """
651 return self.hw.getProductKey()
652
653
655 """
656 DEPRECATED - Return the OS manufacturer name of this device.
657
658 @rtype: string
659 @todo: Remove this method and remove the call from testDevice.py
660 """
661 return self.os.getManufacturerName()
662
663
665 """
666 DEPRECATED - Return the OS product name of this device.
667
668 @rtype: string
669 @todo: Remove this method and remove the call from testDevice.py
670 """
671 return self.os.getProductName()
672
673
675 """
676 DEPRECATED - Return the productKey of the device OS.
677
678 @rtype: string
679 @todo: Remove this method and remove the call from testDevice.py
680 """
681 return self.os.getProductKey()
682
683
685 """
686 Set the productKey of the device OS.
687 """
688 self.os.setProductKey(prodKey, manufacturer)
689
691 """
692 DEPRECATED - Return the tag of the device HW.
693
694 @rtype: string
695 @todo: remove this method and remove the call from testDevice.py
696 """
697 return self.hw.tag
698
699
701 """
702 Set the asset tag of the device hardware.
703 """
704 self.hw.tag = assettag
705
707 """
708 Set the productKey of the device hardware.
709 """
710 self.hw.setProductKey(prodKey, manufacturer)
711
713 """
714 Set the hardware serial number.
715 """
716 self.hw.serialNumber = number
717
719 """
720 DEPRECATED - Return the hardware serial number.
721
722 @rtype: string
723 @todo: Remove this method and remove the call from testDevice.py
724 """
725 return self.hw.serialNumber
726
727
729 """
730 Return the ips that our indirect routs point to which aren't currently
731 connected to devices.
732
733 @todo: Can be moved to zendisc.py
734 """
735 ips = []
736 for r in self.os.routes():
737 ipobj = r.nexthop()
738
739 if ipobj: ips.append(ipobj.id)
740 return ips
741
742
743 security.declareProtected(ZEN_VIEW, 'getLocationName')
745 """
746 Return the location name. i.e. "Rack" from /Locations/Loc/SubLoc/Rack
747
748 @rtype: string
749 @permission: ZEN_VIEW
750 """
751 loc = self.location()
752 if loc: return loc.getOrganizerName()
753 return ""
754
755 security.declareProtected(ZEN_VIEW, 'getLocationLink')
771
772
773 security.declareProtected(ZEN_VIEW, 'getSystemNames')
775 """
776 Return the system names for this device
777
778 @rtype: list
779 @permission: ZEN_VIEW
780 """
781 return map(lambda x: x.getOrganizerName(), self.systems())
782
783
784 security.declareProtected(ZEN_VIEW, 'getSystemNamesString')
786 """
787 Return the system names for this device as a string
788
789 @rtype: string
790 @permission: ZEN_VIEW
791 """
792 return sep.join(self.getSystemNames())
793
794
795 security.declareProtected(ZEN_VIEW, 'getDeviceGroupNames')
797 """
798 Return the device group names for this device
799
800 @rtype: list
801 @permission: ZEN_VIEW
802 """
803 return map(lambda x: x.getOrganizerName(), self.groups())
804
805
806 security.declareProtected(ZEN_VIEW, 'getPerformanceServer')
815
816
817 security.declareProtected(ZEN_VIEW, 'getPerformanceServerName')
828
829
834
835 security.declareProtected(ZEN_VIEW, 'getLastChange')
837 """
838 Return DateTime of last change detected on this device.
839
840 @rtype: DateTime
841 @permission: ZEN_VIEW
842 """
843 return DateTime(float(self._lastChange))
844
845
846 security.declareProtected(ZEN_VIEW, 'getLastChangeString')
848 """
849 Return date string of last change detected on this device.
850
851 @rtype: string
852 @permission: ZEN_VIEW
853 """
854 return Time.LocalDateTimeSecsResolution(float(self._lastChange))
855
856
857 security.declareProtected(ZEN_VIEW, 'getSnmpLastCollection')
859 """
860 Return DateTime of last SNMP collection on this device.
861
862 @rtype: DateTime
863 @permission: ZEN_VIEW
864 """
865 return DateTime(float(self._snmpLastCollection))
866
867
868 security.declareProtected(ZEN_VIEW, 'getSnmpLastCollectionString')
870 """
871 Return date string of last SNMP collection on this device.
872
873 @rtype: string
874 @permission: ZEN_VIEW
875 """
876 if self._snmpLastCollection:
877 return Time.LocalDateTimeSecsResolution(float(self._snmpLastCollection))
878 return "Not Modeled"
879
880
905
907 ipMatch = self.getNetworkRoot().findIp(ip)
908 if ipMatch:
909 dev = ipMatch.device()
910 if dev and self.id != dev.id:
911 return True
912 return False
913
914 security.declareProtected(ZEN_ADMIN_DEVICE, 'setManageIp')
916 """
917 Set the manage IP, if IP is not passed perform DNS lookup.
918 If there is an error with the IP address format, the IP address
919 will be reset to the result of a DNS lookup.
920
921 @rtype: string
922 @permission: ZEN_ADMIN_DEVICE
923 """
924 message = ''
925 ip = ip.replace(' ', '')
926 origip = ip
927 ip = self._sanitizeIPaddress(ip)
928
929 if not ip:
930 try:
931 ip = getHostByName(origip)
932 if ip == '0.0.0.0':
933
934 ip = ''
935 except socket.error:
936 ip = ''
937
938 if not ip:
939 try:
940 ip = getHostByName(ipunwrap(self.id))
941 except socket.error:
942 ip = ''
943 if origip:
944 message = ("%s is an invalid IP address, "
945 "and no appropriate IP could"
946 " be found via DNS for %s") % (origip, self.id)
947 log.warn(message)
948 else:
949 message = "DNS lookup of '%s' failed to return an IP" % \
950 self.id
951
952 if ip:
953 if self._isDuplicateIp(ip):
954 message = "The IP address %s is already assigned" % ip
955 log.warn(message)
956
957 else:
958 self.manageIp = ip
959 self.index_object(idxs=('getDeviceIp',), noips=True)
960 notify(IndexingEvent(self, ('ipAddress',), True))
961 log.info("%s's IP address has been set to %s.",
962 self.id, ip)
963 if REQUEST:
964 audit('UI.Device.ResetIP', self, ip=ip)
965
966 return message
967
968
969 security.declareProtected(ZEN_VIEW, 'getManageIp')
971 """
972 Return the management ip for this device.
973
974 @rtype: string
975 @permission: ZEN_VIEW
976 """
977 return self.manageIp
978
979
981 """
982 DEPRECATED - Return the management ipobject for this device.
983
984 @rtype: IpAddress
985 @todo: This method may not be called anywhere, remove it.
986 """
987 if self.manageIp:
988 return self.Networks.findIp(self.manageIp)
989
990
991 security.declareProtected(ZEN_VIEW, 'getManageInterface')
993 """
994 Return the management interface of a device based on its manageIp.
995
996 @rtype: IpInterface
997 @permission: ZEN_VIEW
998 """
999 ipobj = self.Networks.findIp(self.manageIp)
1000 if ipobj: return ipobj.interface()
1001
1002
1003 security.declareProtected(ZEN_VIEW, 'uptimeStr')
1005 """
1006 Return the SNMP uptime
1007
1008 @rtype: string
1009 @permission: ZEN_VIEW
1010 """
1011 ut = self.sysUpTime()
1012
1013 if ut < 0 or ut != ut:
1014 return "Unknown"
1015 elif ut == 0:
1016 return "0d:0h:0m:0s"
1017 ut = float(ut)/100.
1018 days = int(ut/86400)
1019 hour = int((ut%86400)/3600)
1020 mins = int((ut%3600)/60)
1021 secs = int(ut%60)
1022 return "%02dd:%02dh:%02dm:%02ds" % (
1023 days, hour, mins, secs)
1024
1025
1027 """
1028 Build a list of all device paths that have the python class pyclass
1029
1030 @rtype: list
1031 """
1032 dclass = self.getDmdRoot("Devices")
1033 return dclass.getPeerDeviceClassNames(self.__class__)
1034
1035
1036
1037
1038
1039
1040 security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_snmpCommunity')
1042 """
1043 Reset the snmp community using the zSnmpCommunities variable.
1044
1045 @permission: ZEN_CHANGE_DEVICE
1046 """
1047 try:
1048 zSnmpCommunity, zSnmpPort, zSnmpVer, snmpname = \
1049 findCommunity(self, self.manageIp, self.getDeviceClassPath(),
1050 port=self.zSnmpPort, version=self.zSnmpVer)
1051 except NoSnmp:
1052 pass
1053 else:
1054 if self.zSnmpCommunity != zSnmpCommunity:
1055 self.setZenProperty("zSnmpCommunity", zSnmpCommunity)
1056 if self.zSnmpPort != zSnmpPort:
1057 self.setZenProperty("zSnmpPort", zSnmpPort)
1058 if self.zSnmpVer != zSnmpVer:
1059 self.setZenProperty("zSnmpVer", zSnmpVer)
1060
1061 - def setProductInfo(self, hwManufacturer="", hwProductName="",
1062 osManufacturer="", osProductName=""):
1063 if hwManufacturer and hwProductName:
1064
1065
1066 if hwManufacturer != "_no_change" and hwProductName != "_no_change":
1067 log.info("setting hardware manufacturer to %r productName to %r"
1068 % (hwManufacturer, hwProductName))
1069 self.hw.setProduct(hwProductName, hwManufacturer)
1070 else:
1071 self.hw.productClass.removeRelation()
1072
1073 if osManufacturer and osProductName:
1074
1075
1076 if osManufacturer != "_no_change" and osProductName != "_no_change":
1077 log.info("setting os manufacturer to %r productName to %r"
1078 % (osManufacturer, osProductName))
1079 self.os.setProduct(osProductName, osManufacturer, isOS=True)
1080 else:
1081 self.os.productClass.removeRelation()
1082
1083
1084 security.declareProtected(ZEN_CHANGE_DEVICE, 'updateDevice')
1086 """
1087 Update the device relation and attributes, if passed. If any parameter
1088 is not passed it will not be updated; the value of any unpassed device
1089 propeties will remain the same.
1090
1091 @permission: ZEN_CHANGE_DEVICE
1092 Keyword arguments:
1093 title -- device title [string]
1094 tag -- tag number [string]
1095 serialNumber -- serial number [string]
1096 zProperties -- dict of zProperties [dict]
1097 zSnmpCommunity -- snmp community (overrides corresponding value is zProperties) [string]
1098 zSnmpPort -- snmp port (overrides corresponding value in zProperties) [string]
1099 zSnmpVer -- snmp version (overrides corresponding value in zProperties) [string]
1100 rackSlot -- rack slot number [integer]
1101 productionState -- production state of device [integer]
1102 priority -- device priority [integer]
1103 comment -- device comment [string]
1104 hwManufacturer -- hardware manufacturer [string]
1105 hwProductName -- hardware product name [string]
1106 osManufacturer -- operating system manufacturer [string]
1107 osProductName -- operating system name [string]
1108 locationPath -- location [string]
1109 groupPaths -- group paths [list]
1110 systemPaths -- systen paths [list]
1111 performanceMonitor -- collector name [string]
1112
1113 """
1114 if 'title' in kwargs and kwargs['title'] is not None and str(kwargs['title']).strip():
1115 log.info("setting title to %r" % kwargs['title'])
1116 self.title = kwargs['title']
1117 if 'tag' in kwargs and kwargs['tag'] is not None:
1118 log.info("setting tag to %r" % kwargs['tag'])
1119 self.hw.tag = kwargs['tag']
1120 if 'serialNumber' in kwargs and kwargs['serialNumber'] is not None:
1121 log.info("setting serialNumber to %r" % kwargs['serialNumber'])
1122 self.hw.serialNumber = kwargs['serialNumber']
1123
1124
1125 if 'zProperties' in kwargs and kwargs['zProperties'] is not None:
1126 zProperties = kwargs['zProperties']
1127 else:
1128 zProperties = {}
1129
1130
1131 zpropUpdate = dict((name, kwargs[name]) for name in ('zSnmpCommunity', 'zSnmpPort', 'zSnmpVer')
1132 if name in kwargs)
1133 zProperties.update(zpropUpdate)
1134
1135
1136 for prop, value in zProperties.items():
1137 if value:
1138
1139
1140 self.setZenProperty(prop, value)
1141
1142 if 'rackSlot' in kwargs:
1143 log.info("setting rackSlot to %r" % kwargs["rackSlot"])
1144 self.rackSlot = kwargs["rackSlot"]
1145
1146 if 'productionState' in kwargs:
1147 log.info("setting productionState to %r" % kwargs["productionState"])
1148 self.setProdState(kwargs["productionState"])
1149
1150 if 'priority' in kwargs:
1151 log.info("setting priority to %r" % kwargs["priority"])
1152 self.setPriority(kwargs["priority"])
1153
1154 if 'comments' in kwargs:
1155 log.info("setting comments to %r" % kwargs["comments"])
1156 self.comments = kwargs["comments"]
1157
1158 self.setProductInfo(hwManufacturer=kwargs.get("hwManufacturer","_no_change"),
1159 hwProductName=kwargs.get("hwProductName","_no_change"),
1160 osManufacturer=kwargs.get("osManufacturer","_no_change"),
1161 osProductName=kwargs.get("osProductName","_no_change"))
1162
1163 if kwargs.get("locationPath", False):
1164 log.info("setting location to %r" % kwargs["locationPath"])
1165 self.setLocation(kwargs["locationPath"])
1166
1167 if kwargs.get("groupPaths",False):
1168 log.info("setting group %r" % kwargs["groupPaths"])
1169 self.setGroups(kwargs["groupPaths"])
1170
1171 if kwargs.get("systemPaths",False):
1172 log.info("setting system %r" % kwargs["systemPaths"])
1173 self.setSystems(kwargs["systemPaths"])
1174
1175 if 'performanceMonitor' in kwargs and \
1176 kwargs["performanceMonitor"] != self.getPerformanceServerName():
1177 log.info("setting performance monitor to %r" \
1178 % kwargs["performanceMonitor"])
1179 self.setPerformanceMonitor(kwargs["performanceMonitor"])
1180
1181 self.setLastChange()
1182 self.index_object()
1183 notify(IndexingEvent(self))
1184
1185 security.declareProtected(ZEN_CHANGE_DEVICE, 'manage_editDevice')
1186 - def manage_editDevice(self,
1187 tag="", serialNumber="",
1188 zSnmpCommunity="", zSnmpPort=161, zSnmpVer="",
1189 rackSlot="", productionState=1000, comments="",
1190 hwManufacturer="", hwProductName="",
1191 osManufacturer="", osProductName="",
1192 locationPath="", groupPaths=[], systemPaths=[],
1193 performanceMonitor="localhost", priority=3,
1194 zProperties=None, title=None, REQUEST=None):
1195 """
1196 Edit the device relation and attributes. This method will update device
1197 properties because of the default values that are passed. Calling this
1198 method using a **kwargs dict will result in default values being set for
1199 many device properties. To update only a subset of these properties use
1200 updateDevice(**kwargs).
1201
1202 @param locationPath: path to a Location
1203 @type locationPath: string
1204 @param groupPaths: paths to DeviceGroups
1205 @type groupPaths: list
1206 @param systemPaths: paths to Systems
1207 @type systemPaths: list
1208 @param performanceMonitor: name of PerformanceMonitor
1209 @type performanceMonitor: string
1210 @permission: ZEN_CHANGE_DEVICE
1211 """
1212 self.updateDevice(
1213 tag=tag, serialNumber=serialNumber,
1214 zSnmpCommunity=zSnmpCommunity, zSnmpPort=zSnmpPort, zSnmpVer=zSnmpVer,
1215 rackSlot=rackSlot, productionState=productionState, comments=comments,
1216 hwManufacturer=hwManufacturer, hwProductName=hwProductName,
1217 osManufacturer=osManufacturer, osProductName=osProductName,
1218 locationPath=locationPath, groupPaths=groupPaths, systemPaths=systemPaths,
1219 performanceMonitor=performanceMonitor, priority=priority,
1220 zProperties=zProperties, title=title, REQUEST=REQUEST)
1221 if REQUEST:
1222 from Products.ZenUtils.Time import SaveMessage
1223 IMessageSender(self).sendToBrowser("Saved", SaveMessage())
1224
1225
1226
1227 audit('UI.Device.Edit', self)
1228 return self.callZenScreen(REQUEST)
1229
1230
1232 """
1233 Changes the title to newTitle and reindexes the object
1234 """
1235 super(Device, self).setTitle(newTitle)
1236 self.index_object()
1237 notify(IndexingEvent(self, ('name',), True))
1238
1240 """
1241 Returns true if the device production state >= zProdStateThreshold.
1242
1243 @rtype: boolean
1244 """
1245 return self.productionState >= self.zProdStateThreshold
1246
1247
1249 """
1250 Returns true if the device is subject to SNMP monitoring
1251
1252 @rtype: boolean
1253 """
1254 return (self.monitorDevice()
1255 and self.getManageIp()
1256 and not self.zSnmpMonitorIgnore)
1257
1258
1260 """
1261 Return the numeric device priority.
1262
1263 @rtype: int
1264 """
1265 return self.priority
1266
1267
1269 """
1270 Return the device priority as a string.
1271
1272 @rtype: string
1273 """
1274 return str(self.convertPriority(self.priority))
1275
1286
1297
1298 security.declareProtected(ZEN_CHANGE_DEVICE_PRODSTATE, 'setProdState')
1299 - def setProdState(self, state, maintWindowChange=False, REQUEST=None):
1300 """
1301 Set the device's production state.
1302
1303 @parameter state: new production state
1304 @type state: int
1305 @parameter maintWindowChange: are we resetting state from inside a MW?
1306 @type maintWindowChange: boolean
1307 @permission: ZEN_CHANGE_DEVICE
1308 """
1309
1310 ret = super(Device, self).setProdState(state, maintWindowChange, REQUEST)
1311 for component in self.getDeviceComponents():
1312 if isinstance(component, ManagedEntity) and self.productionState == component.productionState:
1313 notify(IndexingEvent(component.primaryAq(), ('productionState',), True))
1314 if REQUEST:
1315 audit('UI.Device.Edit', self, productionState=state,
1316 maintenanceWindowChange=maintWindowChange)
1317 return ret
1318
1319 security.declareProtected(ZEN_CHANGE_DEVICE, 'setPriority')
1336
1337 security.declareProtected(ZEN_CHANGE_DEVICE, 'setLastChange')
1339 """
1340 Set the changed datetime for this device.
1341
1342 @param value: secs since the epoch, default is now
1343 @type value: float
1344 @permission: ZEN_CHANGE_DEVICE
1345 """
1346 if value is None:
1347 value = time.time()
1348 self._lastChange = float(value)
1349
1350 security.declareProtected(ZEN_CHANGE_DEVICE, 'setSnmpLastCollection')
1352 """
1353 Set the last time snmp collection occurred.
1354
1355 @param value: secs since the epoch, default is now
1356 @type value: float
1357 @permission: ZEN_CHANGE_DEVICE
1358 """
1359 if value is None:
1360 value = time.time()
1361 self._snmpLastCollection = float(value)
1362
1363
1364 security.declareProtected(ZEN_CHANGE_DEVICE, 'addManufacturer')
1365 - def addManufacturer(self, newHWManufacturerName=None,
1366 newSWManufacturerName=None, REQUEST=None):
1367 """
1368 DEPRECATED -
1369 Add either a hardware or software manufacturer to the database.
1370
1371 @permission: ZEN_CHANGE_DEVICE
1372 @todo: Doesn't really do work on a device object.
1373 Already exists on ZDeviceLoader
1374 """
1375 mname = newHWManufacturerName
1376 field = 'hwManufacturer'
1377 if not mname:
1378 mname = newSWManufacturerName
1379 field = 'osManufacturer'
1380 self.getDmdRoot("Manufacturers").createManufacturer(mname)
1381 if REQUEST:
1382 REQUEST[field] = mname
1383 messaging.IMessageSender(self).sendToBrowser(
1384 'Manufacturer Added',
1385 'The %s manufacturer has been created.' % mname
1386 )
1387 audit('UI.Device.AddManufacturer', self, manufacturer=mname)
1388 return self.callZenScreen(REQUEST)
1389
1390
1391 security.declareProtected(ZEN_CHANGE_DEVICE, 'setHWProduct')
1392 - def setHWProduct(self, newHWProductName=None, hwManufacturer=None,
1393 REQUEST=None):
1394 """
1395 DEPRECATED -
1396 Adds a new hardware product
1397
1398 @permission: ZEN_CHANGE_DEVICE
1399 @todo: Doesn't really do work on a device object.
1400 Already exists on ZDeviceLoader
1401 """
1402 added = False
1403 if newHWProductName and hwManufacturer:
1404 self.getDmdRoot("Manufacturers").createHardwareProduct(
1405 newHWProductName, hwManufacturer)
1406 added = True
1407 if REQUEST:
1408 if added:
1409 messaging.IMessageSender(self).sendToBrowser(
1410 'Product Set',
1411 'Hardware product has been set to %s.' % newHWProductName
1412 )
1413 REQUEST['hwProductName'] = newHWProductName
1414 audit('UI.Device.SetHWProduct', self, manufacturer=hwManufacturer,
1415 product=newHWProductName)
1416 else:
1417 messaging.IMessageSender(self).sendToBrowser(
1418 'Set Product Failed',
1419 'Hardware product could not be set to %s.'%newHWProductName,
1420 priority=messaging.WARNING
1421 )
1422 return self.callZenScreen(REQUEST)
1423
1424
1425 security.declareProtected(ZEN_CHANGE_DEVICE, 'setOSProduct')
1426 - def setOSProduct(self, newOSProductName=None, osManufacturer=None, REQUEST=None):
1427 """
1428 DEPRECATED
1429 Adds a new os product
1430
1431 @permission: ZEN_CHANGE_DEVICE
1432 @todo: Doesn't really do work on a device object.
1433 Already exists on ZDeviceLoader
1434 """
1435 if newOSProductName:
1436 self.getDmdRoot("Manufacturers").createSoftwareProduct(
1437 newOSProductName, osManufacturer, isOS=True)
1438 if REQUEST:
1439 if newOSProductName:
1440 messaging.IMessageSender(self).sendToBrowser(
1441 'Product Set',
1442 'OS product has been set to %s.' % newOSProductName
1443 )
1444 REQUEST['osProductName'] = newOSProductName
1445 audit('UI.Device.SetOSProduct', self, manufacturer=osManufacturer,
1446 product=newOSProductName)
1447 else:
1448 messaging.IMessageSender(self).sendToBrowser(
1449 'Set Product Failed',
1450 'OS product could not be set to %s.' % newOSProductName,
1451 priority=messaging.WARNING
1452 )
1453 return self.callZenScreen(REQUEST)
1454
1455
1456 security.declareProtected(ZEN_CHANGE_DEVICE, 'setLocation')
1458 """
1459 Set the location of a device. If the location is new it will be created.
1460
1461 @permission: ZEN_CHANGE_DEVICE
1462 """
1463 if not locationPath:
1464 self.location.removeRelation()
1465 else:
1466 locobj = self.getDmdRoot("Locations").createOrganizer(locationPath)
1467 self.addRelation("location", locobj)
1468 self.setAdminLocalRoles()
1469 self.index_object()
1470 notify(IndexingEvent(self, 'path', False))
1471 if REQUEST:
1472 action = 'SetLocation' if locationPath else 'RemoveFromLocation'
1473 audit(['UI.Device', action], self, location=locationPath)
1474
1475
1476 - def addLocation(self, newLocationPath, REQUEST=None):
1477 """
1478 DEPRECATED
1479 Add a new location and relate it to this device
1480
1481 @todo: Doesn't really do work on a device object.
1482 Already exists on ZDeviceLoader
1483 """
1484 self.getDmdRoot("Locations").createOrganizer(newLocationPath)
1485 if REQUEST:
1486 REQUEST['locationPath'] = newLocationPath
1487 messaging.IMessageSender(self).sendToBrowser(
1488 'Location Added',
1489 'Location %s has been created.' % newLocationPath
1490 )
1491 audit('UI.Device.SetLocation', self, location=newLocationPath)
1492 return self.callZenScreen(REQUEST)
1493
1494
1495 security.declareProtected(ZEN_CHANGE_DEVICE, 'setPerformanceMonitor')
1524
1525
1526 security.declareProtected(ZEN_CHANGE_DEVICE, 'setGroups')
1528 """
1529 Set the list of groups for this device based on a list of paths
1530
1531 @permission: ZEN_CHANGE_DEVICE
1532 """
1533 objGetter = self.getDmdRoot("Groups").createOrganizer
1534 self._setRelations("groups", objGetter, groupPaths)
1535 self.index_object()
1536 notify(IndexingEvent(self, 'path', False))
1537
1538
1539 security.declareProtected(ZEN_CHANGE_DEVICE, 'addDeviceGroup')
1541 """
1542 DEPRECATED?
1543 Add a device group to the database and this device
1544
1545 @permission: ZEN_CHANGE_DEVICE
1546 @todo: Already exists on ZDeviceLoader
1547 """
1548 group = self.getDmdRoot("Groups").createOrganizer(newDeviceGroupPath)
1549 self.addRelation("groups", group)
1550 if REQUEST:
1551 messaging.IMessageSender(self).sendToBrowser(
1552 'Group Added',
1553 'Group %s has been created.' % newDeviceGroupPath
1554 )
1555 audit('UI.Device.AddToGroup', self, group=newDeviceGroupPath)
1556 return self.callZenScreen(REQUEST)
1557
1558
1559 security.declareProtected(ZEN_CHANGE_DEVICE, 'setSystems')
1561 """
1562 Set a list of systems to this device using their system paths
1563
1564 @permission: ZEN_CHANGE_DEVICE
1565 """
1566 objGetter = self.getDmdRoot("Systems").createOrganizer
1567 self._setRelations("systems", objGetter, systemPaths)
1568 self.index_object()
1569 notify(IndexingEvent(self, 'path', False))
1570
1571
1572 security.declareProtected(ZEN_CHANGE_DEVICE, 'addSystem')
1573 - def addSystem(self, newSystemPath, REQUEST=None):
1574 """
1575 DEPRECATED?
1576 Add a systems to this device using its system path
1577
1578 @permission: ZEN_CHANGE_DEVICE
1579 @todo: Already exists on ZDeviceLoader
1580 """
1581 sys = self.getDmdRoot("Systems").createOrganizer(newSystemPath)
1582 self.addRelation("systems", sys)
1583 if REQUEST:
1584 messaging.IMessageSender(self).sendToBrowser(
1585 'System Added',
1586 'System %s has been created.' % newSystemPath
1587 )
1588 audit('UI.Device.AddToSystem', self, system=newSystemPath)
1589 return self.callZenScreen(REQUEST)
1590
1591
1592 security.declareProtected(ZEN_CHANGE_DEVICE, 'setTerminalServer')
1594 """
1595 Set the terminal server of this device
1596
1597 @param termservername: device name of terminal server
1598 @permission: ZEN_CHANGE_DEVICE
1599 """
1600 termserver = self.findDevice(termservername)
1601 if termserver:
1602 self.addRelation('termserver', termserver)
1603
1604
1606 """
1607 Set related objects to this device
1608
1609 @param relName: name of the relation to set
1610 @param objGetter: method to get the relation
1611 @param relPaths: list of relationship paths
1612 """
1613 if not isinstance(relPaths, (list, tuple)):
1614 relPaths = [relPaths,]
1615 relPaths = filter(lambda x: x.strip(), relPaths)
1616 rel = getattr(self, relName, None)
1617 if not rel:
1618 raise AttributeError( "Relation %s not found" % relName)
1619 curRelIds = {}
1620 for value in rel.objectValuesAll():
1621 curRelIds[value.getOrganizerName()] = value
1622 for path in relPaths:
1623 if not path in curRelIds:
1624 robj = objGetter(path)
1625 self.addRelation(relName, robj)
1626 else:
1627 del curRelIds[path]
1628 for obj in curRelIds.values():
1629 self.removeRelation(relName, obj)
1630 self.setAdminLocalRoles()
1631
1633 """
1634 @rtype list
1635 @return a list of the html links supplied by implementers
1636 of the IExpandedLinkProvider subscriber interface
1637 """
1638 providers = subscribers( [self], IExpandedLinkProvider )
1639 expandedLinkList = []
1640 for provider in providers:
1641 expandedLinkList.extend( provider.getExpandedLinks() )
1642 return expandedLinkList
1643
1645 """
1646 Return the expanded zComment property
1647
1648 @rtype: HTML output
1649 """
1650 from Products.ZenUtils.ZenTales import talesEval
1651 try:
1652 linksHtml = talesEval('string:' + self.zLinks, self)
1653 otherLinks = self._getOtherExpandedLinks()
1654 if otherLinks:
1655 linksHtml += '<br/>'.join(otherLinks)
1656 return linksHtml
1657 except Exception, ex:
1658 import cgi
1659 return "<i class='errortitle'>%s</i>" % cgi.escape(str(ex))
1660
1661
1662
1663
1664
1665 security.declareProtected(ZEN_VIEW, 'device')
1667 """
1668 Support DeviceResultInt mixin class. Returns itself
1669
1670 @permission: ZEN_VIEW
1671 """
1672 return self
1673
1674
1675
1676
1677
1678
1679
1681 """
1682 Returns true if the device has more SNMP failures
1683 than maxFailures on its status mon.
1684
1685 @rtype: boolean
1686 """
1687 statusmon = self.monitors()
1688 if len(statusmon) > 0:
1689 statusmon = statusmon[0]
1690 return statusmon.maxFailures < self.getSnmpStatusNumber()
1691 return False
1692
1693
1694
1695 security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
1696 'getLastPollSnmpUpTime')
1698 """
1699 Get the value of the snmpUpTime status object
1700
1701 @permission: ZEN_MANAGE_DEVICE_STATUS
1702 """
1703 return self._lastPollSnmpUpTime.getStatus()
1704
1705
1706
1707 security.declareProtected(ZEN_MANAGE_DEVICE_STATUS,
1708 'setLastPollSnmpUpTime')
1710 """
1711 Set the value of the snmpUpTime status object
1712
1713 @permission: ZEN_MANAGE_DEVICE_STATUS
1714 """
1715 self._lastPollSnmpUpTime.setStatus(value)
1716
1717
1718 - def snmpAgeCheck(self, hours):
1719 """
1720 Returns True if SNMP data was collected more than 24 hours ago
1721 """
1722 lastcoll = self.getSnmpLastCollection()
1723 hours = hours/24.0
1724 if DateTime() > lastcoll + hours: return 1
1725
1726
1728 """
1729 Apply zProperties inherited from Product Contexts.
1730 """
1731 self._applyProdContext(self.hw.getProductContext())
1732 self._applyProdContext(self.os.getProductContext())
1733 for soft in self.os.software():
1734 self._applyProdContext(soft.getProductContext())
1735
1736
1737 - def _applyProdContext(self, context):
1738 """
1739 Apply zProperties taken for the product context passed in.
1740
1741 @param context: list of tuples returned from
1742 getProductContext on a MEProduct.
1743 """
1744 for name, value in context:
1745 if name == "zDeviceClass" and value:
1746 log.info("move device to %s", value)
1747 self.moveDevices(value, self.id)
1748 elif name == "zDeviceGroup" and value:
1749 log.info("add device to group %s", value)
1750 self.addDeviceGroup(value)
1751 elif name == "zSystem" and value:
1752 log.info("add device to system %s", value)
1753 self.addSystem(value)
1754
1755
1756
1757
1758
1759
1760
1761 security.declareProtected(ZEN_MANAGE_DEVICE, 'collectDevice')
1762 - def collectDevice(self, setlog=True, REQUEST=None, generateEvents=False,
1763 background=False, write=None):
1764 """
1765 Collect the configuration of this device AKA Model Device
1766
1767 @param setlog: If true, set up the output log of this process
1768 @permission: ZEN_MANAGE_DEVICE
1769 @todo: generateEvents param is not being used.
1770 """
1771 unused(generateEvents)
1772 xmlrpc = isXmlRpc(REQUEST)
1773 perfConf = self.getPerformanceServer()
1774 if perfConf is None:
1775 msg = "Device %s in unknown state -- remove and remodel" % self.titleOrId()
1776 if write is not None:
1777 write(msg)
1778 log.error("Unable to get collector info: %s", msg)
1779 if xmlrpc: return 1
1780 return
1781
1782 perfConf.collectDevice(self, setlog, REQUEST, generateEvents,
1783 background, write)
1784
1785 if REQUEST:
1786 audit('UI.Device.Remodel', self)
1787 if xmlrpc: return 0
1788
1789
1790 security.declareProtected(ZEN_DELETE_DEVICE, 'deleteDevice')
1791 - def deleteDevice(self, deleteStatus=False, deleteHistory=False,
1792 deletePerf=False, REQUEST=None):
1793 """
1794 Delete device from the database
1795
1796 NB: deleteHistory is disabled for the 2.2 release. In some
1797 circumstances it was causing many subprocesses to be spawned
1798 and creating a gridlock situation.
1799
1800 NOTE: deleteStatus no longer deletes events from the summary
1801 table, but closes them.
1802
1803 @permission: ZEN_ADMIN_DEVICE
1804 """
1805 parent = self.getPrimaryParent()
1806 if deleteStatus:
1807
1808 zep = getFacade('zep')
1809 tagFilter = { 'tag_uuids': [IGlobalIdentifier(self).getGUID()] }
1810 eventFilter = { 'tag_filter': [ tagFilter ] }
1811 log.debug("Closing events for device: %s", self.getId())
1812 zep.closeEventSummaries(eventFilter=eventFilter)
1813 if deletePerf:
1814 perfserv = self.getPerformanceServer()
1815 if perfserv:
1816 perfserv.deleteRRDFiles(self.id)
1817 if REQUEST:
1818 audit('UI.Device.Delete', self, deleteStatus=deleteStatus,
1819 deleteHistory=deleteHistory, deletePerf=deletePerf)
1820 parent._delObject(self.getId())
1821 if REQUEST:
1822 if parent.getId()=='devices':
1823 parent = parent.getPrimaryParent()
1824 REQUEST['RESPONSE'].redirect(parent.absolute_url() +
1825 "/deviceOrganizerStatus"
1826 '?message=Device deleted')
1827
1828
1829 security.declareProtected(ZEN_ADMIN_DEVICE, 'renameDevice')
1831 """
1832 Rename device from the DMD. Disallow assignment of
1833 an id that already exists in the system.
1834
1835 @permission: ZEN_ADMIN_DEVICE
1836 @param newId: new name
1837 @type newId: string
1838 @param REQUEST: Zope REQUEST object
1839 @type REQUEST: Zope REQUEST object
1840 """
1841 parent = self.getPrimaryParent()
1842 path = self.absolute_url_path()
1843 oldId = self.getId()
1844 if newId is None:
1845 return path
1846
1847 if not isinstance(newId, unicode):
1848 newId = self.prepId(newId)
1849
1850 newId = newId.strip()
1851
1852 if newId == '' or newId == oldId:
1853 return path
1854
1855 device = self.dmd.Devices.findDeviceByIdExact( newId )
1856 if device:
1857 message = 'Device already exists with id %s' % newId
1858 raise DeviceExistsError( message, device )
1859
1860 if REQUEST:
1861 audit('UI.Device.ChangeId', self, id=newId)
1862
1863
1864 try:
1865
1866
1867 if self.title:
1868 self.title = newId
1869 parent.manage_renameObject(oldId, newId)
1870 self.renameDeviceInPerformance(oldId, newId)
1871 self.setLastChange()
1872 return self.absolute_url_path()
1873
1874 except CopyError, e:
1875 raise Exception("Device rename failed.")
1876
1897
1898
1908
1909
1916
1917
1919 """
1920 IpAddresses aren't contained underneath Device, so manage_beforeDelete
1921 won't propagate. Thus we must remove those links explicitly.
1922 """
1923 cat = self.dmd.ZenLinkManager._getCatalog(layer=3)
1924 brains = cat(deviceId=self.id)
1925 for brain in brains:
1926 brain.getObject().unindex_links()
1927
1928
1948
1949
1951 """
1952 Called by Commandable.doCommand() to ascertain objects on which
1953 a UserCommand should be executed.
1954 """
1955 return [self]
1956
1965
1967 """
1968 Returns a URL to redirect to after a command has executed
1969 used by Commandable
1970 """
1971 return self.getPrimaryUrlPath() + '/deviceManagement'
1972
1974 """
1975 Returns HTML Event Summary of a device
1976 """
1977 html = []
1978 html.append("<table width='100%' cellspacing='1' cellpadding='3'>")
1979 html.append("<tr>")
1980 def evsummarycell(ev):
1981 if ev[1]-ev[2]>=0: klass = '%s empty thin' % ev[0]
1982 else: klass = '%s thin' % ev[0]
1983 h = '<th align="center" width="16%%" class="%s">%s/%s</th>' % (
1984 klass, ev[1], ev[2])
1985 return h
1986 info = self.getEventSummary(severity)
1987 html += map(evsummarycell, info)
1988 html.append('</tr></table>')
1989 return '\n'.join(html)
1990
1992 """
1993 Returns data ready for serialization
1994 """
1995 url, classurl = map(urlquote,
1996 (self.getDeviceUrl(), self.getDeviceClassPath()))
1997 id = '<a class="tablevalues" href="%s">%s</a>' % (
1998 url, self.titleOrId())
1999 ip = self.getDeviceIp()
2000 if self.checkRemotePerm(ZEN_VIEW, self.deviceClass()):
2001 path = '<a href="/zport/dmd/Devices%s">%s</a>' % (classurl,classurl)
2002 else:
2003 path = classurl
2004 prod = self.getProdState()
2005 evsum = getEventPillME(self, 1, minSeverity)[0]
2006 return [id, ip, path, prod, evsum, self.id]
2007
2009 """
2010 Add export of our child objects.
2011 """
2012 map(lambda o: o.exportXml(ofile, ignorerels), (self.hw, self.os))
2013
2015 """
2016 Returns a list of possible options for a given zProperty
2017 """
2018 if propname == 'zCollectorPlugins':
2019 from Products.DataCollector.Plugins import loadPlugins
2020 return sorted(ldr.pluginName for ldr in loadPlugins(self.dmd))
2021 if propname == 'zCommandProtocol':
2022 return ['ssh', 'telnet']
2023 if propname == 'zSnmpVer':
2024 return ['v1', 'v2c', 'v3']
2025 if propname == 'zSnmpAuthType':
2026 return ['', 'MD5', 'SHA']
2027 if propname == 'zSnmpPrivType':
2028 return ['', 'DES', 'AES']
2029 return ManagedEntity.zenPropertyOptions(self, propname)
2030
2031 security.declareProtected(ZEN_MANAGE_DEVICE, 'pushConfig')
2033 """
2034 This will result in a push of all the devices to live collectors
2035
2036 @permission: ZEN_MANAGE_DEVICE
2037 """
2038 self._p_changed = True
2039 if REQUEST:
2040 messaging.IMessageSender(self).sendToBrowser(
2041 'Changes Pushed',
2042 'Changes to %s pushed to collectors.' % self.id
2043 )
2044 audit('UI.Device.PushChanges', self)
2045 return self.callZenScreen(REQUEST)
2046
2047 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'bindTemplates')
2049 """
2050 This will bind available templates to the zDeviceTemplates
2051
2052 @permission: ZEN_EDIT_LOCAL_TEMPLATES
2053 """
2054 result = self.setZenProperty('zDeviceTemplates', ids, REQUEST)
2055 if REQUEST:
2056 audit('UI.Device.BindTemplates', self, templates=ids)
2057 return result
2058
2059 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'removeZDeviceTemplates')
2075
2076 security.declareProtected(ZEN_EDIT_LOCAL_TEMPLATES, 'addLocalTemplate')
2094
2096 """
2097 Returns all available templates for this device
2098 """
2099
2100 templates = self.objectValues('RRDTemplate')
2101
2102
2103 device_template_ids = set(t.id for t in templates)
2104 templates.extend(t for t in self.deviceClass().getRRDTemplates()
2105 if t.id not in device_template_ids)
2106
2107
2108 templates = filter(lambda t: isinstance(self, t.getTargetPythonClass()), templates)
2109 return sorted(templates, key=lambda x: x.id.lower())
2110
2111
2112 security.declareProtected(ZEN_VIEW, 'getLinks')
2127
2128 security.declareProtected(ZEN_VIEW, 'getXMLEdges')
2129 - def getXMLEdges(self, depth=3, filter="/", start=()):
2137
2138 security.declareProtected(ZEN_VIEW, 'getPrettyLink')
2140 """
2141 Gets a link to this device, plus an icon
2142
2143 @rtype: HTML text
2144 @permission: ZEN_VIEW
2145 """
2146 template = ("<div class='device-icon-container'>"
2147 "<img class='device-icon' src='%s'/> "
2148 "</div>%s")
2149 icon = self.getIconPath()
2150 href = altHref if altHref else self.getPrimaryUrlPath()
2151 name = self.titleOrId()
2152
2153 rendered = template % (icon, name)
2154
2155 if not self.checkRemotePerm(ZEN_VIEW, self):
2156 return rendered
2157 else:
2158 return "<a %s href='%s' class='prettylink'>%s</a>" % \
2159 ('target=' + target if target else '', href, rendered)
2160
2161
2178
2180 """
2181 Returns either 4 or 6 depending on the version
2182 of the manageIp ip adddress
2183 """
2184 from ipaddr import IPAddress
2185 try:
2186 ip = self.getManageIp()
2187 return IPAddress(ip).version
2188 except ValueError:
2189
2190 pass
2191
2192 return 4
2193
2195 """
2196 This method gets the ip address prefix used for this device when running
2197 snmpwalk.
2198 @rtype: string
2199 @return: Prefix used for snmwalk for this device
2200 """
2201 if self.manageIpVersion() == 6:
2202 return "udp6:"
2203 return ""
2204
2206 """
2207 Used by the user commands this returns which ping command
2208 this device should use.
2209 @rtype: string
2210 @return "ping" or "ping6" depending on if the manageIp is ipv6 or not
2211 """
2212 if self.manageIpVersion() == 6:
2213 return "ping6"
2214 return "ping"
2215
2217 """
2218 Used by the user commands this returns which traceroute command
2219 this device should use.
2220 @rtype: string
2221 @return "traceroute" or "traceroute6" depending on if the manageIp is ipv6 or not
2222 """
2223 if self.manageIpVersion() == 6:
2224 return "traceroute6"
2225 return "traceroute"
2226
2227 - def getStatus(self, statusclass=None, **kwargs):
2228 """
2229 Return the status number for this device of class statClass.
2230 """
2231 from Products.ZenEvents.ZenEventClasses import Status_Ping
2232 if statusclass == Status_Ping:
2233 from Products.Zuul import getFacade
2234 from Products.ZenEvents.events2.proxy import EventProxy
2235 from zenoss.protocols.protobufs.zep_pb2 import STATUS_NEW, STATUS_ACKNOWLEDGED, \
2236 SEVERITY_CRITICAL, SEVERITY_ERROR, SEVERITY_WARNING
2237
2238
2239
2240
2241
2242 element_sub_identifier = [""]
2243 ifaces = self.getDeviceComponents(type='IpInterface')
2244 for iface in ifaces:
2245 if self.manageIp in [ip.partition("/")[0] for ip in iface.getIpAddresses()]:
2246 element_sub_identifier.append(iface.id)
2247 break
2248
2249 zep = getFacade('zep', self)
2250 event_filter = zep.createEventFilter(tags=[self.getUUID()],
2251 severity=[SEVERITY_WARNING,SEVERITY_ERROR,SEVERITY_CRITICAL],
2252 status=[STATUS_NEW,STATUS_ACKNOWLEDGED],
2253 element_sub_identifier=element_sub_identifier,
2254 event_class=filter(None, [statusclass]),
2255 details={EventProxy.DEVICE_IP_ADDRESS_DETAIL_KEY: self.getManageIp()})
2256 result = zep.getEventSummaries(0, filter=event_filter, limit=0)
2257 return int(result['total'])
2258
2259 return super(Device, self).getStatus(statusclass, **kwargs)
2260
2262 ip = self.getManageIp()
2263 if ip:
2264 ip = ip.partition('/')[0]
2265 if ip:
2266 return str(numbip(ip))
2267
2269 macs = []
2270 if hasattr(self, 'os') and hasattr(self.os, 'interfaces'):
2271 for intf in self.os.interfaces():
2272 if intf.macaddress:
2273 macs.append(intf.macaddress)
2274 return macs
2275
2276 InitializeClass(Device)
2277