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 as published by
      8  # 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.app.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.').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                  { 'id'            : 'viewHistory'
    142                  , 'name'          : 'Modifications'
    143                  , 'action'        : 'viewHistory'
    144                  , 'permissions'   : (ZEN_VIEW_MODIFICATIONS,)
    145                  },
    146              )
    147            },
    148          )
    149
    150      security = ClassSecurityInfo()
    151
    152 -    def __init__(self, id, title = None):
    153          """
    154          Init OSComponent and set _ipAddresses to an empty list.
    155          """
    156          OSComponent.__init__(self, id, title)
    157          self._ipAddresses = []
    158
    159
    160      security.declareProtected('View', 'viewName')
    161 -    def viewName(self):
    162          """
    163          Use the unmagled interface name for display
    164          """
    165          return self.interfaceName.rstrip('\x00') #Bogus fix for MS names
    166      name = primarySortKey = viewName
    167
    168
    169 -    def _setPropValue(self, id, value):
    170          """
    171          Override from PerpertyManager to handle checks and ip creation
    172          """
    173          self._wrapperCheck(value)
    174          if id == 'ips':
    175              self.setIpAddresses(value)
    176          else:
    177              setattr(self,id,value)
    178              if id == 'macaddress':
    179                  self.index_object()
    180
    181
    182 -    def index_object(self):
    183          """
    184          Override the default so that links are indexed.
    185          """
    186          super(IpInterface, self).index_object()
    187          self.index_links()
    188
    189
    190 -    def unindex_object(self):
    191          """
    192          Override the default so that links are unindexed.
    193          """
    194          self.unindex_links()
    195          super(IpInterface, self).unindex_object()
    196
    197
    198 -    def manage_editProperties(self, REQUEST):
    199          """
    200          Override from propertiyManager so we can trap errors
    201          """
    202          try:
    203              return ConfmonPropManager.manage_editProperties(self, REQUEST)
    204          except IpAddressError, e:
    205              return   MessageDialog(
    206                  title = "Input Error",
    207                  message = e.args[0],
    208                  action = "manage_main")
    209
    210
    211 -    def __getattr__(self, name):
    212          """
    213          Allow access to ipAddresses via the ips attribute
    214          """
    215          if name == 'ips':
    216              return self.getIpAddresses()
    217          else:
    218              raise AttributeError( name )
    219
    220
    221 -    def _prepIp(self, ip, netmask=24):
    222          """
    223          Split ips in the format 1.1.1.1/24 into ip and netmask.
    224          Default netmask is 24.
    225          """
    226          iparray = ip.split("/")
    227          if len(iparray) > 1:
    228              ip = iparray[0]
    229              checkip(ip)
    230              netmask = maskToBits(iparray[1])
    231          return ip, netmask
    232
    233
    234 -    def addIpAddress(self, ip, netmask=24):
    235          """
    236          Add an ip to the ipaddresses relationship on this interface.
    237          """
    238          networks = self.device().getNetworkRoot()
    239          ip, netmask = self._prepIp(ip, netmask)
    240          #see if ip exists already and link it to interface
    241          ipobj = networks.findIp(ip)
    242          if ipobj:
    243              dev = ipobj.device()
    244              if dev and dev != self.device():
    245                  log.warn("Adding IP Address %s to %s found it on device %s",
    246                           ip, self.getId(), dev.getId())
    247              self.ipaddresses.addRelation(ipobj)
    248          #never seen this ip make a new one in correct subnet
    249          else:
    250              ipobj = networks.createIp(ip, netmask)
    251              self.ipaddresses.addRelation(ipobj)
    252          ipobj.index_links()
    253          os = self.os()
    254          notify(ObjectMovedEvent(self, os, self.id, os, self.id))
    255
    256
    257
    258 -    def addLocalIpAddress(self, ip, netmask=24):
    259          """
    260          Add a locally stored ip. Ips like 127./8 are maintained locally.
    261          """
    262          (ip, netmask) = self._prepIp(ip, netmask)
    263          ip = ip + '/' + str(netmask)
    264          if not self._ipAddresses: self._ipAddresses = []
    265          if not ip in self._ipAddresses:
    266              self._ipAddresses = self._ipAddresses + [ip,]
    267
    268
    269 -    def clearIps(self, ips):
    270          """
    271          If no IPs are sent remove all in the relation
    272          """
    273          if not ips:
    274              self.removeRelation('ipaddresses')
    275              return True
    276
    277
    278 -    def setIpAddresses(self, ips):
    279          """
    280          Set a list of ipaddresses in the form 1.1.1.1/24 on to this
    281          interface. If networks for the ips don't exist they will be created.
    282          """
    283          if type(ips) == type(''): ips = [ips,]
    284          if self.clearIps(ips): return
    285
    286          ipids = self.ipaddresses.objectIdsAll()
    287          localips = copy.copy(self._ipAddresses)
    288          for ip in ips:
    289              if localIpCheck(self, ip) or localInterfaceCheck(self, self.id):
    290                  if not ip in localips:
    291                      self.addLocalIpAddress(ip)
    292                  else:
    293                      localips.remove(ip)
    294              else:
    295                  # do this funky filtering because the id we have
    296                  # is a primary id /zport/dmd/Newtowrks... etc
    297                  # and we are looking for just the IP part
    298                  # we used the full id later when deleting the IPs
    299                  rawip = ipFromIpMask(ip)
    300                  ipmatch = filter(lambda x: x.find(rawip) > -1, ipids)
    301                  if not ipmatch:
    302                      self.addIpAddress(ip)
    303                  elif len(ipmatch) == 1:
    304                      ipids.remove(ipmatch[0])
    305
    306
    307          #delete ips that are no longer in use
    308          for ip in ipids:
    309              ipobj = self.ipaddresses._getOb(ip)
    310              self.removeRelation('ipaddresses', ipobj)
    311              ipobj.index_links()
    312          for ip in localips:
    313              self._ipAddresses.remove(ip)
    314
    315
    316 -    def removeIpAddress(self, ip):
    317          """
    318          Remove an ipaddress from this interface.
    319          """
    320          for ipobj in self.ipaddresses():
    321              if ipobj.id == ip:
    322                  self.ipaddresses.removeRelation(ipobj)
    323                  ipobj.index_links()
    324                  return
    325
    326
    327 -    def getIp(self):
    328          """
    329          Return the first ip for this interface in the form: 1.1.1.1.
    330          """
    331          if self.ipaddresses.countObjects():
    332              return self.ipaddresses()[0].getIp()
    333          elif len(self._ipAddresses):
    334              return self._ipAddresses[0].split('/')[0]
    335
    336
    337 -    def getIpSortKey(self):
    338          """
    339          Return the ipaddress as a 32bit integter for sorting purposes.
    340          """
    341          if self.ipaddresses.countObjects():
    342              return self.ipaddresses()[0].primarySortKey()
    343          elif len(self._ipAddresses):
    344              return numbip(self._ipAddresses[0].split('/')[0])
    345
    346
    347 -    def getIpAddress(self):
    348          """
    349          Return the first ipaddress with its netmask ie: 1.1.1.1/24.
    350          """
    351          if self.ipaddresses.countObjects():
    352              return self.ipaddresses()[0].getIpAddress()
    353          elif len(self._ipAddresses):
    354              return self._ipAddresses[0]
    355
    356
    357 -    def getIpAddressObj(self):
    358          """
    359          Return the first real ipaddress object or None if none are found.
    360          """
    361          if len(self.ipaddresses()):
    362              return self.ipaddresses()[0]
    363
    364
    365 -    def getIpAddressObjs(self):
    366          """
    367          Return a list of the ip objects on this interface.
    368          """
    369          retval=[]
    370          for ip in self.ipaddresses.objectValuesAll():
    371              retval.append(ip)
    372          for ip in self._ipAddresses:
    373              retval.append(ip)
    374          return retval
    375
    376
    377 -    def getIpAddresses(self):
    378          """
    379          Return list of ip addresses as strings in the form 1.1.1.1/24.
    380          """
    381          return map(str, self.getIpAddressObjs())
    382
    383
    384 -    def getNetwork(self):
    385          """
    386          Return the network for the first ip on this interface.
    387          """
    388          if self.ipaddresses.countObjects():
    389              return self.ipaddresses()[0].network()
    390
    391
    392 -    def getNetworkName(self):
    393          """
    394          Return the network name for the first ip on this interface.
    395          """
    396          net = self.getNetwork()
    397          if net: return net.getNetworkName()
    398          return ""
    399
    400
    401 -    def getNetworkLink(self):
    402          """
    403          Return the network link for the first ip on this interface.
    404          """
    405          if len(self.ipaddresses()):
    406              addr = self.ipaddresses.objectValuesAll()[0]
    407              if addr:
    408                  if hasattr(aq_base(addr), 'network'):
    409                      if self.checkRemotePerm("View", addr.network):
    410                          return addr.network.getPrimaryLink()
    411                      else:
    412                          return addr.network.getRelatedId()
    413          else:
    414              return ""
    415
    416
    417 -    def getNetworkLinks(self):
    418          """
    419          Return a list of network links for each ip in this interface.
    420          """
    421          addrs = self.ipaddresses() + self._ipAddresses
    422          if addrs:
    423              links = []
    424              for addr in addrs:
    425                  if hasattr(aq_base(addr), 'network'):
    426                      if self.checkRemotePerm('View', addr.network()):
    427                          links.append(addr.network.getPrimaryLink())
    428                      else:
    429                          links.append(addr.network.getRelatedId())
    430                  else:
    431                      links.append("")
    432              return "<br/>".join(links)
    433          else:
    434              return ""
    435
    436
    437      security.declareProtected('View', 'getInterfaceName')
    438 -    def getInterfaceName(self):
    439          """
    440          Return the name of this interface.
    441          """
    442          if self.interfaceName: return self.interfaceName
    443          elif self.viewName(): return self.viewName()
    444          else: return "None"
    445
    446
    447      security.declareProtected('View', 'getInterfaceMacaddress')
    448 -    def getInterfaceMacaddress(self):
    449          """
    450          Return the mac address of this interface.
    451          """
    452          return self.macaddress
    453
    454
    455 -    def getRRDTemplateName(self):
    456          """
    457          Return the interface type as the target type name.
    458          """
    459          return self.prepId(self.type or "Unknown")
    460
    461
    462 -    def getRRDTemplates(self):
    463          """
    464          Return a list containing the appropriate RRDTemplate for this
    465          IpInterface. If none is found then the list will be empty.
    466
    467          Order of preference if the interface supports 64bit counters.
    468              1. <type>_64
    469              2. ethernetCsmacd_64
    470              3. <type>
    471              4. ethernetCsmacd
    472
    473          Order of preference if the interface doesn't support 64bit counters.
    474              1. <type>
    475              2. ethernetCsmacd
    476          """
    477          templateName = self.getRRDTemplateName()
    478
    479          order = ['ethernetCsmacd']
    480          if templateName.endswith('_64'):
    481              order.insert(0, 'ethernetCsmacd_64')
    482              if templateName not in order:
    483                  order.insert(0, templateName)
    484                  order.insert(2, templateName[:-3])
    485          else:
    486              if templateName not in order:
    487                  order.insert(0, templateName)
    488
    489          for name in order:
    490              template = self.getRRDTemplateByName(name)
    491              if template:
    492                  return [template]
    493
    494          return []
    495
    496
    497 -    def snmpIgnore(self):
    498          """
    499          Ignore interface that are administratively down.
    500          """
    501          # This must be based off the modeled admin status or zenhub could
    502          # lock itself up while building configurations.
    503          return self.adminStatus > 1 or self.monitor == False
    504
    505
    506 -    def getAdminStatus(self):
    507          """
    508          Get the current administrative state of the interface. Prefer real-time
    509          value over modeled value.
    510          """
    511          s = self.cacheRRDValue('ifAdminStatus', None)
    512          if s is None: s = self.adminStatus
    513          return s
    514
    515
    516 -    def getOperStatus(self):
    517          """
    518          Get the current operational state of the interface. Prefer real-time
    519          value over modeled value.
    520          """
    521          s = self.cacheRRDValue('ifOperStatus', None)
    522          if s is None: s = self.operStatus
    523          return s
    524
    525
    526 -    def getStatus(self, statClass=None):
    527          """
    528          Return the status number for this interface.
    529          """
    530          # Unknown status if we're not monitoring the interface.
    531          if self.snmpIgnore():
    532              return -1
    533
    534          return super(IpInterface, self).getStatus()
    535
    536
    537 -    def niceSpeed(self):
    538          """
    539          Return a string that expresses self.speed in reasonable units.
    540          """
    541          if not self.speed:
    542              return 'Unknown'
    543          speed = self.speed
    544          for unit in ('bps', 'Kbps', 'Mbps', 'Gbps'):
    545              if speed < 1000: break
    546              speed /= 1000.0
    547          return "%.3f%s" % (speed, unit)
    548
    549 -    def deviceId(self):
    550          """
    551          The device id, for indexing purposes.
    552          """
    553          d = self.device()
    554          if d: return d.getPrimaryId()
    555          else: return None
    556
    557 -    def interfaceId(self):
    558          """
    559          The interface id, for indexing purposes.
    560          """
    561          return self.getPrimaryId()
    562
    563 -    def lanId(self):
    564          """
    565          pass
    566          """
    567          return 'None'
    568
    569 -    def niceDuplex(self):
    570          """
    571          Return a string that expresses self.duplex into human readable format.
    572          """
    573
    574          if self.duplex == 2:
    575              return 'halfDuplex'
    576          elif self.duplex == 3:
    577              return 'fullDuplex'
    578          return 'unknown'
    579
    580  InitializeClass(IpInterface)
    581
    582 -def beforeDeleteIpInterface(ob, event):
    583      if (event.object==ob or event.object==ob.device() or
    584          getattr(event.object, "_operation", -1) < 1):
    585          ob.unindex_object()
    586