Package Products :: Package ZenHub :: Package services :: Module DiscoverService |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenHub.services.DiscoverService

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2008, Zenoss Inc.
      5  #
      6  # This program is free software; you can redistribute it and/or modify it
      7  # under the terms of the GNU General Public License version 2 as published by
      8  # the Free Software Foundation.
      9  #
     10  # For complete information please visit: http://www.zenoss.com/oss/
     11  #
     12  ###########################################################################
     13
     14  import logging
     15  log = logging.getLogger('zen.DiscoverService')
     16
     17  from Products.ZenUtils.IpUtil import numbip, strip
     18  from Products.ZenEvents.Event import Event
     19  from Products.ZenEvents.ZenEventClasses import Status_Ping
     20  from Products.ZenModel.Device import manage_createDevice
     21  from Products.Jobber.status import JobStatusProxy
     22  from Products.ZenHub.PBDaemon import translateError
     23  from Products.ZenModel.Exceptions import DeviceExistsError
     24
     25  import transaction
     26
     27  from twisted.spread import pb
     28  import math
     29  import re
     30
     31  from ModelerService import ModelerService
     32
     33  DEFAULT_PING_THRESH = 168
     34
     35
     36 -class IpNetProxy(pb.Copyable, pb.RemoteCopy):
     37      "A class that will represent a ZenModel/IpNetwork in zendisc"
     38
     39      id = ''
     40      _children = None
     41      netmask = None
     42
     43 -    def __init__(self, ipnet):
     44          self.id = ipnet.id
     45          self._children = map(IpNetProxy, ipnet.children())
     46          self.netmask = ipnet.netmask
     47          for prop in 'zAutoDiscover zDefaultNetworkTree zPingFailThresh'.split():
     48              if hasattr(ipnet, prop):
     49                  setattr(self, prop, getattr(ipnet, prop))
     50
     51 -    def children(self):
     52          return self._children
     53
     54 -    def fullIpList(self):
     55          "copied from IpNetwork"
     56          if (self.netmask == 32): return [self.id]
     57          ipnumb = numbip(self.id)
     58          maxip = math.pow(2, 32 - self.netmask)
     59          start = int(ipnumb + 1)
     60          end = int(ipnumb + maxip - 1)
     61          return map(strip, range(start,end))
     62
     63 -    def getNetworkName(self):
     64          return "%s/%d" % (self.id, self.netmask)
     65
     66  pb.setUnjellyableForClass(IpNetProxy, IpNetProxy)
     67
     68 -class DiscoverService(ModelerService):
     69
     70      @translateError
     71 -    def remote_getNetworks(self, net, includeSubNets):
     72          "Get network objects to scan networks should be in CIDR form 1.1.1.0/24"
     73          netObj = self.dmd.Networks.getNetworkRoot().findNet(net)
     74          if not netObj:
     75              return None
     76          nets = [netObj]
     77          if includeSubNets:
     78              nets += netObj.getSubNetworks()
     79          return map(IpNetProxy, nets)
     80
     81
     82      @translateError
     83 -    def remote_pingStatus(self, net, goodips, badips, resetPtr, addInactive):
     84          "Create objects based on ping results"
     85          net = self.dmd.Networks.getNetworkRoot().findNet(net.id, net.netmask)
     86          pingthresh = getattr(net, "zPingFailThresh", DEFAULT_PING_THRESH)
     87          ips = []
     88          for ip in goodips:
     89              ipobj = net.createIp(ip, net.netmask)
     90              if resetPtr:
     91                  ipobj.setPtrName()
     92              if not ipobj.device():
     93                  ips.append(ip)
     94              if ipobj.getStatus(Status_Ping) > 0:
     95                  self.sendIpStatusEvent(ipobj, sev=0)
     96          for ip in badips:
     97              ipobj = self.dmd.Networks.getNetworkRoot().findIp(ip)
     98              if not ipobj and addInactive:
     99                  ipobj = net.createIp(ip, net.netmask)
    100              if ipobj:
    101                  if resetPtr:
    102                      ipobj.setPtrName()
    103                  elif ipobj.getStatus(Status_Ping) > pingthresh:
    104                      net.ipaddresses.removeRelation(ipobj)
    105                  if ipobj:
    106                      self.sendIpStatusEvent(ipobj)
    107          transaction.commit()
    108          return ips
    109
    110
    111 -    def sendIpStatusEvent(self, ipobj, sev=2):
    112          """Send an ip down event.  These are used to cleanup unused ips.
    113          """
    114          ip = ipobj.id
    115          dev = ipobj.device()
    116          if sev == 0:
    117              msg = "ip %s is up" % ip
    118          else:
    119              msg = "ip %s is down" % ip
    120          if dev:
    121              devname = dev.id
    122              comp = ipobj.interface().id
    123          else:
    124              devname = comp = ip
    125          self.sendEvent(dict(device=devname, ipAddress=ip, eventKey=ip,
    126              component=comp, eventClass=Status_Ping, summary=msg, severity=sev,
    127              agent="Discover"))
    128
    129
    130      @translateError
    131 -    def remote_createDevice(self, ip, force=False, **kw):
    132          """Create a device.
    133
    134          @param ip: The manageIp of the device
    135          @param kw: The args to manage_createDevice.
    136          """
    137          from Products.ZenModel.Device import getNetworkRoot
    138          try:
    139              netroot = getNetworkRoot(self.dmd,
    140                  kw.get('performanceMonitor', 'localhost'))
    141              netobj = netroot.getNet(ip)
    142              netmask = 24
    143              if netobj is not None:
    144                  netmask = netobj.netmask
    145              else:
    146                  defaultNetmasks = getattr(netroot, 'zDefaultNetworkTree', [])
    147                  if defaultNetmasks:
    148                      netmask = defaultNetmasks[0]
    149              netroot.createIp(ip, netmask)
    150              autoDiscover = getattr(netobj, 'zAutoDiscover', True)
    151              # If we're not supposed to discover this IP, return None
    152              if not force and not autoDiscover:
    153                  return None, False
    154              kw['manageIp'] = ip
    155              dev = manage_createDevice(self.dmd, **kw)
    156          except DeviceExistsError, e:
    157              # Update device with latest info from zendisc
    158              e.dev.setManageIp(kw['manageIp'])
    159              # only overwrite title if it has not been set
    160              if e.dev.title is None or len(e.dev.title) <= 0 or \
    161                 re.match('^(0*([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}0*([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5]){1}$', e.dev.title):
    162                  e.dev.setTitle(kw['deviceName'])
    163              for key in ('manageIp', 'deviceName', 'devicePath',
    164                          'discoverProto'):
    165                  del kw[key]
    166              # use updateDevice so we don't clobber existing device properties.
    167              e.dev.updateDevice(**kw)
    168              # Make and return a device proxy
    169              return self.createDeviceProxy(e.dev), False
    170          except Exception, ex:
    171              log.exception("IP address %s (kw = %s) encountered error", ip, kw)
    172              raise pb.CopyableFailure(ex)
    173          transaction.commit()
    174          return self.createDeviceProxy(dev), True
    175
    176      @translateError
    177 -    def remote_getJobProperties(self, jobid):
    178          jobstatus = self.dmd.JobManager.getJob(jobid)
    179          if jobstatus:
    180              return JobStatusProxy(jobstatus)
    181
    182      @translateError
    183 -    def remote_succeedDiscovery(self, id):
    184          dev = self.dmd.Devices.findDeviceByIdOrIp(id)
    185          if dev:
    186              dev._temp_device = False
    187          transaction.commit()
    188          return True
    189
    190      @translateError
    191 -    def remote_followNextHopIps(self, device):
    192          """
    193          Return the ips that the device's indirect routes point to
    194          which aren't currently connected to devices.
    195          """
    196          dev = self.getPerformanceMonitor().findDevice(device)
    197          ips = []
    198          for r in dev.os.routes():
    199              ipobj = r.nexthop()
    200              if ipobj: ips.append(ipobj.id)
    201          return ips
    202
    203
    204      @translateError
    205 -    def remote_getSubNetworks(self):
    206          "Fetch proxies for all the networks"
    207          return map(IpNetProxy,
    208                  self.dmd.Networks.getNetworkRoot().getSubNetworks())
    209
    210
    211      @translateError
    212 -    def remote_getSnmpConfig(self, devicePath):
    213          "Get the snmp configuration defaults for scanning a device"
    214          devroot = self.dmd.Devices.createOrganizer(devicePath)
    215          return (devroot.zSnmpCommunities,
    216                  devroot.zSnmpPort,
    217                  devroot.zSnmpVer,
    218                  devroot.zSnmpTimeout,
    219                  devroot.zSnmpTries)
    220
    221
    222      @translateError
    223 -    def remote_moveDevice(self, dev, path):
    224          self.dmd.Devices.moveDevices(path, [dev])
    225          transaction.commit()
    226
    227      @translateError
    228 -    def remote_getDefaultNetworks(self):
    229          monitor = self.dmd.Monitors.Performance._getOb(self.instance)
    230          return [net for net in monitor.discoveryNetworks]
    231