def process(self, device, results, log):
        """Process SNMP information from this device"""
        log.info('Modeler %s processing data for device %s', self.name(),
                 device.id)
        getdata, tabledata = results
        log.debug("%s tabledata = %s", device.id, tabledata)
        fstable = tabledata.get("fsTableOid")
        if fstable is None:
            log.error("Unable to get data for %s from fsTableOid"
                      " -- skipping model" % device.id)
            return None

        skipfsnames = getattr(device, 'zFileSystemMapIgnoreNames', None)
        maps = []
        rm = self.relMap()
        for fs in fstable.values():
            if not self.checkColumns(fs, self.columns, log):
                continue

            totalBlocks = fs['totalBlocks']

            # This may now be a redundant check. Candidate for removal.
            #   http://dev.zenoss.org/trac/ticket/4556
            if totalBlocks < 0:
                fs['totalBlocks'] = unsigned(totalBlocks)

            # blockSize is not used by UCD mibs.
            # UCD mibs display size in kilobytes.
            # Value has been hardcoded as 1024 to convert to bytes.
            fs['blockSize'] = 1024
            size = fs['totalBlocks']

            # UCD-SNMP-MIB does not provide filesystem type info.
            # Only zFileSystemMapIgnoreNames is checked.
            if skipfsnames and re.search(skipfsnames, fs['mount']):
                log.info(
                    "Skipping %s as it matches zFileSystemMapIgnoreNames.",
                    fs['mount'])
                continue

            om = self.objectMap(fs)
            om.id = self.prepId(om.mount)
            rm.append(om)
        maps.append(rm)
        return maps
    def process(self, device, results, log):
        """Process SNMP information from this device"""
        log.info('Modeler %s processing data for device %s', self.name(), device.id)
        getdata, tabledata = results
        log.debug("%s tabledata = %s", device.id, tabledata)
        fstable = tabledata.get("fsTableOid")
        if fstable is None:
            log.error("Unable to get data for %s from fsTableOid"
                          " -- skipping model" % device.id)
            return None

        skipfsnames = getattr(device, 'zFileSystemMapIgnoreNames', None)
        maps = []
        rm = self.relMap()
        for fs in fstable.values():
            if not self.checkColumns(fs, self.columns, log):
                continue
            
            totalBlocks = fs['totalBlocks']

            # This may now be a redundant check. Candidate for removal.
            #   http://dev.zenoss.org/trac/ticket/4556
            if totalBlocks < 0:
                fs['totalBlocks'] = unsigned(totalBlocks)

            # blockSize is not used by UCD mibs.
            # UCD mibs display size in kilobytes.
            # Value has been hardcoded as 1024 to convert to bytes.
            fs['blockSize'] = 1024
            size = fs['totalBlocks']

            # UCD-SNMP-MIB does not provide filesystem type info.
            # Only zFileSystemMapIgnoreNames is checked.
            if skipfsnames and re.search(skipfsnames, fs['mount']):
                log.info("Skipping %s as it matches zFileSystemMapIgnoreNames.",
                    fs['mount'])
                continue
            
            om = self.objectMap(fs)
            om.id = self.prepId(om.mount)
            rm.append(om)
        maps.append(rm)
        return maps
class InterfaceMap(SnmpPlugin):
    """
    Map IPv4 and IPv6 network names and aliases to DMD 'interface' objects
    """
    order = 80
    compname = "os"
    relname = "interfaces"
    modname = "Products.ZenModel.IpInterface"
    deviceProperties = \
                SnmpPlugin.deviceProperties + ('zInterfaceMapIgnoreNames',
                                               'zInterfaceMapIgnoreTypes',
                                               'zInterfaceMapIgnoreDescriptions')

    # Interface related tables likely to be used in all subclasses.
    baseSnmpGetTableMaps = (
        GetTableMap(
            'iftable', '.1.3.6.1.2.1.2.2.1', {
                '.1': 'ifindex',
                '.2': 'id',
                '.3': 'type',
                '.4': 'mtu',
                '.5': 'speed',
                '.6': 'macaddress',
                '.7': 'adminStatus',
                '.8': 'operStatus'
            }),
        # ipAddrTable is the better way to get IP addresses
        GetTableMap('ipAddrTable', '.1.3.6.1.2.1.4.20.1', {
            '.1': 'ipAddress',
            '.2': 'ifindex',
            '.3': 'netmask'
        }),

        # IP-MIB::ipAddressIfIndex can give us IPv6 addresses.
        GetTableMap('ipAddressIfIndex', '.1.3.6.1.2.1.4.34.1.3.2', {
            '.16': 'ifindex',
        }),
        # Use the ipNetToMediaTable as a backup to the ipAddrTable
        GetTableMap('ipNetToMediaTable', '.1.3.6.1.2.1.4.22.1', {
            '.1': 'ifindex',
            '.3': 'ipaddress',
            '.4': 'iptype'
        }),
        # attempt to determine if the interface supports duplex mode
        GetTableMap('duplex', '.1.3.6.1.2.1.10.7.2.1', {'.19': 'duplex'}),
    )

    # Base interface tables, plus ones used locally.
    snmpGetTableMaps = baseSnmpGetTableMaps + (
        # Extended interface information.
        GetTableMap(
            'ifalias', '.1.3.6.1.2.1.31.1.1.1', {
                '.6': 'ifHCInOctets',
                '.7': 'ifHCInUcastPkts',
                '.15': 'highSpeed',
                '.18': 'description'
            }), )

    def process(self, device, results, log):
        """
        From SNMP info gathered from the device, convert them
        to interface objects.
        """
        getdata, tabledata = results
        log.info('Modeler %s processing data for device %s', self.name(),
                 device.id)
        log.debug("%s tabledata = %s", device.id, tabledata)
        rm = self.relMap()
        iptable = tabledata.get("ipAddrTable")
        sourceTable = 'ipAddrTable'
        if not iptable:
            iptable = tabledata.get("ipNetToMediaTable")
            if iptable:
                log.info(
                    "Unable to use ipAddrTable -- using ipNetToMediaTable instead"
                )
                sourceTable = 'ipNetToMediaTable'
            else:
                log.warn("Unable to get data for %s from either ipAddrTable or"
                         " ipNetToMediaTable" % device.id)
                iptable = dict()

        # Add in IPv6 info
        ipv6table = tabledata.get("ipAddressIfIndex")
        if ipv6table:
            iptable.update(ipv6table)

        iftable = tabledata.get("iftable")
        if iftable is None:
            log.error(
                "Unable to get data for %s for iftable -- skipping model" %
                device.id)
            return None

        ifalias = tabledata.get("ifalias", {})

        self.prepIfTable(log, iftable, ifalias)

        omtable = {}
        duplex = tabledata.get("duplex", {})
        for key, iface in iftable.items():
            if key in duplex:
                iftable[key]['duplex'] = duplex[key].get('duplex', 0)
            else:
                iftable[key]['duplex'] = 0

        for ip, row in iptable.items():
            #FIXME - not getting ifindex back from HP printer
            if 'ifindex' not in row:
                log.debug("IP entry for %s is missing ifindex" % ip)
                continue

            ip_parts = ip.split('.')
            # If the ipAddrTable key has five octets, that probably
            # means this is a classless subnet (that is, <256).  Usually,
            # the first 4 octets will be the ipAddress we care about.
            # Regardless, we will be using the ip address in the row
            # later anyway.

            try:
                if len(ip_parts) == 5 and sourceTable == 'ipAddrTable':
                    addr_type = IpUtil.IPV4_ADDR_TYPE
                    ip = IpUtil.bytesToCanonIp(ip_parts[:-1])

                # If we are using the ipNetToMediaTable, we use the
                # last 4 octets.
                elif len(ip_parts) == 5 and sourceTable == 'ipNetToMediaTable':
                    addr_type = IpUtil.IPV4_ADDR_TYPE
                    if row['iptype'] != 1:
                        log.debug("iptype (%s) is not 1 -- skipping" %
                                  (row['iptype']))
                        continue
                    ip = IpUtil.bytesToCanonIp(ip_parts[1:])
                    log.warn("Can't find netmask -- using /24")
                    row['netmask'] = '255.255.255.0'

                elif len(ip_parts) == 16:
                    addr_type = IpUtil.IPV6_ADDR_TYPE
                    ip = IpUtil.bytesToCanonIp(ip_parts)

            except Exception:
                log.warn("The %s address for ifindex %s is incorrect: %s",
                         addr_type, row['ifindex'], ip)
                continue

            strindex = str(row['ifindex'])
            if strindex not in omtable and strindex not in iftable:
                log.warn("Skipping %s as it points to missing ifindex %s",
                         row.get('ipAddress', ""), row.get('ifindex', ""))
                continue

            if strindex not in omtable:
                om = self.processInt(log, device, iftable[strindex])
                if not om:
                    continue
                rm.append(om)
                omtable[strindex] = om
                del iftable[strindex]
            elif strindex in omtable:
                om = omtable[strindex]
            else:
                log.warn("The IP %s points to missing ifindex %s -- skipping" %
                         (ip, strindex))
                continue

            if not hasattr(om, 'setIpAddresses'):
                om.setIpAddresses = []
            if 'ipAddress' in row:
                ip = row['ipAddress']
            if 'netmask' in row:
                ip = ip + "/" + str(self.maskToBits(row['netmask'].strip()))

            # Ignore IP addresses with a 0.0.0.0 netmask.
            if ip.endswith("/0"):
                log.warn("Ignoring IP address with 0.0.0.0 netmask: %s", ip)
            else:
                om.setIpAddresses.append(ip)

        for iface in iftable.values():
            om = self.processInt(log, device, iface)
            if om:
                rm.append(om)

        return rm

    def prepIfTable(self, log, iftable, ifalias):
        """
        Add interface alias (Cisco description) to iftable
        Sanity check speed
        """
        for ifidx, data in ifalias.items():
            log.debug("ifalias %s raw data = %s" % (ifidx, data))
            if ifidx not in iftable:
                log.debug("ifidx %s is not in iftable -- skipping" % (ifidx))
                continue

            iftable[ifidx]['description'] = data.get('description', '')

            # handle 10GB interfaces using IF-MIB::ifHighSpeed
            speed = iftable[ifidx].get('speed', 0)
            if speed == 4294967295L or speed == 1410065408 or speed < 0:
                try:
                    iftable[ifidx]['speed'] = data['highSpeed'] * 1e6
                except KeyError:
                    pass

            # Detect availability of the high-capacity counters
            if data.get('ifHCInOctets', None) is not None and \
                data.get('ifHCInUcastPkts', None) is not None:
                iftable[ifidx]['hcCounters'] = True

        for ifidx, data in iftable.items():
            try:
                data['speed'] = unsigned(data['speed'])
            except KeyError:
                pass
    def process(self, device, results, log):
        """Process SNMP information from this device"""
        log.info('Modeler %s processing data for device %s', self.name(), device.id)
        getdata, tabledata = results
        log.debug("%s tabledata = %s", device.id, tabledata)
        fstable = tabledata.get("fsTableOid")
        if fstable is None:
            log.error("Unable to get data for %s from fsTableOid"
                          " -- skipping model" % device.id)
            return None

        dskTable = tabledata.get("dskTable")

        hrFSEntry = tabledata.get("hrFSEntry", {})
        remoteMountMap = self._createRemoteMountMap(hrFSEntry)

        skipfsnames = getattr(device, 'zFileSystemMapIgnoreNames', None)
        skipfstypes = getattr(device, 'zFileSystemMapIgnoreTypes', None)
        maps = []
        rm = self.relMap()
        for fs in fstable.values():
            if not self.checkColumns(fs, self.columns, log):
                continue
            
            # Gentoo and openSUSE report "Virtual memory" as swap. This needs
            # to be ignored so we can pickup the real swap later in the table.
            if "virtual memory" in fs['mount'].lower():
                continue

            rmount = remoteMountMap.get(fs['snmpindex'])
            if rmount is not None and fs['mount'] != rmount:
                log.debug('Switching mount from %s to %s', fs['mount'], rmount)
                fs['storageDevice'] = rmount

            # Large file systems can report as an unsigned integer
            if fs['totalBlocks'] < 0:
                fs['totalBlocks'] = unsigned(totalBlocks)

            totalBlocks = fs['totalBlocks']
            size = long(fs['blockSize'] * totalBlocks)
            if size <= 0:
                log.info("Skipping %s. 0 total blocks.", fs['mount'])
                continue
            
            fs['type'] = self.typemap.get(fs['type'], "other")
            size = long(fs['blockSize'] * totalBlocks)
            
            # Handle file systems that need to be mapped into other parts of
            # the model such as total memory or total swap.
            if fs['type'] == "ram":
                maps.append(ObjectMap({"totalMemory": size}, compname="hw"))
            elif fs['type'] == "virtualMemory" or fs['mount'] == 'Swap':
                maps.append(ObjectMap({"totalSwap": size}, compname="os"))
            
            if skipfsnames and re.search(skipfsnames, fs['mount']):
                log.info("Skipping %s as it matches zFileSystemMapIgnoreNames.",
                    fs['mount'])
                continue
            
            if skipfstypes and fs['type'] in skipfstypes:
                log.info("Skipping %s (%s) as it matches zFileSystemMapIgnoreTypes.",
                    fs['mount'], fs['type'])
                continue

            fs["snmpindex_dct"] = {HRFileSystemMap.dskTableOid: self._getDskIndex(dskTable, fs["mount"])}

            om = self.objectMap(fs)
            om.id = self.prepId(om.mount)
            om.title = om.mount
            rm.append(om)
        maps.append(rm)

        # look for any map 'm' with m.compname == 'os' and m.totalSwap > 0
        if not any(getattr(m,'compname', None) == 'os' and 
                   getattr(m,'totalSwap', 0) > 0
                                    for m in maps):
            # if no value set for device.os.totalSwap, set totalSwap to 0 
            log.info("Swap space not detected for device %s, setting to 0", device.id)
            maps.append(ObjectMap({'totalSwap': 0}, compname="os"))

        return maps
Exemple #5
0
class AIXInterfaceMap(SnmpPlugin):

    order = 80
    maptype = "InterfaceMap"
    compname = "os"
    relname = "interfaces"
    modname = "Products.ZenModel.IpInterface"
    deviceProperties = \
                SnmpPlugin.deviceProperties + ('zInterfaceMapIgnoreNames',
                                               'zInterfaceMapIgnoreTypes')

    snmpGetTableMaps = (
        # If table
        GetTableMap(
            'iftable', '.1.3.6.1.2.1.2.2.1', {
                '.1': 'ifindex',
                '.2': 'id',
                '.3': 'type',
                '.4': 'mtu',
                '.5': 'speed',
                '.6': 'macaddress',
                '.7': 'adminStatus',
                '.8': 'operStatus'
            }),
        # AIX If table
        GetTableMap(
            'aixiftable',
            '.1.3.6.1.4.1.2.6.191.9.8.1.1',
            {
                '.1': 'id',
                '.2': 'ifindex',
                '.3': 'aixNetworkType',
                #'.4': 'aixNetworkInterface', # eg EN or LO or ....
                '.5':
                'aixNetworkStatus',  # 1 for available, 2 for defined state
                #'.6': 'aixNetworkLocation', # Slot number
                '.7': 'aixNetworkDescr',
            }),
        # ipAddrTable is the better way to get IP addresses
        GetTableMap('ipAddrTable', '.1.3.6.1.2.1.4.20.1', {
            '.1': 'ipAddress',
            '.2': 'ifindex',
            '.3': 'netmask'
        }),
        # Use the ipNetToMediaTable as a backup to the ipAddrTable
        GetTableMap('ipNetToMediaTable', '.1.3.6.1.2.1.4.22.1', {
            '.1': 'ifindex',
            '.3': 'ipaddress',
            '.4': 'iptype'
        }),
        # Interface Description
        GetTableMap('ifalias', '.1.3.6.1.2.1.31.1.1.1', {
            '.18': 'description',
            '.15': 'highSpeed',
        }),
    )

    def process(self, device, results, log):
        """Gather SNMP information from the the standard MIB
           and match it with what AIX provides."""

        log.info('processing %s for device %s', self.name(), device.id)

        getdata, tabledata = results

        #
        # Find all available AIX adapters
        #
        aixiftable = tabledata.get("aixiftable")
        if aixiftable is None:
            log.error('%s: Unable to gather data for aixiftable!', self.name())
            return

        available_interfaces = {}
        for index, data in aixiftable.items():
            if data.get(
                    'aixNetworkStatus') != 1:  # ie not in 'available' state
                continue
            id = data.get('id')
            if_type = data.get('aixNetworkType')
            if_desc = data.get('aixNetworkDescr')
            log.debug("Found 'available' interface %s with desc= %s", id,
                      if_desc)
            available_interfaces[id] = {
                'description': if_desc,
                'type': if_type,
            }

        #
        # Now match the AIX OID interfaces with the HOST-MIB OID interfaces.
        # This is necessary as we'll still be using the collectors for HOST-MIB,
        # so we'll need to keep the interface indices the same (ie all HOST-MIB indices).
        #
        iptable= tabledata.get("ipAddrTable") \
            or tabledata.get("ipNetToMediaTable")
        iftable = tabledata.get("iftable")
        ifalias = tabledata.get("ifalias")
        if iptable is None or iftable is None:
            log.error('%s: Unable to gather HOST-MIB data!', self.name())
            return
        if not ifalias:
            ifalias = {}

        #
        # NB: One of the issues is that the regular HOST-MIB entries find id's like
        # en2; Product: 10 Gigabit-SR Ethernet PCI-X Adapter Manufacturer: not available! Part Number: 16R0599 FRU Number: 16R0599
        #
        #      which is, of course, really annoying.  Remove any of the tripe after
        #      the first semi-colon in order to return to sanity.
        #

        #
        # add interface alias (Cisco description) to iftable
        #
        for ifidx, data in ifalias.items():
            if not iftable.has_key(ifidx):
                continue

            iftable[ifidx]['description'] = data.get('description', '')
            # if we collect ifAlias name use it
            # this is in the map subclass InterfaceAliasMap
            id = data.get('id', None)
            if id:
                semicolon_index = id.find(';')
                if semicolon_index != -1:
                    id = id[:semicolon_index]
                iftable[ifidx]['id'] = id

            iftable[ifidx]['description'] = data.get('description', '')
            # handle 10GB interfaces using IF-MIB::ifHighSpeed
            speed = iftable[ifidx].get('speed', 0)
            if speed == 4294967295L or speed < 0:
                try:
                    iftable[ifidx]['speed'] = data['highSpeed'] * 1e6
                except KeyError:
                    pass

        for ifidx, data in iftable.items():
            try:
                data['speed'] = unsigned(data['speed'])
            except KeyError:
                pass

        rm = self.relMap()
        omtable = {}
        for ip, row in iptable.items():
            if not row.has_key("ifindex"): continue

            # Fix data up if it is from the ipNetToMediaTable.
            if len(ip.split('.')) == 5:
                if row['iptype'] != 1: continue
                ip = '.'.join(ip.split('.')[1:])
                row['netmask'] = '255.255.255.0'

            strindex = str(row['ifindex'])
            if not omtable.has_key(strindex) and not iftable.has_key(strindex):
                log.warn("skipping %s points to missing ifindex %s",
                         row.get('ipAddress', ""), row.get('ifindex', ""))
                continue

            if not omtable.has_key(strindex):
                log.debug("Examining %s", iftable[strindex])
                om = self.processInt(device, iftable[strindex],
                                     available_interfaces)
                if not om: continue
                log.debug("Adding iface %s", om.id)
                rm.append(om)
                omtable[strindex] = om
                del iftable[strindex]
            elif omtable.has_key(strindex):
                om = omtable[strindex]
            else:
                log.warn("ip points to missing ifindex %s skipping", strindex)
                continue

            if not hasattr(om, 'setIpAddresses'): om.setIpAddresses = []
            if row.has_key('ipAddress'): ip = row['ipAddress']
            if row.has_key('netmask'):
                ip = ip + "/" + str(self.maskToBits(row['netmask'].strip()))
            om.setIpAddresses.append(ip)
            #om.ifindex = row.ifindex #FIXME ifindex is not set!

        for iface in iftable.values():
            log.debug("Examining %s", iface['id'])
            om = self.processInt(device, iface, available_interfaces)
            if om:
                log.debug("Adding iface %s", om.id)
                rm.append(om)

        return rm
    def process(self, device, results, log):
        """Process SNMP information from this device"""
        log.info('Modeler %s processing data for device %s', self.name(),
                 device.id)
        getdata, tabledata = results
        log.debug("%s tabledata = %s", device.id, tabledata)
        fstable = tabledata.get("fsTableOid")
        if fstable is None:
            log.error("Unable to get data for %s from fsTableOid"
                      " -- skipping model" % device.id)
            return None

        dskTable = tabledata.get("dskTable")

        hrFSEntry = tabledata.get("hrFSEntry", {})
        remoteMountMap = self._createRemoteMountMap(hrFSEntry)

        skipfsnames = getattr(device, 'zFileSystemMapIgnoreNames', None)
        skipfstypes = getattr(device, 'zFileSystemMapIgnoreTypes', None)
        maps = []
        rm = self.relMap()
        for fs in fstable.values():
            if not self.checkColumns(fs, self.columns, log):
                continue

            # Gentoo and openSUSE report "Virtual memory" as swap. This needs
            # to be ignored so we can pickup the real swap later in the table.
            if "virtual memory" in fs['mount'].lower():
                continue

            rmount = remoteMountMap.get(fs['snmpindex'])
            if rmount is not None and fs['mount'] != rmount:
                log.debug('Switching mount from %s to %s', fs['mount'], rmount)
                fs['storageDevice'] = rmount

            # Large file systems can report as an unsigned integer
            if fs['totalBlocks'] < 0:
                fs['totalBlocks'] = unsigned(totalBlocks)

            totalBlocks = fs['totalBlocks']
            size = long(fs['blockSize'] * totalBlocks)
            if size <= 0:
                log.info("Skipping %s. 0 total blocks.", fs['mount'])
                continue

            fs['type'] = self.typemap.get(fs['type'], "other")
            size = long(fs['blockSize'] * totalBlocks)

            # Handle file systems that need to be mapped into other parts of
            # the model such as total memory or total swap.
            if fs['type'] == "ram":
                maps.append(ObjectMap({"totalMemory": size}, compname="hw"))
            elif fs['type'] == "virtualMemory" or fs['mount'] == 'Swap':
                maps.append(ObjectMap({"totalSwap": size}, compname="os"))

            if skipfsnames and re.search(skipfsnames, fs['mount']):
                log.info(
                    "Skipping %s as it matches zFileSystemMapIgnoreNames.",
                    fs['mount'])
                continue

            if skipfstypes and fs['type'] in skipfstypes:
                log.info(
                    "Skipping %s (%s) as it matches zFileSystemMapIgnoreTypes.",
                    fs['mount'], fs['type'])
                continue

            fs["snmpindex_dct"] = {
                HRFileSystemMap.dskTableOid:
                self._getDskIndex(dskTable, fs["mount"])
            }

            om = self.objectMap(fs)
            om.id = self.prepId(om.mount)
            om.title = om.mount
            rm.append(om)
        maps.append(rm)

        # look for any map 'm' with m.compname == 'os' and m.totalSwap > 0
        if not any(
                getattr(m, 'compname', None) == 'os'
                and getattr(m, 'totalSwap', 0) > 0 for m in maps):
            # if no value set for device.os.totalSwap, set totalSwap to 0
            log.info("Swap space not detected for device %s, setting to 0",
                     device.id)
            maps.append(ObjectMap({'totalSwap': 0}, compname="os"))

        return maps