def createDevice(self, driver): """ Add a device to the system by name or IP. @param driver: driver object @type driver: Twisted/Zenoss object @return: Twisted deferred @rtype: Twisted deferred """ deviceName = self.options.device self.log.info("Looking for %s" % deviceName) ip = None if isip(ipunwrap(deviceName)): ip = ipunwrap(deviceName) else: try: # FIXME ZenUtils.IpUtil.asyncIpLookup is probably a better tool # for this, but it hasn't been tested, so it's for another day self.log.debug("getHostByName") ip = getHostByName(deviceName) except socket.error: ip = "" if not ip: raise NoIPAddress("No IP found for name %s" % deviceName) else: self.log.debug("Found IP %s for device %s" % (ip, deviceName)) yield self.config().callRemote('getDeviceConfig', [deviceName]) me, = driver.next() or [None] if not me or me.temp_device or self.options.remodel: yield self.discoverDevice( ip, devicepath=self.options.deviceclass, prodState=self.options.productionState) yield succeed("Discovered device %s." % deviceName) driver.next()
def createDevice(self, driver): """ Add a device to the system by name or IP. @param driver: driver object @type driver: Twisted/Zenoss object @return: Twisted deferred @rtype: Twisted deferred """ deviceName = self.options.device self.log.info("Looking for %s" % deviceName) ip = None if isip(ipunwrap(deviceName)): ip = ipunwrap(deviceName) else: try: # FIXME ZenUtils.IpUtil.asyncIpLookup is probably a better tool # for this, but it hasn't been tested, so it's for another day self.log.debug("getHostByName") ip = getHostByName(deviceName) except socket.error: ip = "" if not ip: raise NoIPAddress("No IP found for name %s" % deviceName) else: self.log.debug("Found IP %s for device %s" % (ip, deviceName)) yield self.config().callRemote('getDeviceConfig', [deviceName]) me, = driver.next() or [None] if not me or me.temp_device or self.options.remodel: yield self.discoverDevice(ip, devicepath=self.options.deviceclass, prodState=self.options.productionState) yield succeed("Discovered device %s." % deviceName) driver.next()
def fullIpList(self): "copied from IpNetwork" log.debug("fullIpList: using ipaddr IPNetwork on %s (%s)" % (self.id, ipunwrap(self.id))) net = IPNetwork(ipunwrap(self.id)) if self.netmask == net.max_prefixlen: return [ipunwrap(self.id)] ipnumb = long(int(net)) maxip = math.pow(2, net.max_prefixlen - self.netmask) start = int(ipnumb+1) end = int(ipnumb+maxip-1) return map(strip, range(start,end))
def _doDbWork(): """ return device object (either new or existing), and flag indicating whether device was newly created, or just updated """ try: netroot = getNetworkRoot(self.dmd, kw.get('performanceMonitor', 'localhost')) netobj = netroot.getNet(ip) netmask = 24 if netobj is not None: netmask = netobj.netmask else: defaultNetmasks = getattr(netroot, 'zDefaultNetworkTree', []) if defaultNetmasks: netmask = defaultNetmasks[0] autoDiscover = getattr(netobj, 'zAutoDiscover', True) # If we're not supposed to discover this IP, return None if not force and not autoDiscover: return None, False kw['manageIp'] = ipunwrap(ip) dev = manage_createDevice(self.dmd, **kw) netroot.createIp(ip, netmask) return dev, True except DeviceExistsError as e: # Update device with latest info from zendisc # (if necessary) if not e.dev.getManageIp(): e.dev.setManageIp(kw['manageIp']) # only overwrite title if it has not been set if not e.dev.title or isip(e.dev.title): if not isip(kw.get('deviceName')): e.dev.setTitle(kw['deviceName']) # copy kw->updateAttributes, to keep kw intact in case # we need to retry transaction updateAttributes = {} for k,v in kw.items(): if k not in ('manageIp', 'deviceName', 'devicePath', 'discoverProto', 'performanceMonitor', 'productionState'): updateAttributes[k] = v # use updateDevice so we don't clobber existing device properties. e.dev.updateDevice(**updateAttributes) return e.dev, False except Exception as ex: log.exception("IP address %s (kw = %s) encountered error", ipunwrap(ip), kw) raise pb.CopyableFailure(ex)
def __init__(self, ip, ipVersion=4, iface='', basepath='', ds=None, perfServer='localhost'): self.ip = ipunwrap(ip) self.ipVersion = ipVersion self.iface = iface self.cycleTime = getattr(ds, 'cycleTime', 60) self.tries = getattr(ds, 'attempts', 2) self.sampleSize = getattr(ds, 'sampleSize', 1) self.points = [] self.connectedIps = [] if not ds: # Don't need the datapoints to get the IP monitored return log.debug("Using the %s template settings for IP %s", ds.rrdTemplate().getPrimaryUrlPath(), self.ip) for dp in ds.getRRDDataPoints(): ipdData = (dp.id, "/".join((basepath, dp.name())), dp.rrdtype, dp.getRRDCreateCommand(perfServer).strip(), dp.rrdmin, dp.rrdmax) self.points.append(ipdData)
def setPtrName(self): try: data = socket.gethostbyaddr(ipunwrap(self.id)) if data: self.ptrName = data[0] except socket.error, e: self.ptrName = "" log.warn("%s: %s", self.title, e)
def createDevice(self): """ Add a device to the system by name or IP. """ deviceName = self.options.device self.log.info("Looking for %s", deviceName) ip = ipunwrap(deviceName) if not isip(ip): try: ip = yield getHostByName(deviceName) except socket.error as ex: self.log.warn( "Hostname lookup failed for %s: %s", deviceName, ex ) raise NoIPAddress("No IP found for name %s" % deviceName) self.log.info("Found IP %s for device %s", ip, deviceName) configs = yield self.config().callRemote( 'getDeviceConfig', [deviceName] ) config = configs[0] if configs else None if not config or config.temp_device or self.options.remodel: device = yield self.discoverDevice( ip, devicepath=self.options.deviceclass, prodState=self.options.productionState, deviceConfig=config ) if device: self.log.info("Discovered device %s.", device.id) else: self.log.info("Device '%s' not found", deviceName) defer.returnValue(device) else: self.log.info("Device '%s' already found", deviceName)
def idx_lastDecimalIp(self): last_decimal_ip = None if isip(self.id): net = IPNetwork(ipunwrap(self.id)) first_decimal_ip = long(int(net.network)) last_decimal_ip = str(long(first_decimal_ip + math.pow(2, net.max_prefixlen - self.netmask) - 1)) return last_decimal_ip
def createDevice(self): """ Add a device to the system by name or IP. """ deviceName = self.options.device self.log.info("Looking for %s", deviceName) ip = ipunwrap(deviceName) if not isip(ip): try: ip = yield getHostByName(deviceName) except socket.error as ex: self.log.warn("Hostname lookup failed for %s: %s", deviceName, ex) raise NoIPAddress("No IP found for name %s" % deviceName) self.log.info("Found IP %s for device %s", ip, deviceName) configs = yield self.config().callRemote('getDeviceConfig', [deviceName]) config = configs[0] if configs else None if not config or config.temp_device or self.options.remodel: device = yield self.discoverDevice( ip, devicepath=self.options.deviceclass, prodState=self.options.productionState) if device: self.log.info("Discovered device %s.", device.id) else: self.log.info("Device '%s' not found", deviceName) defer.returnValue(device) else: self.log.info("Device '%s' already found", deviceName)
def __init__(self, ip, ipVersion=4, iface='', ds=None, perfServer='localhost', metadata=None): self.ip = ipunwrap(ip) self.ipVersion = ipVersion self.iface = iface self.cycleTime = getattr(ds, 'cycleTime', 60) self.tries = getattr(ds, 'attempts', 2) self.sampleSize = getattr(ds, 'sampleSize', 1) self.points = [] self.connectedIps = [] if not ds: # Don't need the datapoints to get the IP monitored return log.debug("Using the %s template settings for IP %s", ds.rrdTemplate().getPrimaryUrlPath(), self.ip) for dp in ds.getRRDDataPoints(): ipdData = (dp.id, dp.name(), dp.rrdtype, dp.getRRDCreateCommand(perfServer).strip(), dp.rrdmin, dp.rrdmax, metadata) self.points.append(ipdData)
def setIpAddress(self, ip): """ Set the IP address. Use the format 1.1.1.1/24 to also set the netmask """ iparray = ip.split("/") if len(iparray) > 1: ip = iparray[0] self._netmask = maskToBits(iparray[1]) checkip(ip) aqself = self.primaryAq() #set aq path network = aqself.aq_parent netip = netFromIpAndNet(ip, network.netmask) if netip == network.id: network._renameObject(aqself.id, ipwrap(ip)) else: raise WrongSubnetError("IP %s is in a different subnet than %s" % (ipunwrap(ip), ipunwrap(self.id)))
def setIpAddress(self, ip): """ Set the IP address. Use the format 1.1.1.1/24 to also set the netmask """ iparray = ip.split("/") if len(iparray) > 1: ip = iparray[0] self._netmask = maskToBits(iparray[1]) checkip(ip) aqself = self.primaryAq() #set aq path network = aqself.aq_parent netip = netFromIpAndNet(ip, network.netmask) if netip == network.id: network._renameObject(aqself.id, ipwrap(ip)) else: raise WrongSubnetError( "IP %s is in a different subnet than %s" % (ipunwrap(ip), ipunwrap(self.id)) )
def __init__(self, id, netmask=24): checkip(id) ManagedEntity.__init__(self, ipwrap(id)) ipobj = IPAddress(ipunwrap_strip(id)) if ipobj.version == 6: # No user-definable subnet masks for IPv6 netmask = 64 self._netmask = maskToBits(netmask) self.ptrName = None self.title = ipunwrap(id) self.version = ipobj.version
def __init__(self, taskName, deviceId, scheduleIntervalSeconds, taskConfig): """ @param deviceId: the Zenoss deviceId to watch @type deviceId: string @param taskName: the unique identifier for this task @type taskName: string @param scheduleIntervalSeconds: the interval at which this task will be collected @type scheduleIntervalSeconds: int @param taskConfig: the configuration for this task """ super(PingTask, self).__init__( taskName, deviceId, scheduleIntervalSeconds, taskConfig ) # Needed for interface self.name = taskName self.configId = deviceId self.state = TaskStates.STATE_IDLE # The taskConfig corresponds to a DeviceProxy self._device = taskConfig self._devId = deviceId self._manageIp = ipunwrap(self._device.manageIp) self.interval = scheduleIntervalSeconds self._pingResult = None self._isUp = None self._daemon = component.queryUtility(interfaces.ICollector) self._dataService = component.queryUtility(interfaces.IDataService) self._eventService = component.queryUtility(interfaces.IEventService) self._preferences = component.queryUtility(interfaces.ICollectorPreferences, COLLECTOR_NAME) self._traceCache = self._preferences.options.traceCache if self._traceCache.get(self._devId, None) is None: self._traceCache[self._devId] = tuple() # Split up so that every interface's IP gets its own ping job self.config = self._device.monitoredIps[0] self._iface = self.config.iface self._lastErrorMsg = '' # by defautl don't pause after schedule self.pauseOnScheduled = False self._rtt =[]
def _doDbWork(): """ return device object (either new or existing), and flag indicating whether device was newly created, or just updated """ try: netroot = getNetworkRoot(self.dmd, kw.get('performanceMonitor', 'localhost')) netobj = netroot.getNet(ip) netmask = 24 if netobj is not None: netmask = netobj.netmask else: defaultNetmasks = getattr(netroot, 'zDefaultNetworkTree', []) if defaultNetmasks: netmask = defaultNetmasks[0] autoDiscover = getattr(netobj, 'zAutoDiscover', True) # If we're not supposed to discover this IP, return None if not force and not autoDiscover: return None, False kw['manageIp'] = ipunwrap(ip) dev = manage_createDevice(self.dmd, **kw) netroot.createIp(ip, netmask) return dev, True except DeviceExistsError, e: # Update device with latest info from zendisc # (if necessary) if not e.dev.getManageIp(): e.dev.setManageIp(kw['manageIp']) # only overwrite title if it has not been set if not e.dev.title or isip(e.dev.title): if not isip(kw.get('deviceName')): e.dev.setTitle(kw['deviceName']) # copy kw->updateAttributes, to keep kw intact in case # we need to retry transaction updateAttributes = {} for k,v in kw.items(): if k not in ('manageIp', 'deviceName', 'devicePath', 'discoverProto', 'performanceMonitor', 'productionState'): updateAttributes[k] = v # use updateDevice so we don't clobber existing device properties. e.dev.updateDevice(**updateAttributes) return e.dev, False
def __init__(self, taskName, deviceId, scheduleIntervalSeconds, taskConfig): """ @param deviceId: the Zenoss deviceId to watch @type deviceId: string @param taskName: the unique identifier for this task @type taskName: string @param scheduleIntervalSeconds: the interval at which this task will be collected @type scheduleIntervalSeconds: int @param taskConfig: the configuration for this task """ super(PingTask, self).__init__(taskName, deviceId, scheduleIntervalSeconds, taskConfig) # Needed for interface self.name = taskName self.configId = deviceId self.state = TaskStates.STATE_IDLE # The taskConfig corresponds to a DeviceProxy self._device = taskConfig self._devId = deviceId self._manageIp = ipunwrap(self._device.manageIp) self.interval = scheduleIntervalSeconds self._pingResult = None self._isUp = None self._daemon = component.queryUtility(interfaces.ICollector) self._dataService = component.queryUtility(interfaces.IDataService) self._eventService = component.queryUtility(interfaces.IEventService) self._preferences = component.queryUtility( interfaces.ICollectorPreferences, COLLECTOR_NAME) self._traceCache = self._preferences.options.traceCache if self._traceCache.get(self._devId, None) is None: self._traceCache[self._devId] = tuple() # Split up so that every interface's IP gets its own ping job self.config = self._device.monitoredIps[0] self._iface = self.config.iface self._lastErrorMsg = '' # by defautl don't pause after schedule self.pauseOnScheduled = False self._rtt = []
def getNetworkName(self): return "%s/%d" % (ipunwrap(self.id), self.netmask)
def idx_firstDecimalIp(self): first_decimal_ip = None if isip(self.id): net = IPNetwork(ipunwrap(self.id)) first_decimal_ip = str(int(net.network)) return first_decimal_ip
def getIp(self): """ Return only the IP address """ return ipunwrap(self.id)
def remote_createDevice(self, ip, force=False, **kw): """Create a device. @param ip: The manageIp of the device @param kw: The args to manage_createDevice. """ # During discovery, if the device # shares an id with another device # with a different ip, set the device # title to the supplied id and replace # the id with the ip deviceName = kw['deviceName'] if deviceName: device = self.dmd.Devices.findDeviceByIdExact(deviceName) if device and ip != device.manageIp: kw['deviceName'] = ip kw['title'] = deviceName from Products.ZenModel.Device import getNetworkRoot @transact def _doDbWork(): """ return device object (either new or existing), and flag indicating whether device was newly created, or just updated """ try: netroot = getNetworkRoot( self.dmd, kw.get('performanceMonitor', 'localhost')) netobj = netroot.getNet(ip) netmask = 24 if netobj is not None: netmask = netobj.netmask else: defaultNetmasks = getattr(netroot, 'zDefaultNetworkTree', []) if defaultNetmasks: netmask = defaultNetmasks[0] netroot.createIp(ip, netmask) autoDiscover = getattr(netobj, 'zAutoDiscover', True) # If we're not supposed to discover this IP, return None if not force and not autoDiscover: return None, False kw['manageIp'] = ipunwrap(ip) dev = manage_createDevice(self.dmd, **kw) return dev, True except DeviceExistsError, e: # Update device with latest info from zendisc e.dev.setManageIp(kw['manageIp']) # only overwrite title if it has not been set if not e.dev.title or isip(e.dev.title): if not isip(kw.get('deviceName')): e.dev.setTitle(kw['deviceName']) # copy kw->updateAttributes, to keep kw intact in case # we need to retry transaction updateAttributes = {} for k, v in kw.items(): if k not in ('manageIp', 'deviceName', 'devicePath', 'discoverProto'): updateAttributes[k] = v # use updateDevice so we don't clobber existing device properties. e.dev.updateDevice(**updateAttributes) return e.dev, False except Exception, ex: log.exception("IP address %s (kw = %s) encountered error", ipunwrap(ip), kw) raise pb.CopyableFailure(ex)
def getIpAddress(self): """ Return the IP with its netmask in the form 1.1.1.1/24 """ return ipunwrap(self.id) + "/" + str(self._netmask)
def inner(driver): """ Twisted driver class to iterate through devices @param driver: Zenoss driver @type driver: Zenoss driver @return: successful result is a list of IPs that were added @rtype: Twisted deferred @todo: modularize this function (130+ lines is ridiculous) """ try: kw = dict(deviceName=ip, discoverProto=None, devicePath=devicepath, performanceMonitor=self.options.monitor, productionState=prodState) # If zProperties are set via a job, get them and pass them in if self.options.job: yield self.config().callRemote('getJobProperties', self.options.job) job_props = driver.next() if job_props is not None: # grab zProperties from Job kw['zProperties'] = getattr(job_props, 'zProperties', {}) # grab other Device properties from jobs #deviceProps = job_props.get('deviceProps', {}) #kw.update(deviceProps) #@FIXME we are not getting deviceProps, check calling # chain for clues. twisted upgrade heartburn perhaps? # if we are using SNMP, lookup the device SNMP info and use the # name defined there for deviceName if not self.options.nosnmp: self.log.debug("Scanning device with address %s", ip) snmpCommunities = kw.get('zProperties', {}).get( 'zSnmpCommunities', None) yield self.findRemoteDeviceInfo(ip, devicepath, snmpCommunities) snmp_config = driver.next() if snmp_config: if snmp_config.sysName: kw['deviceName'] = snmp_config.sysName if snmp_config.version: kw['zSnmpVer'] = snmp_config.version if snmp_config.port: kw['zSnmpPort'] = snmp_config.port if snmp_config.community: kw['zSnmpCommunity'] = snmp_config.community # if we are using SNMP, did not find any snmp info, # and we are in strict discovery mode, do not # create a device elif self.options.zSnmpStrictDiscovery: self.log.info('zSnmpStrictDiscovery is True. ' + 'Not creating device for %s.' % ip ) return # RULES FOR DEVICE NAMING: # 1. If zPreferSnmpNaming is true: # If snmp name is returned, use snmp name. Otherwise, # use the passed device name. If no device name was passed, # do a dns lookup on the ip. # 2. If zPreferSnmpNaming is false: # If we are discovering a single device and a name is # passed in instead of an IP, use the passed-in name. # Otherwise, do a dns lookup on the ip. if self.options.zPreferSnmpNaming and \ not isip( kw['deviceName'] ): # In this case, we want to keep kw['deviceName'] as-is, # because it is what we got from snmp pass elif self.options.device and not isip(self.options.device): kw['deviceName'] = self.options.device else: # An IP was passed in so we do a reverse lookup on it to get # deviceName yield asyncNameLookup(ip) try: kw.update(dict(deviceName=driver.next())) except Exception, ex: self.log.debug("Failed to lookup %s (%s)" % (ip, ex)) # If it's discovering a particular device, # ignore zAutoDiscover limitations forceDiscovery = bool(self.options.device) # now create the device by calling zenhub yield self.config().callRemote('createDevice', ipunwrap(ip), force=forceDiscovery, **kw) result = driver.next() self.log.debug("ZenDisc.discoverDevice.inner: got result from remote_createDevice") if isinstance(result, Failure): raise ZentinelException(result.value) dev, created = result # if no device came back from createDevice we assume that it # was told to not auto-discover the device. This seems very # dubious to me! -EAD if not dev: self.log.info("IP '%s' on no auto-discover, skipping",ip) return else: # A device came back and it already existed. if not created and not dev.temp_device: # if we shouldn't remodel skip the device by returning # at the end of this block if not self.options.remodel: self.log.info("Found IP '%s' on device '%s';" " skipping discovery", ip, dev.id) if self.options.device: self.setExitCode(3) yield succeed(dev) driver.next() return else: # we continue on to model the device. self.log.info("IP '%s' on device '%s' remodel", ip, dev.id) self.sendDiscoveredEvent(ip, dev) # the device that we found/created or that should be remodeled # is added to the list of devices to be modeled later if not self.options.nosnmp: self.discovered.append(dev.id) yield succeed(dev) driver.next()
def discoverDevice(self, ip, devicepath=None, prodState=None): """ Discover the device at the given IP address. @param ip: IP address @type ip: string @param devicepath: where in the DMD to put any discovered devices @type devicepath: string @param prodState: production state (see Admin Guide for a description) @type prodState: integer @return: Twisted/Zenoss Python iterable @rtype: Python iterable """ if devicepath is None: devicepath = self.options.deviceclass if prodState is None: prodState = self.options.productionState self.scanned += 1 if self.options.maxdevices: if self.scanned >= self.options.maxdevices: self.log.info("Limit of %d devices reached", self.options.maxdevices) defer.returnValue(None) try: kw = dict(deviceName=ip, discoverProto=None, devicePath=devicepath, performanceMonitor=self.options.monitor, productionState=prodState) # If zProperties are set via a job, get them and pass them in if self.options.job: job_props = yield self.config().callRemote( 'getJobProperties', self.options.job) if job_props is not None: # grab zProperties from Job kw['zProperties'] = getattr(job_props, 'zProperties', {}) # grab other Device properties from jobs # deviceProps = job_props.get('deviceProps', {}) # kw.update(deviceProps) # @FIXME we are not getting deviceProps, check calling # chain for clues. twisted upgrade heartburn perhaps? # if we are using SNMP, lookup the device SNMP info and use the # name defined there for deviceName if not self.options.nosnmp: self.log.debug("Scanning device with address %s", ip) snmpCommunities = \ kw.get('zProperties', {}).get('zSnmpCommunities', None) snmp_config = yield self.findRemoteDeviceInfo( ip, devicepath, snmpCommunities) if snmp_config: if snmp_config.sysName: kw['deviceName'] = snmp_config.sysName if snmp_config.version: kw['zSnmpVer'] = snmp_config.version if snmp_config.port: kw['zSnmpPort'] = snmp_config.port if snmp_config.community: kw['zSnmpCommunity'] = snmp_config.community # Since we did not find any snmp info and we are in # strict discovery mode, do not create a device elif self.options.zSnmpStrictDiscovery: self.log.info( "zSnmpStrictDiscovery is True. " "Not creating device for %s.", ip) defer.returnValue(None) # RULES FOR DEVICE NAMING: # 1. If zPreferSnmpNaming is true: # If snmp name is returned, use snmp name. Otherwise, # use the passed device name. If no device name was passed, # do a dns lookup on the ip. # 2. If zPreferSnmpNaming is false: # If we are discovering a single device and a name is # passed in instead of an IP, use the passed-in name. # Otherwise, do a dns lookup on the ip. if self.options.zPreferSnmpNaming and not isip(kw['deviceName']): # In this case, we want to keep kw['deviceName'] as-is, # because it is what we got from snmp pass elif self.options.device and not isip(self.options.device): kw['deviceName'] = self.options.device else: # An IP was passed in so we do a reverse lookup on it to get # deviceName try: kw["deviceName"] = yield asyncNameLookup(ip) except Exception as ex: self.log.debug("Failed to lookup %s (%s)", ip, ex) # If it's discovering a particular device, # ignore zAutoDiscover limitations forceDiscovery = bool(self.options.device) # now create the device by calling zenhub result = None try: result = yield self.config().callRemote('createDevice', ipunwrap(ip), force=forceDiscovery, **kw) except Exception as ex: raise ZentinelException(ex) self.log.debug("Got result from remote_createDevice: %s", result) dev, created = result # if no device came back from createDevice we assume that it # was told to not auto-discover the device. This seems very # dubious to me! -EAD if not dev: self.log.info("IP '%s' on no auto-discover, skipping", ip) defer.returnValue(None) # A device came back and it already existed. if not created and not dev.temp_device: # if we shouldn't remodel skip the device by returning # at the end of this block if not self.options.remodel: self.log.info( "Found IP '%s' on device '%s';" " skipping discovery", ip, dev.id) if self.options.device: self.setExitCode(3) defer.returnValue(dev) else: # we continue on to model the device. self.log.info("IP '%s' on device '%s' remodel", ip, dev.id) self.sendDiscoveredEvent(ip, dev) # the device that we found/created or that should be remodeled # is added to the list of devices to be modeled later if not self.options.nosnmp: self.discovered.append(dev.id) yield self.config().callRemote('succeedDiscovery', dev.id) defer.returnValue(dev) except ZentinelException as e: self.log.exception(e) if self.options.snmpMissing: self.sendEvent( dict(device=ip, component=ip, ipAddress=ip, eventKey=ip, eventClass=Status_Snmp, summary=str(e), severity=Info, agent="Discover")) except Exception as e: self.log.exception("Failed device discovery for '%s'", ip) finally: self.log.info("Finished scanning device with address %s", ip)
def discoverDevice(self, ip, devicepath=None, prodState=None, deviceConfig=None): """ Discover the device at the given IP address. @param ip: IP address @type ip: string @param devicepath: where in the DMD to put any discovered devices @type devicepath: string @param prodState: production state (see Admin Guide for a description) @type prodState: integer @return: Twisted/Zenoss Python iterable @rtype: Python iterable """ if devicepath is None: devicepath = self.options.deviceclass if prodState is None: prodState = self.options.productionState self.scanned += 1 if self.options.maxdevices: if self.scanned >= self.options.maxdevices: self.log.info("Limit of %d devices reached", self.options.maxdevices) defer.returnValue(None) try: kw = dict( deviceName=ip, discoverProto=None, devicePath=devicepath, performanceMonitor=self.options.monitor, locationPath=self.options.location, groupPaths=self.options.groups, systemPaths=self.options.systems, productionState=prodState ) # If zProperties are set via a job, get them and pass them in if self.options.job: job_props = yield self.config().callRemote( 'getJobProperties', self.options.job ) if job_props is not None: # grab zProperties from Job kw['zProperties'] = getattr(job_props, 'zProperties', {}) # grab other Device properties from jobs # deviceProps = job_props.get('deviceProps', {}) # kw.update(deviceProps) # @FIXME we are not getting deviceProps, check calling # chain for clues. twisted upgrade heartburn perhaps? # if we are using SNMP, lookup the device SNMP info and use the # name defined there for deviceName if not self.options.nosnmp: self.log.debug("Scanning device with address %s", ip) zProps = kw.get('zProperties', {}) deviceSnmpCommunities = zProps.get('zSnmpCommunities', None) if not deviceSnmpCommunities and deviceConfig: deviceSnmpCommunities = getattr( deviceConfig, 'zSnmpCommunities', None) snmp_config = yield self.findRemoteDeviceInfo( ip, devicepath, deviceSnmpCommunities ) if snmp_config: if snmp_config.sysName: kw['deviceName'] = snmp_config.sysName if snmp_config.version: kw['zSnmpVer'] = snmp_config.version if snmp_config.port: kw['zSnmpPort'] = snmp_config.port if snmp_config.community: kw['zSnmpCommunity'] = snmp_config.community # Since we did not find any snmp info and we are in # strict discovery mode, do not create a device elif self.options.zSnmpStrictDiscovery: self.log.info( "zSnmpStrictDiscovery is True. " "Not creating device for %s.", ip ) defer.returnValue(None) # RULES FOR DEVICE NAMING: # 1. If zPreferSnmpNaming is true: # If snmp name is returned, use snmp name. Otherwise, # use the passed device name. If no device name was passed, # do a dns lookup on the ip. # 2. If zPreferSnmpNaming is false: # If we are discovering a single device and a name is # passed in instead of an IP, use the passed-in name. # Otherwise, do a dns lookup on the ip. if self.options.zPreferSnmpNaming and not isip(kw['deviceName']): # In this case, we want to keep kw['deviceName'] as-is, # because it is what we got from snmp pass elif self.options.device and not isip(self.options.device): kw['deviceName'] = self.options.device else: # An IP was passed in so we do a reverse lookup on it to get # deviceName try: kw["deviceName"] = yield asyncNameLookup(ip) except Exception as ex: self.log.debug("Failed to lookup %s (%s)", ip, ex) # If it's discovering a particular device, # ignore zAutoDiscover limitations forceDiscovery = bool(self.options.device) # now create the device by calling zenhub result = None try: result = yield self.config().callRemote( 'createDevice', ipunwrap(ip), force=forceDiscovery, **kw ) except Exception as ex: raise ZentinelException(ex) self.log.debug("Got result from remote_createDevice: %s", result) dev, created = result # if no device came back from createDevice we assume that it # was told to not auto-discover the device. This seems very # dubious to me! -EAD if not dev: self.log.info("IP '%s' on no auto-discover, skipping", ip) defer.returnValue(None) # A device came back and it already existed. if not created and not dev.temp_device: # if we shouldn't remodel skip the device by returning # at the end of this block if not self.options.remodel: self.log.info("Found IP '%s' on device '%s';" " skipping discovery", ip, dev.id) if self.options.device: self.setExitCode(3) defer.returnValue(dev) else: # we continue on to model the device. self.log.info("IP '%s' on device '%s' remodel", ip, dev.id) self.sendDiscoveredEvent(ip, dev) # the device that we found/created or that should be remodeled # is added to the list of devices to be modeled later if not self.options.nosnmp: self.discovered.append(dev.id) yield self.config().callRemote('succeedDiscovery', dev.id) defer.returnValue(dev) except ZentinelException as e: self.log.exception(e) if self.options.snmpMissing: self.sendEvent(dict( device=ip, component=ip, ipAddress=ip, eventKey=ip, eventClass=Status_Snmp, summary=str(e), severity=Info, agent="Discover" )) except Exception as e: self.log.exception("Failed device discovery for '%s'", ip) finally: self.log.info("Finished scanning device with address %s", ip)
def inner(driver): """ Twisted driver class to iterate through devices @param driver: Zenoss driver @type driver: Zenoss driver @return: successful result is a list of IPs that were added @rtype: Twisted deferred @todo: modularize this function (130+ lines is ridiculous) """ try: kw = dict(deviceName=ip, discoverProto=None, devicePath=devicepath, performanceMonitor=self.options.monitor, productionState=prodState) # If zProperties are set via a job, get them and pass them in if self.options.job: yield self.config().callRemote('getJobProperties', self.options.job) job_props = driver.next() if job_props is not None: # grab zProperties from Job kw['zProperties'] = getattr(job_props, 'zProperties', {}) # grab other Device properties from jobs #deviceProps = job_props.get('deviceProps', {}) #kw.update(deviceProps) #@FIXME we are not getting deviceProps, check calling # chain for clues. twisted upgrade heartburn perhaps? # if we are using SNMP, lookup the device SNMP info and use the # name defined there for deviceName if not self.options.nosnmp: self.log.debug("Scanning device with address %s", ip) snmpCommunities = kw.get('zProperties', {}).get('zSnmpCommunities', None) yield self.findRemoteDeviceInfo(ip, devicepath, snmpCommunities) snmp_config = driver.next() if snmp_config: if snmp_config.sysName: kw['deviceName'] = snmp_config.sysName if snmp_config.version: kw['zSnmpVer'] = snmp_config.version if snmp_config.port: kw['zSnmpPort'] = snmp_config.port if snmp_config.community: kw['zSnmpCommunity'] = snmp_config.community # if we are using SNMP, did not find any snmp info, # and we are in strict discovery mode, do not # create a device elif self.options.zSnmpStrictDiscovery: self.log.info('zSnmpStrictDiscovery is True. ' + 'Not creating device for %s.' % ip) return # RULES FOR DEVICE NAMING: # 1. If zPreferSnmpNaming is true: # If snmp name is returned, use snmp name. Otherwise, # use the passed device name. If no device name was passed, # do a dns lookup on the ip. # 2. If zPreferSnmpNaming is false: # If we are discovering a single device and a name is # passed in instead of an IP, use the passed-in name. # Otherwise, do a dns lookup on the ip. if self.options.zPreferSnmpNaming and \ not isip( kw['deviceName'] ): # In this case, we want to keep kw['deviceName'] as-is, # because it is what we got from snmp pass elif self.options.device and not isip(self.options.device): kw['deviceName'] = self.options.device else: # An IP was passed in so we do a reverse lookup on it to get # deviceName yield asyncNameLookup(ip) try: kw.update(dict(deviceName=driver.next())) except Exception, ex: self.log.debug("Failed to lookup %s (%s)" % (ip, ex)) # If it's discovering a particular device, # ignore zAutoDiscover limitations forceDiscovery = bool(self.options.device) # now create the device by calling zenhub yield self.config().callRemote('createDevice', ipunwrap(ip), force=forceDiscovery, **kw) result = driver.next() self.log.debug( "ZenDisc.discoverDevice.inner: got result from remote_createDevice" ) if isinstance(result, Failure): raise ZentinelException(result.value) dev, created = result # if no device came back from createDevice we assume that it # was told to not auto-discover the device. This seems very # dubious to me! -EAD if not dev: self.log.info("IP '%s' on no auto-discover, skipping", ip) return else: # A device came back and it already existed. if not created and not dev.temp_device: # if we shouldn't remodel skip the device by returning # at the end of this block if not self.options.remodel: self.log.info( "Found IP '%s' on device '%s';" " skipping discovery", ip, dev.id) if self.options.device: self.setExitCode(3) yield succeed(dev) driver.next() return else: # we continue on to model the device. self.log.info("IP '%s' on device '%s' remodel", ip, dev.id) self.sendDiscoveredEvent(ip, dev) # the device that we found/created or that should be remodeled # is added to the list of devices to be modeled later if not self.options.nosnmp: self.discovered.append(dev.id) yield succeed(dev) driver.next()
def remote_createDevice(self, ip, force=False, **kw): """Create a device. @param ip: The manageIp of the device @param kw: The args to manage_createDevice. """ # During discovery, if the device # shares an id with another device # with a different ip, set the device # title to the supplied id and replace # the id with the ip deviceName = kw['deviceName'] if deviceName: device = self.dmd.Devices.findDeviceByIdExact(deviceName) if device and all((device.manageIp, not device._temp_device, ip != device.manageIp)): kw['deviceName'] = ip kw['title'] = deviceName from Products.ZenModel.Device import getNetworkRoot @transact def _doDbWork(): """ return device object (either new or existing), and flag indicating whether device was newly created, or just updated """ try: netroot = getNetworkRoot(self.dmd, kw.get('performanceMonitor', 'localhost')) netobj = netroot.getNet(ip) netmask = 24 if netobj is not None: netmask = netobj.netmask else: defaultNetmasks = getattr(netroot, 'zDefaultNetworkTree', []) if defaultNetmasks: netmask = defaultNetmasks[0] autoDiscover = getattr(netobj, 'zAutoDiscover', True) # If we're not supposed to discover this IP, return None if not force and not autoDiscover: return None, False kw['manageIp'] = ipunwrap(ip) dev = manage_createDevice(self.dmd, **kw) netroot.createIp(ip, netmask) return dev, True except DeviceExistsError, e: # Update device with latest info from zendisc # (if necessary) if not e.dev.getManageIp(): e.dev.setManageIp(kw['manageIp']) # only overwrite title if it has not been set if not e.dev.title or isip(e.dev.title): if not isip(kw.get('deviceName')): e.dev.setTitle(kw['deviceName']) # copy kw->updateAttributes, to keep kw intact in case # we need to retry transaction updateAttributes = {} for k,v in kw.items(): if k not in ('manageIp', 'deviceName', 'devicePath', 'discoverProto', 'performanceMonitor', 'productionState'): updateAttributes[k] = v # use updateDevice so we don't clobber existing device properties. e.dev.updateDevice(**updateAttributes) return e.dev, False except Exception, ex: log.exception("IP address %s (kw = %s) encountered error", ipunwrap(ip), kw) raise pb.CopyableFailure(ex)