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,
     }
    def get_lldp_neighbors_detail(self, interface=""):
        lldp = {}

        if interface:
            command = "show lldp remote_ports {} mode detailed".format(
                interface)
        else:
            command = "show lldp remote_ports mode detailed"
        lldp_entries = self._send_command(command)
        lldp_entries = textfsm_extractor(self, "show_lldp_remote_ports_detail",
                                         lldp_entries)

        if len(lldp_entries) == 0:
            return {}

        for idx, lldp_entry in enumerate(lldp_entries):
            local_intf = lldp_entry.pop("local_interface")
            # Add fields missing on Dlink
            lldp_entry["parent_interface"] = lldp_entry[
                "remote_system_enable_capab"] = ""

            # Standarding "remote system capab"
            if lldp_entry["remote_system_capab"]:
                lldp_entry["remote_system_capab"] = sorted(
                    lldp_entry["remote_system_capab"].strip().lower().split(
                        ","))
            else:
                lldp_entry["remote_system_capab"] = []
            # Turn the interfaces into their long version
            local_intf = canonical_interface_name(local_intf)
            lldp.setdefault(local_intf, [])
            lldp[local_intf].append(lldp_entry)

        return lldp
Exemple #3
0
    def get_facts(self):
        """Return a set of facts from the devices."""
        # default values.
        vendor = "Mellanox"
        uptime = -1
        os_version, hostname, model = ("", ) * 3

        # obtain output from device
        show_ver = self._send_command("show version")
        show_hosts = self._send_command("show hosts")
        show_int_status = self._send_command("show interface status")

        # uptime/serial_number/IOS version
        for line in show_ver.splitlines():
            if "Uptime:" in line:
                _, uptime_str = line.split("Uptime:")
                uptime = self.parse_uptime(uptime_str)

            if "Product release:" in line:
                line = line.strip()
                os_version = line.split()[2]
                os_version = os_version.strip()

            if "Product model:" in line:
                line = line.strip()
                model = line.split()[2]

        for line in show_hosts.splitlines():
            if "Hostname: " in line:
                _, hostname = line.split("Hostname: ")
                break

        interface_list = []
        for line in show_int_status.splitlines():
            if line == '':
                continue
            elif line.startswith('E') or line.startswith('m'):
                interface = line.split()[0]
                # Return canonical interface name
                interface_list.append(
                    helpers.canonical_interface_name(interface))

        return {
            "uptime": int(uptime),
            "vendor": vendor,
            "os_version": py23_compat.text_type(os_version),
            "model": py23_compat.text_type(model),
            "hostname": py23_compat.text_type(hostname),
            "interface_list": interface_list,
        }
    def get_lldp_neighbors_detail(self, interface=""):
        """
        get_lldp_neighbors_detail() implementation for s350
        """
        details = {}

        # First determine all interfaces with valid LLDP neighbors
        for local_port in self.get_lldp_neighbors().keys():
            if interface:
                if interface == local_port:
                    entry = self._get_lldp_neighbors_detail_parse(local_port)
                    local_port = canonical_interface_name(local_port, s350_base_interfaces)
                    details[local_port] = [
                        entry,
                    ]

            else:
                entry = self._get_lldp_neighbors_detail_parse(local_port)
                local_port = canonical_interface_name(local_port, s350_base_interfaces)
                details[local_port] = [
                    entry,
                ]

        return details
    def get_lldp_neighbors(self):
        """get_lldp_neighbors implementation for s350"""
        neighbors = {}
        output = self._send_command("show lldp neighbors")

        header = True  # cycle trought header
        local_port = ""  # keep previous context - multiline syname
        remote_port = ""
        remote_name = ""
        for line in output.splitlines():
            if header:
                # last line of header
                match = re.match(r"^--------- -+ .*$", line)
                if match:
                    header = False
                    fields_end = self._get_lldp_neighbors_fields_end(line)
                continue

            line_elems = self._get_lldp_neighbors_line_to_fields(line, fields_end)

            # info owerflow to the other line
            if line_elems[0] == "" or line_elems[4] == "" or line_elems[5] == "":
                # complete owerflown fields
                local_port = local_port + line_elems[0]
                remote_port = remote_port + line_elems[2]
                remote_name = remote_name + line_elems[3]
                # then reuse old values na rewrite previous entry
            else:
                local_port = line_elems[0]
                remote_port = line_elems[2]
                remote_name = line_elems[3]

            local_port = canonical_interface_name(local_port, s350_base_interfaces)

            neighbor = {
                "hostname": remote_name,
                "port": remote_port,
            }
            neighbor_list = [
                neighbor,
            ]
            neighbors[local_port] = neighbor_list

        return neighbors
    def _get_lldp_neighbors_detail_parse(self, local_port):
        # Set defaults, just in case the remote fails to provide a field.
        (
            remote_port_id,
            remote_port_description,
            remote_chassis_id,
            remote_system_name,
            remote_system_description,
            remote_system_capab,
            remote_system_enable_capab,
        ) = ("N/A",) * 7

        output = self._send_command("show lldp neighbors {}".format(local_port))

        for line in output.splitlines():
            if line.startswith("Port ID"):
                remote_port_id = line.split()[-1]
            elif line.startswith("Device ID"):
                remote_chassis_id = line.split()[-1]
            elif line.startswith("Port description"):
                remote_port_description = self._get_lldp_line_value(line)
            elif line.startswith("System Name"):
                remote_system_name = self._get_lldp_line_value(line)
            elif line.startswith("System description"):
                remote_system_description = self._get_lldp_line_value(line)
            elif line.startswith("Capabilities"):
                caps = self._get_lldp_neighbors_detail_capabilities_parse(line)

        remote_port_id = canonical_interface_name(remote_port_id, s350_base_interfaces)

        entry = {
            "parent_interface": "N/A",
            "remote_port": remote_port_id,
            "remote_port_description": remote_port_description,
            "remote_chassis_id": remote_chassis_id,
            "remote_system_name": remote_system_name,
            "remote_system_description": remote_system_description,
            "remote_system_capab": caps,
            "remote_system_enable_capab": caps,
        }

        return entry
    def get_interfaces_ip(self):
        """Returns all configured interface IP addresses."""
        interfaces = {}
        show_ip_int = self._send_command("show ip interface")

        header = True  # cycle trought header
        for line in show_ip_int.splitlines():
            if header:
                # last line of first header
                match = re.match(r"^---+ -+ .*$", line)
                if match:
                    header = False
                    fields_end = self._get_ip_int_fields_end(line)
                continue

            # next header, stop processing text
            if re.match(r"^---+ -+ .*$", line):
                break

            line_elems = self._get_ip_int_line_to_fields(line, fields_end)

            # only valid interfaces
            # in diferent firmwares there is 'Status' field allwais on last place
            if line_elems[len(line_elems) - 1] != "Valid":
                continue

            cidr = line_elems[0]
            interface = line_elems[1]

            ip = netaddr.IPNetwork(cidr)
            family = "ipv{0}".format(ip.version)

            interface = canonical_interface_name(interface, s350_base_interfaces)

            interfaces[interface] = {family: {str(ip.ip): {"prefix_length": ip.prefixlen}}}

        return interfaces
    def get_arp_table(self, vrf=""):
        """
        Get the ARP table, the age isn't readily available so we leave that out for now.

        vrf is needed for test - no support on s350
        """

        arp_table = []

        output = self._send_command("show arp")

        for line in output.splitlines():
            # A VLAN may not be set for the entry
            if "vlan" not in line:
                continue
            if len(line.split()) == 4:
                interface, ip, mac, _ = line.split()
            elif len(line.split()) == 5:
                if1, if2, ip, mac, _ = line.split()
                interface = "{} {}".format(if1, if2)
            elif len(line.split()) == 6:
                _, _, interface, ip, mac, _ = line.split()
            else:
                raise ValueError("Unexpected output: {}".format(line.split()))

            interface = canonical_interface_name(interface, s350_base_interfaces)

            entry = {
                "interface": interface,
                "mac": napalm.base.helpers.mac(mac),
                "ip": ip,
                "age": 0.0,
            }

            arp_table.append(entry)

        return arp_table
def collect_transceivers_info(  # pylint: disable=R0911
        task: Task, update_cache=True, use_cache=False) -> Result:
    """
    Collect transceiver informaton on all devices

    Supported Devices:
        Cisco IOS
        cisco_nxos

    Args:
      task: Task:
      update_cache: (Default value = True)
      use_cache: (Default value = False)

    Returns:

    """
    cache_name = "transceivers"

    if use_cache:
        data = get_data_from_file(task.host.name, cache_name)
        return Result(host=task.host, result=data)

    transceivers_inventory = []

    xcvr_model = {
        "interface": None,
        "manufacturer": None,
        "serial": None,
        "part_number": None,
        "type": None,
    }

    check_data_dir(task.host.name)

    if task.host.platform == "ios":

        try:
            results = task.run(
                task=netmiko_send_command,
                command_string="show inventory",
                use_textfsm=True,
            )
        except:
            logger.debug("An exception occured while pulling the inventory",
                         exc_info=True)
            return Result(host=task.host, failed=True)

        inventory = results[0].result

        cmd = "show interface transceiver"
        try:
            results = task.run(
                task=netmiko_send_command,
                command_string=cmd,
                use_textfsm=True,
            )
        except:
            logger.debug(
                "An exception occured while pulling the transceiver info",
                exc_info=True)
            return Result(host=task.host, failed=True)

        transceivers = results[0].result

        if not isinstance(transceivers, list):
            logger.debug(
                f"{task.host.name}: command: {cmd} was not returned as a list, please check if the ntc-template are installed properly"  # pylint: disable=C0301
            )
            return Result(host=task.host, result=transceivers_inventory)

        transceiver_names = [t["iface"] for t in transceivers]
        full_transceiver_names = [
            canonical_interface_name(t) for t in transceiver_names
        ]

        # Check if the optic is in the inventory by matching on the interface name
        # Normalize the name of the interface before returning it
        for item in inventory:
            xcvr = copy.deepcopy(xcvr_model)

            if item.get("name", "") in transceiver_names:
                xcvr["interface"] = canonical_interface_name(item["name"])
            elif item.get("name", "") in full_transceiver_names:
                xcvr["interface"] = item["name"]
            else:
                continue

            xcvr["serial"] = item["sn"]
            xcvr["type"] = item["descr"]

            transceivers_inventory.append(xcvr)

    elif task.host.platform == "nxos":
        cmd = "show interface transceiver"
        try:
            results = task.run(task=netmiko_send_command,
                               command_string=cmd,
                               use_textfsm=True)
        except:
            logger.debug(
                "An exception occured while pulling the transceiver info",
                exc_info=True)
            return Result(host=task.host, failed=True)

        transceivers = results[0].result

        if not isinstance(transceivers, list):
            logger.warning(
                f"command: {cmd} was not returned as a list, please check if the ntc-template are installed properly"
            )
            return Result(host=task.host, result=transceivers_inventory)

        for tranceiver in transceivers:
            transceivers_inventory.append(tranceiver)

    elif task.host.platform == "eos":

        nr_device = task.host.get_connection("napalm", task.nornir.config)
        eos_device = nr_device.device
        results = eos_device.run_commands(["show transceiver status"])

        transceivers = results[0]["ports"]

        for name, data in transceivers.items():

            try:
                xcvr = copy.deepcopy(xcvr_model)
                xcvr["serial"] = data["serialNumber"]["state"]
                xcvr["interface"] = list(data["interfaces"].keys())[0]
                xcvr["type"] = data["mediaType"]["state"]
                xcvr["part_number"] = data["mediaType"]["state"]
            except:
                logger.warning(
                    f"Unable to extract the transceiver information for {name} : {sys.exc_info()[0]}"
                )
                continue

            transceivers_inventory.append(xcvr)

    else:
        logger.debug(
            f"{task.host.name} | collect_transceiver_info not supported yet for {task.host.platform}"
        )

    if update_cache and transceivers_inventory:
        save_data_to_file(task.host.name, cache_name, transceivers_inventory)

    return Result(host=task.host, result=transceivers_inventory)
    def get_interfaces(self):
        """
        get_interfaces() implementation for S350
        """
        interfaces = {}

        show_status_output = self._send_command("show interfaces status")
        show_description_output = self._send_command("show interfaces description")

        # by documentation SG350
        show_jumbo_frame = self._send_command("show ports jumbo-frame")
        match = re.search(r"Jumbo frames are enabled", show_jumbo_frame, re.M)
        if match:
            mtu = 9000
        else:
            mtu = 1518

        mac = "0"

        for status_line in show_status_output.splitlines():
            if "Up" in status_line or "Down" in status_line:
                if "Po" in status_line:
                    interface, _, _, speed, _, _, link_state = status_line.split()
                else:
                    interface, _, _, speed, _, _, link_state, _, _ = status_line.split()

                # Since the MAC address for all the local ports are equal, get the address
                # from the first port and use it everywhere.
                if mac == "0":
                    show_system_output = self._send_command("show lldp local " + interface)
                    mac = show_system_output.splitlines()[0].split(":", maxsplit=1)[1].strip()

                if speed == "--":
                    is_enabled = False
                    speed = 0
                else:
                    is_enabled = True
                    speed = int(speed)

                is_up = link_state == "Up"

                for descr_line in show_description_output.splitlines():
                    description = 0
                    if descr_line.startswith(interface):
                        description = " ".join(descr_line.split()[1:])
                        break

                # last_flapped can not be get - setting to default
                entry = {
                    "is_up": is_up,
                    "is_enabled": is_enabled,
                    "speed": speed,
                    "mtu": mtu,
                    "last_flapped": -1.0,
                    "description": description,
                    "mac_address": napalm.base.helpers.mac(mac),
                }

                interface = canonical_interface_name(interface, s350_base_interfaces)

                interfaces[interface] = entry

        return interfaces
    def get_facts(self):
        """Return a set of facts from the device."""
        serial_number, fqdn, os_version, hostname, domainname = ("Unknown",) * 5

        # Submit commands to the device.
        show_ver = self._send_command("show version")
        show_sys = self._send_command("show system")
        show_inv = self._send_command("show inventory")
        show_hosts = self._send_command("show hosts")
        show_int_st = self._send_command("show interfaces status")

        os_version = self._get_facts_parse_os_version(show_ver)

        # hostname
        hostname = self._get_facts_hostname(show_sys)
        # special case for SG500 fw v1.4.x
        if hostname == "Unknown":
            hostname = self._get_facts_hostname_from_config(
                self._send_command("show running-config")
            )

        # uptime
        uptime_str = self._get_facts_uptime(show_sys)
        uptime = self._parse_uptime(uptime_str)

        # serial_number and model
        inventory = self._get_facts_parse_inventory(show_inv)["1"]
        serial_number = inventory["sn"]
        model = inventory["pid"]

        # fqdn
        domainname = napalm.base.helpers.textfsm_extractor(self, "hosts", show_hosts)[0]
        domainname = domainname["domain_name"]
        if domainname == "Domain":
            domainname = "Unknown"
        if domainname != "Unknown" and hostname != "Unknown":
            fqdn = "{0}.{1}".format(hostname, domainname)

        # interface_list
        interfaces = []
        show_int_st = show_int_st.strip()
        # remove the header information
        show_int_st = re.sub(
            r"(^-.*$|^Port .*$|^Ch .*$)|^\s.*$|^.*Flow.*$", "", show_int_st, flags=re.M
        )
        for line in show_int_st.splitlines():
            if not line:
                continue
            interface = line.split()[0]
            interface = canonical_interface_name(interface, s350_base_interfaces)

            interfaces.append(str(interface))

        return {
            "fqdn": str(fqdn),
            "hostname": str(hostname),
            "interface_list": interfaces,
            "model": str(model),
            "os_version": str(os_version),
            "serial_number": str(serial_number),
            "uptime": uptime,
            "vendor": "Cisco",
        }
    def get_facts(self):
        """Return a set of facts from the devices."""
        # default values.
        vendor = "Cisco"
        uptime = -1
        serial_number, fqdn, os_version, hostname, domain_name, model = ("",) * 6

        # obtain output from device
        show_ver = self._send_command("show version")
        show_hosts = self._send_command("show hosts")
        show_int_status = self._send_command("show interface status")
        show_hostname = self._send_command("show hostname")

        # uptime/serial_number/IOS version
        for line in show_ver.splitlines():
            if " uptime is " in line:
                _, uptime_str = line.split(" uptime is ")
                uptime = self.parse_uptime(uptime_str)

            if "Processor Board ID" in line:
                _, serial_number = line.split("Processor Board ID ")
                serial_number = serial_number.strip()

            if "system: " in line or "NXOS: " in line:
                line = line.strip()
                os_version = line.split()[2]
                os_version = os_version.strip()

            if "cisco" in line and "hassis" in line:
                match = re.search(r".cisco (.*) \(", line)
                if match:
                    model = match.group(1).strip()
                match = re.search(r".cisco (.* [cC]hassis)", line)
                if match:
                    model = match.group(1).strip()

        hostname = show_hostname.strip()

        # Determine domain_name and fqdn
        for line in show_hosts.splitlines():
            if "Default domain" in line:
                _, domain_name = re.split(r".*Default domain.*is ", line)
                domain_name = domain_name.strip()
                break
        if hostname.count(".") >= 2:
            fqdn = hostname
            # Remove domain name from hostname
            if domain_name:
                hostname = re.sub(re.escape(domain_name) + "$", "", hostname)
                hostname = hostname.strip(".")
        elif domain_name:
            fqdn = "{}.{}".format(hostname, domain_name)

        # interface_list filter
        interface_list = []
        show_int_status = show_int_status.strip()
        # Remove the header information
        show_int_status = re.sub(
            r"(?:^---------+$|^Port .*$|^ .*$)", "", show_int_status, flags=re.M
        )
        for line in show_int_status.splitlines():
            if not line:
                continue
            interface = line.split()[0]
            # Return canonical interface name
            interface_list.append(helpers.canonical_interface_name(interface))

        return {
            "uptime": int(uptime),
            "vendor": vendor,
            "os_version": py23_compat.text_type(os_version),
            "serial_number": py23_compat.text_type(serial_number),
            "model": py23_compat.text_type(model),
            "hostname": py23_compat.text_type(hostname),
            "fqdn": fqdn,
            "interface_list": interface_list,
        }
Exemple #13
0
    def get_facts(self):
        """Return a set of facts from the devices."""
        # default values.
        vendor = u'Cisco'
        uptime = -1
        serial_number, fqdn, os_version, hostname, domain_name, model = (
            '', ) * 6

        # obtain output from device
        show_ver = self._send_command('show version')
        show_hosts = self._send_command('show hosts')
        show_int_status = self._send_command('show interface status')
        show_hostname = self._send_command('show hostname')

        # uptime/serial_number/IOS version
        for line in show_ver.splitlines():
            if ' uptime is ' in line:
                _, uptime_str = line.split(' uptime is ')
                uptime = self.parse_uptime(uptime_str)

            if 'Processor Board ID' in line:
                _, serial_number = line.split("Processor Board ID ")
                serial_number = serial_number.strip()

            if 'system: ' in line or 'NXOS: ' in line:
                line = line.strip()
                os_version = line.split()[2]
                os_version = os_version.strip()

            if 'cisco' in line and 'hassis' in line:
                match = re.search(r'.cisco (.*) \(', line)
                if match:
                    model = match.group(1).strip()
                match = re.search(r'.cisco (.* [cC]hassis)', line)
                if match:
                    model = match.group(1).strip()

        hostname = show_hostname.strip()

        # Determine domain_name and fqdn
        for line in show_hosts.splitlines():
            if 'Default domain' in line:
                _, domain_name = re.split(r".*Default domain.*is ", line)
                domain_name = domain_name.strip()
                break
        if hostname.count(".") >= 2:
            fqdn = hostname
            # Remove domain name from hostname
            if domain_name:
                hostname = re.sub(re.escape(domain_name) + '$', '', hostname)
                hostname = hostname.strip('.')
        elif domain_name:
            fqdn = '{}.{}'.format(hostname, domain_name)

        # interface_list filter
        interface_list = []
        show_int_status = show_int_status.strip()
        # Remove the header information
        show_int_status = re.sub(r'(?:^---------+$|^Port .*$|^ .*$)',
                                 '',
                                 show_int_status,
                                 flags=re.M)
        for line in show_int_status.splitlines():
            if not line:
                continue
            interface = line.split()[0]
            # Return canonical interface name
            interface_list.append(canonical_interface_name(interface))

        return {
            'uptime': int(uptime),
            'vendor': vendor,
            'os_version': py23_compat.text_type(os_version),
            'serial_number': py23_compat.text_type(serial_number),
            'model': py23_compat.text_type(model),
            'hostname': py23_compat.text_type(hostname),
            'fqdn': fqdn,
            'interface_list': interface_list
        }