Exemplo n.º 1
0
    def get_arp_table(self, vrf=u''):
        """FTOS implementation of get_arp_table."""
        if vrf:
            msg = "VRF support has not been added for this getter on this platform."
            raise NotImplementedError(msg)

        command = "show arp"
        arp_entries = self._send_command(command)
        arp_entries = textfsm_extractor(self, 'show_arp', arp_entries)

        table = []
        for idx, arp in enumerate(arp_entries):
            entry = {
                'interface': arp['interface'],
                'ip': ip(arp['ip']),
                'mac': mac(arp['mac']),
            }

            try:
                # age is given in minutes
                entry['age'] = float(arp['age']) * 60
            except ValueError:
                entry['age'] = -1.0

            table.append(entry)

        return table
Exemplo n.º 2
0
 def process_mac_fields(vlan, mac, mac_type, interface):
     """Return proper data for mac address fields."""
     if mac_type.lower() in ["self", "static", "system"]:
         static = True
         if vlan.lower() == "all":
             vlan = 0
         elif vlan == "-":
             vlan = 0
         if (
             interface.lower() == "cpu"
             or re.search(r"router", interface.lower())
             or re.search(r"switch", interface.lower())
         ):
             interface = ""
     else:
         static = False
     if mac_type.lower() in ["dynamic"]:
         active = True
     else:
         active = False
     return {
         "mac": helpers.mac(mac),
         "interface": helpers.canonical_interface_name(interface),
         "vlan": int(vlan),
         "static": static,
         "active": active,
         "moves": -1,
         "last_move": -1.0,
     }
Exemplo n.º 3
0
    def get_interfaces(self):
        """FTOS implementation of get_interfaces."""
        iface_entries = self._get_interfaces_detail()

        interfaces = {}
        for i, entry in enumerate(iface_entries):
            if len(entry['iface_name']) == 0:
                continue
            if len(entry['mac_address']) == 0:
                continue

            # init interface entry with default values
            iface = {
                'is_enabled': False,
                'is_up': False,
                'description': str(entry['description']),
                'mac_address': u'',
                'last_flapped': 0.0,  # in seconds
                'speed': 0,  # in megabits
                'mtu': 0,
            }

            # not all interface have MAC addresses specified in `show interfaces'
            # so if converting it to a MAC address won't work, leave it like that
            try:
                iface['mac_address'] = mac(entry['mac_address'])
            except AddrFormatError:
                pass

            # set statuses
            if entry['admin_status'] == 'up':
                iface['is_enabled'] = True
            if entry['oper_status'] == 'up':
                iface['is_up'] = True

            # parse line_speed
            if re.search(r'bit$', entry['line_speed']):
                speed = entry['line_speed'].split(' ')
                if speed[1] == 'Mbit':
                    iface['speed'] = int(speed[0])
                # not sure if this ever occurs
                elif speed[1] == 'Gbit':
                    iface['speed'] = int(speed[0] * 1000)

            # parse mtu
            iface['mtu'] = int(entry['mtu'])

            # parse last_flapped
            iface['last_flapped'] = float(
                parse_uptime(entry['last_flapped'], True))

            # add interface data to dict
            local_intf = canonical_interface_name(entry['iface_name'])
            interfaces[local_intf] = iface

        return interfaces
    def get_facts(self):
        """ Return a set of facts from the devices. """
        # default values.
        serial_number, fqdn, os_version, hostname, domain_name = (
            "Unknown", ) * 5

        output = self._send_command("show switch")
        show_switch = textfsm_extractor(self, "show_switch", output)[0]

        uptime = self.parse_uptime(show_switch["uptime"])
        vendor = "Dlink"
        os_version = show_switch["os_version"]
        serial_number = show_switch["serial_number"]
        model = show_switch["model"]
        # In Dlink device can't change hostname. Add system_name.
        hostname = fqdn = show_switch["system_name"]

        # Get interface list
        show_ports = self._send_command("show ports")
        interface_list = re.findall(r'^\d+', show_ports, re.MULTILINE)

        return {
            "uptime": uptime,
            "vendor": vendor,
            "os_version": str(os_version),
            "serial_number": str(serial_number),
            "model": str(model),
            "hostname": str(hostname),
            "fqdn": fqdn,
            "interface_list": interface_list,

            # Additional data
            "mac_addr": mac(show_switch["mac_addr"]),
            "ip_addr": show_switch["ip_addr"],
            "vlan_name": show_switch["vlan_name"],
            "subnet_mask": show_switch["subnet_mask"],
            "gateway": show_switch["gateway"],
            "boot_version": show_switch["boot_version"],
            "protocol_version": show_switch["protocol_version"],
            "hardware_version": show_switch["hardware_version"],
            "system_time": show_switch["system_time"],
            "location": show_switch["location"],
            "contact": show_switch["contact"],
            "stp": show_switch["stp"],
            "gvrp": show_switch["gvrp"],
            "igmp_snooping": show_switch["igmp_snooping"],
            "radius": show_switch["radius"],
            "telnet": show_switch["telnet"],
            "web": show_switch["web"],
            "rmon": show_switch["rmon"],
            "ssh": show_switch["ssh"],
            "vlan_trunk": show_switch["vlan_trunk"],
            "syslog": show_switch["syslog"],
            "cli_paging": show_switch["cli_paging"],
            "password_encryption": show_switch["password_encryption"],
        }
    def get_lldp_neighbors_detail(self, interface=''):
        """FTOS implementation of get_lldp_neighbors_detail."""
        if interface:
            command = "show lldp neighbors interface {} detail".format(
                interface)
        else:
            command = "show lldp neighbors detail"

        lldp_entries = self._send_command(command)
        lldp_entries = textfsm_extractor(self, 'show_lldp_neighbors_detail',
                                         lldp_entries)

        lldp = {}
        for idx, lldp_entry in enumerate(lldp_entries):
            # TODO: the current textfsm template keeps adding an empty entry at
            # the end of each interface and I couldn't fix it so at some point
            # it was just easier to get rid of these empty entries in code
            nonZero = False
            for key in lldp_entry.keys():
                # local_interface is set to Filldown so that is always filled
                if key == 'local_interface':
                    continue
                if len(lldp_entry[key].strip()) > 0:
                    nonZero = True
                    break
            if not nonZero:
                continue

            # get pretty interface name
            local_intf = canonical_interface_name(
                lldp_entry.pop('local_interface'))

            # cast some mac addresses
            for k in ['remote_port', 'remote_chassis_id']:
                if len(lldp_entry[k].strip()) > 0:
                    try:
                        lldp_entry[k] = mac(lldp_entry[k])
                    except AddrFormatError:
                        pass

            # transform capabilities
            for k in ['remote_system_capab', 'remote_system_enable_capab']:
                lldp_entry[k] = transform_lldp_capab(lldp_entry[k])

            # not implemented
            lldp_entry['parent_interface'] = u''

            lldp.setdefault(local_intf, [])
            lldp[local_intf].append(lldp_entry)

        return lldp
    def get_mac_address_table(self):
        """
        Returns a lists of dictionaries. Each dictionary represents an entry in the MAC Address
        Table, having the following keys
            * mac (string)
            * interface (string)
            * vlan (int)
            * active (boolean)
            * static (boolean)
            * moves (int)
            * last_move (float)

        Format:
        VID  VLAN Name                        MAC Address       Port Type
        ---- -------------------------------- ----------------- ---- ---------------
        903  ACswmgmt              C0-A0-BB-DB-7D-C5 CPU  Self
        903  ACswmgmt             28-8A-1C-A8-1A-96 25   Dynamic
        903  ACswmgmt              70-62-B8-A8-94-13 25   Dynamic
        """
        mac_address_table = []

        output = self._send_command("show fdb")
        show_fdb = textfsm_extractor(self, "show_fdb", output)

        for line in show_fdb:
            mac_addr = mac(line["mac"])
            interface = line["interface"]
            vlan = int(line["vlan"])
            static = False

            if line["mac_type"].lower() in ["self", "static", "system"]:
                static = True

            if (line["interface"].lower() == "cpu"
                    or re.search(r"router", line["mac_type"].lower())
                    or re.search(r"switch", line["mac_type"].lower())):
                interface = ""

            mac_address_table.append({
                "mac": mac_addr,
                "interface": interface,
                "vlan": vlan,
                "static": static,
                "active": True,
                "moves": -1,
                "last_move": -1.0,
            })

        return mac_address_table
Exemplo n.º 7
0
    def get_mac_address_table(self):
        """FTOS implementation of get_mac_address_table."""
        mac_entries = self._send_command("show mac-address-table")
        mac_entries = textfsm_extractor(self, 'show_mac-address-table', mac_entries)

        mac_table = []
        for idx, entry in enumerate(mac_entries):
            entry['mac'] = mac(entry['mac'])
            entry['interface'] = canonical_interface_name(entry['interface'])
            entry['vlan'] = int(entry['vlan'])
            entry['static'] = (entry['static'] == 'Static')
            entry['active'] = (entry['active'] == 'Active')
            entry['moves'] = -1        # not implemented
            entry['last_move'] = -1.0  # not implemented

            mac_table.append(entry)

        return mac_table
Exemplo n.º 8
0
    def get_interfaces(self):
        """FTOS implementation of get_interfaces."""
        iface_entries = self._get_interfaces_detail()

        interfaces = {}
        for i, entry in enumerate(iface_entries):
            if len(entry['iface_name']) == 0:
                continue
            if len(entry['mac_address']) == 0:
                continue

            # init interface entry with default values
            iface = {
                'is_enabled':   False,
                'is_up':        False,
                'description':  entry['description'],
                'mac_address':  mac(entry['mac_address']),
                'last_flapped': 0.0,  # in seconds
                'speed':        0,    # in megabits
            }

            # set statuses
            if entry['admin_status'] == 'up':
                iface['is_enabled'] = True
            if entry['oper_status'] == 'up':
                iface['is_up'] = True

            # parse line_speed
            if re.search(r'bit$', entry['line_speed']):
                speed = entry['line_speed'].split(' ')
                if speed[1] == 'Mbit':
                    iface['speed'] = int(speed[0])
                # not sure if this ever occurs
                elif speed[1] == 'Gbit':
                    iface['speed'] = int(speed[0]*1000)

            # parse last_flapped
            iface['last_flapped'] = float(parse_uptime(entry['last_flapped'], True))

            # add interface data to dict
            local_intf = canonical_interface_name(entry['iface_name'])
            interfaces[local_intf] = iface

        return interfaces
Exemplo n.º 9
0
    def get_arp_table(self, vrf=u''):
        if vrf:
            msg = "VRF support has not been added for this getter on this platform."
            raise NotImplementedError(msg)

        command = "arp -van"
        arp_entries = self._send_command(command)
        arp_entries = textfsm_extractor(self, 'show_arp', arp_entries)

        table = []
        for idx, arp in enumerate(arp_entries):
            entry = {
                'interface': arp['interface'],
                'ip': ip(arp['ip']),
                'mac': mac(arp['mac']),
            }

            table.append(entry)

        return table
    def get_arp_table(self, vrf=""):
        """
        Device does not support VRF. Using age as is configured on device, not real aging time.
        Get arp table information.

        Return a list of dictionaries having the following set of keys:
            * interface (string)
            * mac (string)
            * ip (string)
            * age (float)

        For example::
            [
                {
                    'interface' : 'MgmtEth0/RSP0/CPU0/0',
                    'mac'       : '5c:5e:ab:da:3c:f0',
                    'ip'        : '172.17.17.1',
                    'age'       : 1454496274.84
                },
                {
                    'interface': 'MgmtEth0/RSP0/CPU0/0',
                    'mac'       : '66:0e:94:96:e0:ff',
                    'ip'        : '172.17.17.2',
                    'age'       : 1435641582.49
                }
            ]
        """
        arp_table = []

        output = self._send_command("show arpentry")
        show_arpentry = textfsm_extractor(self, "show_arpentry", output)

        for line in show_arpentry:
            line["mac"] = mac(line["mac"])
            line["age"] = int(line["age"]) * 60
            arp_table.append(line)

        return arp_table
Exemplo n.º 11
0
    def get_arp_table(self, vrf=""):
        """
        Get arp table information.

        Return a list of dictionaries having the following set of keys:
            * interface (string)
            * mac (string)
            * ip (string)
            * age (float)

        For example::
            [
                {
                    'interface' : 'MgmtEth0/RSP0/CPU0/0',
                    'mac'       : '5c:5e:ab:da:3c:f0',
                    'ip'        : '172.17.17.1',
                    'age'       : 12.0
                },
                {
                    'interface': 'MgmtEth0/RSP0/CPU0/0',
                    'mac'       : '66:0e:94:96:e0:ff',
                    'ip'        : '172.17.17.2',
                    'age'       : 14.0
                }
            ]
        """
        arp_table = []

        command = "show ip arp vrf {} | exc INCOMPLETE".format(vrf or "all")
        output = self._send_command(command)

        separator = r"^Address\s+Age.*Interface.*$"
        arp_list = re.split(separator, output, flags=re.M)
        if len(arp_list) != 2:
            raise ValueError("Error processing arp table output:\n\n{}".format(output))

        arp_entries = arp_list[1].strip()
        for line in arp_entries.splitlines():
            if len(line.split()) >= 4:
                # Search for extra characters to strip, currently strip '*', '+', '#', 'D'
                line = re.sub(r"\s+[\*\+\#D]{1,4}\s*$", "", line, flags=re.M)
                address, age, mac, interface = line.split()
            else:
                raise ValueError("Unexpected output from: {}".format(line.split()))

            if age == "-":
                age = -1.0
            elif ":" not in age:
                # Cisco sometimes returns a sub second arp time 0.411797
                try:
                    age = float(age)
                except ValueError:
                    age = -1.0
            else:
                age = convert_hhmmss(age)
                age = float(age)
            age = round(age, 1)

            # Validate we matched correctly
            if not re.search(RE_IPADDR, address):
                raise ValueError("Invalid IP Address detected: {}".format(address))
            if not re.search(RE_MAC, mac):
                raise ValueError("Invalid MAC Address detected: {}".format(mac))
            entry = {
                "interface": interface,
                "mac": helpers.mac(mac),
                "ip": address,
                "age": age,
            }
            arp_table.append(entry)
        return arp_table
Exemplo n.º 12
0
def parse_intf_section(interface):
    """Parse a single entry from show interfaces output.

    Different cases:
    mgmt0 is up
    admin state is up

    Ethernet2/1 is up
    admin state is up, Dedicated Interface

    Vlan1 is down (Administratively down), line protocol is down, autostate enabled

    Ethernet154/1/48 is up (with no 'admin state')
    """
    interface = interface.strip()
    re_protocol = (
        r"^(?P<intf_name>\S+?)\s+is\s+(?P<status>.+?)"
        r",\s+line\s+protocol\s+is\s+(?P<protocol>\S+).*$"
    )
    re_intf_name_state = r"^(?P<intf_name>\S+) is (?P<intf_state>\S+).*"
    re_is_enabled_1 = r"^admin state is (?P<is_enabled>\S+)$"
    re_is_enabled_2 = r"^admin state is (?P<is_enabled>\S+), "
    re_is_enabled_3 = r"^.* is down.*Administratively down.*$"
    re_mac = r"^\s+Hardware:\s+(?P<hardware>.*),\s+address:\s+(?P<mac_address>\S+) "
    re_speed = r"\s+MTU .*?,\s+BW\s+(?P<speed>\S+)\s+(?P<speed_unit>\S+).*$"
    re_description_1 = r"^\s+Description:\s+(?P<description>.*)  (?:MTU|Internet)"
    re_description_2 = r"^\s+Description:\s+(?P<description>.*)$"
    re_hardware = r"^.* Hardware: (?P<hardware>\S+)$"

    # Check for 'protocol is ' lines
    match = re.search(re_protocol, interface, flags=re.M)
    if match:
        intf_name = match.group("intf_name")
        status = match.group("status")
        protocol = match.group("protocol")

        if "admin" in status.lower():
            is_enabled = False
        else:
            is_enabled = True
        is_up = bool("up" in protocol)

    else:
        # More standard is up, next line admin state is lines
        match = re.search(re_intf_name_state, interface)
        intf_name = match.group("intf_name")
        intf_state = match.group("intf_state").strip()
        is_up = True if intf_state == "up" else False

        admin_state_present = re.search("admin state is", interface)
        if admin_state_present:
            # Parse cases where 'admin state' string exists
            for x_pattern in [re_is_enabled_1, re_is_enabled_2]:
                match = re.search(x_pattern, interface, flags=re.M)
                if match:
                    is_enabled = match.group("is_enabled").strip()
                    is_enabled = True if re.search("up", is_enabled) else False
                    break
            else:
                msg = "Error parsing intf, 'admin state' never detected:\n\n{}".format(
                    interface
                )
                raise ValueError(msg)
        else:
            # No 'admin state' should be 'is up' or 'is down' strings
            # If interface is up; it is enabled
            is_enabled = True
            if not is_up:
                match = re.search(re_is_enabled_3, interface, flags=re.M)
                if match:
                    is_enabled = False

    match = re.search(re_mac, interface, flags=re.M)
    if match:
        mac_address = match.group("mac_address")
        mac_address = helpers.mac(mac_address)
    else:
        mac_address = ""

    match = re.search(re_hardware, interface, flags=re.M)
    speed_exist = True
    if match:
        if match.group("hardware") == "NVE":
            speed_exist = False

    if speed_exist:
        match = re.search(re_speed, interface, flags=re.M)
        speed = int(match.group("speed"))
        speed_unit = match.group("speed_unit")
        speed_unit = speed_unit.rstrip(",")
        # This was alway in Kbit (in the data I saw)
        if speed_unit != "Kbit":
            msg = "Unexpected speed unit in show interfaces parsing:\n\n{}".format(
                interface
            )
            raise ValueError(msg)
        speed = int(round(speed / 1000.0))
    else:
        speed = -1

    description = ""
    for x_pattern in [re_description_1, re_description_2]:
        match = re.search(x_pattern, interface, flags=re.M)
        if match:
            description = match.group("description")
            break

    return {
        intf_name: {
            "description": description,
            "is_enabled": is_enabled,
            "is_up": is_up,
            "last_flapped": -1.0,
            "mac_address": mac_address,
            "speed": speed,
        }
    }