Package Products :: Package ZenModel :: Module IpInterface |
[hide private]
[frames] | no frames]

# Source Code for Module Products.ZenModel.IpInterface

      1  ###########################################################################
      2  #
      3  # This program is part of Zenoss Core, an open source monitoring platform.
      4  # Copyright (C) 2007, 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  __doc__="""IpInterface
     15
     16  IpInterface is a collection of devices and subsystems that make
     17  up a business function
     18  """
     19
     20  import re
     21  import copy
     22  import logging
     23  log = logging.getLogger("zen.IpInterface")
     24
     25  from Globals import DTMLFile
     26  from Globals import InitializeClass
     27  from Acquisition import aq_base
     28  from App.Dialogs import MessageDialog
     29  from AccessControl import ClassSecurityInfo
     30  from zope.event import notify
     31  from zope.container.contained import ObjectMovedEvent
     32
     33  from Products.ZenRelations.RelSchema import *
     34
     35  from Products.ZenUtils.Utils import localIpCheck, localInterfaceCheck
     36  from Products.ZenUtils.IpUtil import *
     37
     38  from ConfmonPropManager import ConfmonPropManager
     39  from OSComponent import OSComponent
     40  from Products.ZenModel.Exceptions import *
     41  from Products.ZenModel.Linkable import Layer2Linkable
     42
     43  from Products.ZenModel.ZenossSecurity import *
     44
     45 -def manage_addIpInterface(context, newId, userCreated, REQUEST = None):
     46      """
     47      Make a device via the ZMI
     48      """
     49      d = IpInterface(newId)
     50      context._setObject(newId, d)
     51      d = context._getOb(newId)
     52      d.interfaceName = newId
     53      if userCreated: d.setUserCreateFlag()
     54      if REQUEST is not None:
     55          REQUEST['RESPONSE'].redirect(context.absolute_url()
     56                                       +'/manage_main')
     57
     58  addIpInterface = DTMLFile('dtml/addIpInterface',globals())
     59
     60
     61 -class IpInterface(OSComponent, Layer2Linkable):
     62      """
     63      IpInterface object
     64      """
     65
     66      portal_type = meta_type = 'IpInterface'
     67
     68      manage_editIpInterfaceForm = DTMLFile('dtml/manageEditIpInterface',
     69                                                          globals())
     70
     71      # catalog to find interfaces that should be pinged
     72      # indexes are id and description
     73      #default_catalog = 'interfaceSearch'
     74
     75      ifindex = '0'
     76      interfaceName = ''
     77      macaddress = ""
     78      type = ""
     79      description = ""
     80      mtu = 0
     81      speed = 0
     82      adminStatus = 0
     83      operStatus = 0
     84      duplex = 0
     85      _ipAddresses =  []
     86
     87
     88      _properties = OSComponent._properties + (
     89          {'id':'ips', 'type':'lines', 'mode':'w', 'setter':'setIpAddresses'},
     90          {'id':'interfaceName', 'type':'string', 'mode':'w'},
     91          {'id':'ifindex', 'type':'string', 'mode':'w'},
     92          {'id':'macaddress', 'type':'string', 'mode':'w'},
     93          {'id':'type', 'type':'string', 'mode':'w'},
     94          {'id':'description', 'type':'string', 'mode':'w'},
     95          {'id':'mtu', 'type':'int', 'mode':'w'},
     96          {'id':'speed', 'type':'long', 'mode':'w'},
     97          {'id':'adminStatus', 'type':'int', 'mode':'w'},
     98          {'id':'operStatus', 'type':'int', 'mode':'w'},
     99          {'id':'duplex', 'type':'int', 'mode':'w'},
    100          )
    101
    102      _relations = OSComponent._relations + (
    103          ("os", ToOne(ToManyCont,"Products.ZenModel.OperatingSystem","interfaces")),
    104          ("ipaddresses", ToMany(ToOne,"Products.ZenModel.IpAddress","interface")),
    105          ("iproutes", ToMany(ToOne,"Products.ZenModel.IpRouteEntry","interface")),
    106          )
    107
    108      zNoPropertiesCopy = ('ips','macaddress')
    109
    110      localipcheck = re.compile(r'^127.|^0.|^::1$|^fe80:').search
    111      localintcheck = re.compile(r'^lo0').search
    112
    113      defaultIgnoreTypes = ('Other', 'softwareLoopback', 'CATV MAC Layer')
    114
    115      factory_type_information = (
    116          {
    117              'id'             : 'IpInterface',
    118              'meta_type'      : 'IpInterface',
    119              'description'    : """Arbitrary device grouping class""",
    120              'icon'           : 'IpInterface_icon.gif',
    121              'product'        : 'ZenModel',
    122              'factory'        : 'manage_addIpInterface',
    123              'immediate_view' : 'viewIpInterface',
    124              'actions'        :
    125              (
    126                  { 'id'            : 'status'
    127                  , 'name'          : 'Status'
    128                  , 'action'        : 'viewIpInterface'
    129                  , 'permissions'   : (ZEN_VIEW,)
    130                  },
    131                  { 'id'            : 'events'
    132                  , 'name'          : 'Events'
    133                  , 'action'        : 'viewEvents'
    134                  , 'permissions'   : (ZEN_VIEW, )
    135                  },
    136                  { 'id'            : 'perfConf'
    137                  , 'name'          : 'Template'
    138                  , 'action'        : 'objTemplates'
    139                  , 'permissions'   : ("Change Device", )
    140                  },
    141              )
    142            },
    143          )
    144
    145      security = ClassSecurityInfo()
    146
    147 -    def __init__(self, id, title = None):
    148          """
    149          Init OSComponent and set _ipAddresses to an empty list.
    150          """
    151          OSComponent.__init__(self, id, title)
    152          self._ipAddresses = []
    153
    154
    155      security.declareProtected('View', 'viewName')
    156 -    def viewName(self):
    157          """
    158          Use the unmagled interface name for display
    159          """
    160          return self.interfaceName.rstrip('\x00') #Bogus fix for MS names
    161      name = primarySortKey = viewName
    162
    163 -    def _setPropValue(self, id, value):
    164          """
    165          Override from PerpertyManager to handle checks and ip creation
    166          """
    167          self._wrapperCheck(value)
    168          if id == 'ips':
    169              self.setIpAddresses(value)
    170          else:
    171              setattr(self,id,value)
    172              if id == 'macaddress':
    173                  self.index_object()
    174
    175 -    def index_object(self, idxs=None):
    176          """
    177          Override the default so that links are indexed.
    178          """
    179          super(IpInterface, self).index_object(idxs)
    180          self.index_links()
    181          # index our ip addresses if necessary
    182          for ip in self.ipaddresses():
    183              ip.index_object()
    184
    185 -    def unindex_object(self):
    186          """
    187          Override the default so that links are unindexed.
    188          """
    189          self.unindex_links()
    190          super(IpInterface, self).unindex_object()
    191          # index our ip addresses if necessary
    192          for ip in self.ipaddresses():
    193              ip.index_object()
    194
    195 -    def manage_deleteComponent(self, REQUEST=None):
    196          """
    197          Reindexes all the ip addresses on this interface
    198          after it has been deleted
    199          """
    200          ips = self.ipaddresses()
    201          super(IpInterface, self).manage_deleteComponent(REQUEST)
    202          for ip in ips:
    203              ip.primaryAq().index_object()
    204
    205 -    def manage_editProperties(self, REQUEST):
    206          """
    207          Override from propertiyManager so we can trap errors
    208          """
    209          try:
    210              return ConfmonPropManager.manage_editProperties(self, REQUEST)
    211          except IpAddressError, e:
    212              return   MessageDialog(
    213                  title = "Input Error",
    214                  message = e.args[0],
    215                  action = "manage_main")
    216
    217
    218 -    def __getattr__(self, name):
    219          """
    220          Allow access to ipAddresses via the ips attribute
    221          """
    222          if name == 'ips':
    223              return self.getIpAddresses()
    224          else:
    225              raise AttributeError( name )
    226
    227
    228 -    def _prepIp(self, ip, netmask=24):
    229          """
    230          Split ips in the format 1.1.1.1/24 into ip and netmask.
    231          Default netmask is 24.
    232          """
    233          iparray = ip.split("/")
    234          if len(iparray) > 1:
    235              ip = iparray[0]
    236              checkip(ip)
    237              netmask = maskToBits(iparray[1])
    238          return ip, netmask
    239
    240
    241 -    def addIpAddress(self, ip, netmask=24):
    242          """
    243          Add an ip to the ipaddresses relationship on this interface.
    244          """
    245          networks = self.device().getNetworkRoot()
    246          ip, netmask = self._prepIp(ip, netmask)
    247          #see if ip exists already and link it to interface
    248          ipobj = networks.findIp(ip)
    249          if ipobj:
    250              dev = ipobj.device()
    251              if dev and dev != self.device():
    252                  log.warn("Adding IP Address %s to %s found it on device %s",
    253                           ip, self.getId(), dev.getId())
    254              self.ipaddresses.addRelation(ipobj)
    255          #never seen this ip make a new one in correct subnet
    256          else:
    257              ipobj = networks.createIp(ip, netmask)
    258              self.ipaddresses.addRelation(ipobj)
    259          ipobj.index_object()
    260          os = self.os()
    261          notify(ObjectMovedEvent(self, os, self.id, os, self.id))
    262
    263
    264
    265 -    def addLocalIpAddress(self, ip, netmask=24):
    266          """
    267          Add a locally stored ip. Ips like 127./8 are maintained locally.
    268          """
    269          (ip, netmask) = self._prepIp(ip, netmask)
    270          ip = ip + '/' + str(netmask)
    271          if not self._ipAddresses: self._ipAddresses = []
    272          if not ip in self._ipAddresses:
    273              self._ipAddresses = self._ipAddresses + [ip,]
    274
    275
    276 -    def clearIps(self, ips):
    277          """
    278          If no IPs are sent remove all in the relation
    279          """
    280          if not ips:
    281              self.removeRelation('ipaddresses')
    282              return True
    283
    284
    285 -    def setIpAddresses(self, ips):
    286          """
    287          Set a list of ipaddresses in the form 1.1.1.1/24 on to this
    288          interface. If networks for the ips don't exist they will be created.
    289          """
    290          if isinstance(ips, basestring): ips = [ips,]
    291          if self.clearIps(ips): return
    292
    293          ipids = self.ipaddresses.objectIdsAll()
    294          localips = copy.copy(self._ipAddresses)
    295          for ip in ips:
    296              if localIpCheck(self, ip) or localInterfaceCheck(self, self.id):
    297                  if not ip in localips:
    298                      self.addLocalIpAddress(ip)
    299                  else:
    300                      localips.remove(ip)
    301              else:
    302                  # do this funky filtering because the id we have
    303                  # is a primary id /zport/dmd/Newtowrks... etc
    304                  # and we are looking for just the IP part
    305                  # we used the full id later when deleting the IPs
    306                  rawip = ipFromIpMask(ip)
    307                  ipmatch = filter(lambda x: x.find(rawip) > -1, ipids)
    308                  if not ipmatch:
    309                      self.addIpAddress(ip)
    310                  elif len(ipmatch) == 1:
    311                      ipids.remove(ipmatch[0])
    312
    313
    314          #delete ips that are no longer in use
    315          for ip in ipids:
    316              ipobj = self.ipaddresses._getOb(ip)
    317              self.removeRelation('ipaddresses', ipobj)
    318              ipobj.index_object()
    319          for ip in localips:
    320              self._ipAddresses.remove(ip)
    321
    322
    323 -    def removeIpAddress(self, ip):
    324          """
    325          Remove an ipaddress from this interface.
    326          """
    327          for ipobj in self.ipaddresses():
    328              if ipobj.id == ip:
    329                  self.ipaddresses.removeRelation(ipobj)
    330                  ipobj.index_object()
    331                  return
    332
    333
    334 -    def getIp(self):
    335          """
    336          Return the first ip for this interface in the form: 1.1.1.1.
    337          """
    338          if self.ipaddresses.countObjects():
    339              return self.ipaddresses()[0].getIp()
    340          elif len(self._ipAddresses):
    341              return self._ipAddresses[0].split('/')[0]
    342
    343
    344 -    def getIpSortKey(self):
    345          """
    346          Return the IP address as an integter for sorting purposes.
    347          """
    348          if self.ipaddresses.countObjects():
    349              return self.ipaddresses()[0].primarySortKey()
    350          elif len(self._ipAddresses):
    351              return numbip(self._ipAddresses[0].split('/')[0])
    352
    353
    354 -    def getIpAddress(self):
    355          """
    356          Return the first IP address with its netmask ie: 1.1.1.1/24.
    357          """
    358          if self.ipaddresses.countObjects():
    359              return self.ipaddresses()[0].getIpAddress()
    360          elif len(self._ipAddresses):
    361              return self._ipAddresses[0]
    362
    363
    364 -    def getIpAddressObj(self):
    365          """
    366          Return the first real IP address object or None if none are found.
    367          """
    368          if len(self.ipaddresses()):
    369              return self.ipaddresses()[0]
    370
    371
    372 -    def getIpAddressObjs(self):
    373          """
    374          Return a list of the ip objects on this interface.
    375          """
    376          retval=[]
    377          for ip in self.ipaddresses.objectValuesAll():
    378              retval.append(ip)
    379          for ip in self._ipAddresses:
    380              retval.append(ip)
    381          return retval
    382
    383
    384 -    def getIpAddresses(self):
    385          """
    386          Return list of ip addresses as strings in the form 1.1.1.1/24.
    387          """
    388          return map(str, self.getIpAddressObjs())
    389
    390
    391 -    def getNetwork(self):
    392          """
    393          Return the network for the first ip on this interface.
    394          """
    395          if self.ipaddresses.countObjects():
    396              return self.ipaddresses()[0].network()
    397
    398
    399 -    def getNetworkName(self):
    400          """
    401          Return the network name for the first ip on this interface.
    402          """
    403          net = self.getNetwork()
    404          if net: return net.getNetworkName()
    405          return ""
    406
    407
    408 -    def getNetworkLink(self):
    409          """
    410          Return the network link for the first ip on this interface.
    411          """
    412          if len(self.ipaddresses()):
    413              addr = self.ipaddresses.objectValuesAll()[0]
    414              if addr:
    415                  if hasattr(aq_base(addr), 'network'):
    416                      if self.checkRemotePerm("View", addr.network):
    417                          return addr.network.getPrimaryLink()
    418                      else:
    419                          return addr.network.getRelatedId()
    420          else:
    421              return ""
    422
    423
    424 -    def getNetworkLinks(self):
    425          """
    426          Return a list of network links for each ip in this interface.
    427          """
    428          addrs = self.ipaddresses() + self._ipAddresses
    429          if addrs:
    430              links = []
    431              for addr in addrs:
    432                  if hasattr(aq_base(addr), 'network'):
    433                      if self.checkRemotePerm('View', addr.network()):
    434                          links.append(addr.network.getPrimaryLink())
    435                      else:
    436                          links.append(addr.network.getRelatedId())
    437                  else:
    438                      links.append("")
    439              return "<br/>".join(links)
    440          else:
    441              return ""
    442
    443
    444      security.declareProtected('View', 'getInterfaceName')
    445 -    def getInterfaceName(self):
    446          """
    447          Return the name of this interface.
    448          """
    449          if self.interfaceName: return self.interfaceName
    450          elif self.viewName(): return self.viewName()
    451          else: return "None"
    452
    453
    454      security.declareProtected('View', 'getInterfaceMacaddress')
    455 -    def getInterfaceMacaddress(self):
    456          """
    457          Return the mac address of this interface.
    458          """
    459          return self.macaddress
    460
    461
    462 -    def getRRDTemplateName(self):
    463          """
    464          Return the interface type as the target type name.
    465          """
    466          return self.prepId(self.type or "Unknown")
    467
    468
    469 -    def getRRDTemplates(self):
    470          """
    471          Return a list containing the appropriate RRDTemplate for this
    472          IpInterface. If none is found then the list will be empty.
    473
    474          Order of preference if the interface supports 64bit counters.
    475              1. <type>_64
    476              2. ethernetCsmacd_64
    477              3. <type>
    478              4. ethernetCsmacd
    479
    480          Order of preference if the interface doesn't support 64bit counters.
    481              1. <type>
    482              2. ethernetCsmacd
    483          """
    484          templateName = self.getRRDTemplateName()
    485
    486          order = ['ethernetCsmacd']
    487          if templateName.endswith('_64'):
    488              order.insert(0, 'ethernetCsmacd_64')
    489              if templateName not in order:
    490                  order.insert(0, templateName)
    491                  order.insert(2, templateName[:-3])
    492          else:
    493              if templateName not in order:
    494                  order.insert(0, templateName)
    495
    496          for name in order:
    497              template = self.getRRDTemplateByName(name)
    498              if template:
    499                  return [template]
    500
    501          return []
    502
    503
    504 -    def snmpIgnore(self):
    505          """
    506          Ignore interface that are administratively down.
    507          """
    508          # This must be based off the modeled admin status or zenhub could
    509          # lock itself up while building configurations.
    510          return self.adminStatus > 1 or self.monitor == False
    511
    512
    513 -    def getAdminStatus(self):
    514          """
    515          Get the current administrative state of the interface. Prefer real-time
    516          value over modeled value.
    517          """
    518          s = self.cacheRRDValue('ifAdminStatus', None)
    519          if s is None: s = self.adminStatus
    520          return s
    521
    522
    523 -    def getAdminStatusString(self):
    524          """
    525          Return the current administrative state of the interface converted to
    526          its string version.
    527          """
    528          return {1: 'Up', 2: 'Down', 3: 'Testing'}.get(
    529              self.getAdminStatus(), 'Unknown')
    530
    531
    532 -    def getOperStatus(self):
    533          """
    534          Get the current operational state of the interface. Prefer real-time
    535          value over modeled value.
    536          """
    537          s = self.cacheRRDValue('ifOperStatus', None)
    538          if s is None: s = self.operStatus
    539          return s
    540
    541
    542 -    def getOperStatusString(self):
    543          """
    544          Return the current operational state of the interface converted to
    545          its string version.
    546          """
    547          return {
    548              1: 'Up', 2: 'Down', 3: 'Testing', 5: 'Dormant', 6: 'Not Present',
    549              7: 'Lower Layer Down'}.get(
    550                  self.getOperStatus(), 'Unknown')
    551
    552
    553 -    def getStatus(self, statClass=None):
    554          """
    555          Return the status number for this interface.
    556          """
    557          # Unknown status if we're not monitoring the interface.
    558          if self.snmpIgnore():
    559              return -1
    560
    561          return super(IpInterface, self).getStatus()
    562
    563
    564 -    def niceSpeed(self):
    565          """
    566          Return a string that expresses self.speed in reasonable units.
    567          """
    568          if not self.speed:
    569              return 'Unknown'
    570          speed = self.speed
    571          for unit in ('bps', 'Kbps', 'Mbps', 'Gbps'):
    572              if speed < 1000: break
    573              speed /= 1000.0
    574          return "%.3f%s" % (speed, unit)
    575
    576 -    def deviceId(self):
    577          """
    578          The device id, for indexing purposes.
    579          """
    580          d = self.device()
    581          if d: return d.getPrimaryId()
    582          else: return None
    583
    584 -    def interfaceId(self):
    585          """
    586          The interface id, for indexing purposes.
    587          """
    588          return self.getPrimaryId()
    589
    590 -    def lanId(self):
    591          """
    592          pass
    593          """
    594          return 'None'
    595
    596 -    def niceDuplex(self):
    597          """
    598          Return a string that expresses self.duplex into human readable format.
    599          """
    600
    601          if self.duplex == 2:
    602              return 'halfDuplex'
    603          elif self.duplex == 3:
    604              return 'fullDuplex'
    605          return 'unknown'
    606
    607  InitializeClass(IpInterface)
    608
    609 -def beforeDeleteIpInterface(ob, event):
    610      if (event.object==ob or event.object==ob.device() or
    611          getattr(event.object, "_operation", -1) < 1):
    612          ob.unindex_object()
    613