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