Exemplo n.º 1
0
def get_system_nics(plugin_object, redfish_url):

    def get_network_port(port_data=None, network_function_id=None, return_data=False):

        # could be
        #  * a string
        #  * a dict with just the link
        #  * a dict with full data
        port_response = None
        redfish_path = None
        if isinstance(port_data, dict):

            if port_data.get("Id") is not None:
                port_response = port_data
            else:
                redfish_path = port_data.get("@odata.id")

        elif isinstance(port_data, str):
            redfish_path = port_data

        # query data
        if port_response is None and redfish_path is not None:
            port_response = plugin_object.rf.get_view(f"{redfish_path}{plugin_object.rf.vendor_data.expand_string}")

        if port_response is None:
            return NetworkPort()

        # get health status
        status_data = get_status_data(port_response.get("Status"))

        # get Link speed
        current_speed = \
            port_response.get("CurrentLinkSpeedMbps") or \
            grab(port_response, "SupportedLinkCapabilities.0.LinkSpeedMbps") or \
            grab(port_response, "SupportedLinkCapabilities.LinkSpeedMbps")

        if isinstance(current_speed, str):
            current_speed = current_speed.replace("Gbps", "000")

        if str(current_speed) == "-":
            current_speed = None

        # get port number
        if port_response.get("PhysicalPortNumber"):
            nic_port_name = "Port " + port_response.get("PhysicalPortNumber")
        else:
            nic_port_name = port_response.get("Name")

        if plugin_object.rf.vendor == "Cisco" and network_function_id is not None:
            port_id = f"{network_function_id}.{port_response.get('Id')}"
        else:
            port_id = port_response.get('Id')

        if plugin_object.rf.vendor != "Dell":
            port_id = f"{adapter_id}.{port_id}"

        # check if port has already be added
        if port_id in [p.id for p in plugin_object.inventory.get(NetworkPort)]:
            print(f"ALREADY in INVENTORY: {port_id}")
            return

        network_port_inventory = NetworkPort(
            id=port_id,
            name=port_response.get("Name"),
            port_name=nic_port_name,
            health_status=status_data.get("Health"),
            operation_status=status_data.get("State"),
            addresses=format_interface_addresses(grab(port_response, "AssociatedNetworkAddresses")),
            link_type=port_response.get("ActiveLinkTechnology"),
            autoneg=grab(port_response, "SupportedLinkCapabilities.0.AutoSpeedNegotiation"),
            current_speed=current_speed,
            capable_speed=grab(port_response, "SupportedLinkCapabilities.0.CapableLinkSpeedMbps.0"),
            link_status=f"{port_response.get('LinkStatus') or ''}".replace("Link", ""),
            system_ids=system_id
        )

        network_port_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                            port_response.get("Links"))
        network_port_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                            port_response.get("RelatedItem"))

        plugin_object.inventory.add(network_port_inventory)

        if plugin_object.cli_args.verbose:
            network_port_inventory.source_data = {"port": port_response}

        if return_data is True:
            return network_port_inventory

        return

    def get_network_function(function_data=None):

        # could be
        #  * a string
        #  * a dict with just the link
        #  * a dict with full data
        function_response = None
        redfish_path = None
        if isinstance(function_data, dict):

            if function_data.get("Id") is not None:
                function_response = function_data
            else:
                redfish_path = function_data.get("@odata.id")
        elif isinstance(function_data, str):
            redfish_path = function_data

        # query data
        if function_response is None and redfish_path is not None:
            function_response = plugin_object.rf.get_view(f"{redfish_path}{plugin_object.rf.vendor_data.expand_string}")

        port_inventory = None
        if function_response is not None:
            physical_port_path = grab(function_response, "Links.PhysicalPortAssignment") or \
                 grab(function_response, "PhysicalPortAssignment")

            if physical_port_path is None:
                return

            network_function_id = function_response.get("Id")

            port_inventory = get_network_port(physical_port_path, network_function_id, True)

            if plugin_object.cli_args.verbose:
                source_data = getattr(port_inventory, "source_data")
                source_data["function"] = function_response

                port_inventory.update("source_data", source_data)

            port_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                        function_response.get("Links"))
            port_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                        function_response.get("RelatedItem"))

            # get health status
            status_data = get_status_data(function_response.get("Status"))

            if port_inventory.health_status is None:
                port_inventory.health_status = status_data.get("Health")

            if port_inventory.operation_status is None:
                port_inventory.operation_status = status_data.get("State")

            # get and sanitize MAC and WWPN addresses
            port_inventory.update("addresses",
                                  format_interface_addresses(grab(function_response, "Ethernet.PermanentMACAddress")) +
                                  format_interface_addresses(grab(function_response, "Ethernet.MACAddress")) +
                                  format_interface_addresses(grab(function_response, "FibreChannel.PermanentWWPN")) +
                                  format_interface_addresses(grab(function_response, "FibreChannel.WWPN")),
                                  append=True)

            # set VLAN settings
            port_inventory.vlan_id = grab(function_response, "Ethernet.VLAN.VLANId")
            port_inventory.vlan_enabled = grab(function_response, "Ethernet.VLAN.VLANEnable")

            # get IP addresses
            vendor_data = grab(function_response, f"Oem.{plugin_object.rf.vendor_dict_key}")

            if vendor_data is not None:
                port_inventory.ipv4_addresses = get_interface_ip_addresses(vendor_data, "IPv4Addresses")
                port_inventory.ipv6_addresses = get_interface_ip_addresses(vendor_data, "IPv6Addresses")

            # set link type
            port_inventory.update("link_type", function_response.get("NetDevFuncType"))

            if plugin_object.rf.vendor == "Cisco":
                port_inventory.update("os_name", function_response.get("Name"))

            if plugin_object.rf.vendor == "Dell":
                duplex_setting = \
                    grab(function_response, f"Oem.{plugin_object.rf.vendor_dict_key}.DellNIC.LinkDuplex") or ""
                if "full" in duplex_setting.lower():
                    port_inventory.update("full_duplex", True)
                elif "half" in duplex_setting.lower():
                    port_inventory.update("full_duplex", False)

                port_inventory.update("name", grab(function_response,
                                                   f"Oem.{plugin_object.rf.vendor_dict_key}.DellNIC.DeviceDescription"))

        return port_inventory

    plugin_object.set_current_command("NICs")

    system_id = redfish_url.rstrip("/").split("/")[-1]

    if plugin_object.rf.vendor == "HPE":
        system_response = plugin_object.rf.get(redfish_url)

        ethernet_interfaces_path = grab(system_response,
                                        f"Oem/{plugin_object.rf.vendor_dict_key}/Links/EthernetInterfaces/@odata.id",
                                        separator="/")
        network_adapter_path = grab(system_response,
                                    f"Oem/{plugin_object.rf.vendor_dict_key}/Links/NetworkAdapters/@odata.id",
                                    separator="/")
    else:
        ethernet_interfaces_path = f"{redfish_url}/EthernetInterfaces"
        network_adapter_path = f"{redfish_url}/NetworkInterfaces"

    network_adapter_response = \
        plugin_object.rf.get_view(f"{network_adapter_path}{plugin_object.rf.vendor_data.expand_string}")

    # HPE specific
    if network_adapter_response.get("NetworkAdapters") is not None:
        network_adapter_members = network_adapter_response.get("NetworkAdapters")
    else:
        network_adapter_members = network_adapter_response.get("Members")

    if network_adapter_members and len(network_adapter_members) > 0:

        for adapter in network_adapter_members:

            if adapter.get("Id") is not None:
                nic_member = adapter
            else:
                nic_member = plugin_object.rf.get(adapter.get("@odata.id"))

            adapter_path = grab(nic_member, "Links/NetworkAdapter/@odata.id", separator="/") or \
                grab(nic_member, "Links.NetworkAdapter.0")

            # HPE systems
            num_ports = 0
            network_ports = None
            network_functions = None

            if adapter_path is None:

                status_data = get_status_data(nic_member.get("Status"))
                adapter_id = nic_member.get("Id")
                manufacturer = None
                name = nic_member.get("Name")
                model = nic_member.get("Model")
                part_number = nic_member.get("PartNumber")
                serial = nic_member.get("SerialNumber")
                firmware = grab(nic_member, "Firmware.Current.VersionString")

                source_data = nic_member
                num_ports = len(nic_member.get("PhysicalPorts") or list())
            else:
                adapter_response = plugin_object.rf.get(adapter_path)

                source_data = adapter_response

                status_data = get_status_data(adapter_response.get("Status"))

                adapter_id = adapter_response.get("Id")
                manufacturer = adapter_response.get("Manufacturer")
                name = adapter_response.get("Name")
                model = adapter_response.get("Model")
                part_number = adapter_response.get("PartNumber")
                serial = adapter_response.get("SerialNumber")
                firmware = grab(adapter_response, "Firmware.Current.VersionString")

                adapter_controllers = adapter_response.get("Controllers") or list()

                if isinstance(adapter_controllers, dict):
                    adapter_controllers = [adapter_controllers]

                for controller in adapter_controllers:
                    firmware = grab(controller, "FirmwarePackageVersion")

                    network_ports = grab(controller, "Links.NetworkPorts") or \
                        grab(controller, "Link.NetworkPorts")
                    network_functions = grab(controller, "Links.NetworkDeviceFunctions") or \
                        grab(controller, "Link.NetworkDeviceFunctions")

                    num_ports = len(network_ports)

            adapter_inventory = NetworkAdapter(
                id=adapter_id,
                name=name,
                health_status=status_data.get("Health"),
                operation_status=status_data.get("State"),
                model=model,
                manufacturer=manufacturer,
                num_ports=num_ports,
                firmware=firmware,
                part_number=part_number,
                serial=serial,
                system_ids=system_id
            )

            discovered_network_ports = 0
            for network_function in network_functions or list():
                port_inventory_data = get_network_function(network_function)

                if port_inventory_data is not None:
                    adapter_inventory.update("port_ids", port_inventory_data.id, True)

                    port_inventory_data.update("adapter_id", adapter_inventory.id)

                    discovered_network_ports += 1

            if discovered_network_ports == 0:
                for network_port in network_ports or list():
                    port_inventory_data = get_network_port(network_port, return_data=True)

                    if port_inventory_data is not None:
                        adapter_inventory.update("port_ids", port_inventory_data.id, True)

                        port_inventory_data.update("adapter_id", adapter_inventory.id)

            # special case for HPE
            if plugin_object.rf.vendor == "HPE" and len(nic_member.get("PhysicalPorts") or list()) > 0:

                num_port = 0
                for network_port in nic_member.get("PhysicalPorts") or list():
                    num_port += 1

                    port_id = f"{adapter_inventory.id}.{num_port}"

                    status_data = get_status_data(network_port.get("Status"))

                    network_port_inventory = NetworkPort(
                        id=port_id,
                        adapter_id=adapter_inventory.id,
                        os_name=network_port.get("Name"),
                        port_name=num_port,
                        health_status=status_data.get("Health"),
                        operation_status=status_data.get("State"),
                        addresses=format_interface_addresses(grab(network_port, "MacAddress")),
                        ipv4_addresses=get_interface_ip_addresses(network_port, "IPv4Addresses"),
                        ipv6_addresses=get_interface_ip_addresses(network_port, "IPv6Addresses"),
                        full_duplex=grab(network_port, "FullDuplex"),
                        current_speed=grab(network_port, "SpeedMbps"),
                        link_status=f"{network_port.get('LinkStatus') or ''}".replace("Link", ""),
                        system_ids=system_id
                    )

                    adapter_inventory.update("port_ids", port_id, True)

                    plugin_object.inventory.add(network_port_inventory)

                    if plugin_object.cli_args.verbose:
                        network_port_inventory.source_data = {"port": network_port}

            if plugin_object.cli_args.verbose:
                adapter_inventory.source_data = source_data

            plugin_object.inventory.add(adapter_inventory)

    if len(plugin_object.inventory.get(NetworkPort)) == 0:
        ethernet_interface_response = \
            plugin_object.rf.get_view(f"{ethernet_interfaces_path}{plugin_object.rf.vendor_data.expand_string}")

        # HPE specific
        if ethernet_interface_response.get("EthernetInterfaces") is not None:
            ethernet_interface_members = ethernet_interface_response.get("EthernetInterfaces")
        else:
            ethernet_interface_members = ethernet_interface_response.get("Members")

        if ethernet_interface_members and len(ethernet_interface_members) > 0:

            for interface in ethernet_interface_members:

                if interface.get("Id") is not None:
                    interface_member = interface
                else:
                    interface_member = plugin_object.rf.get(interface.get("@odata.id"))

                if interface_member.get("Id"):

                    # get health status
                    status_data = get_status_data(interface_member.get("Status"))

                    addresses = interface_member.get("PermanentMACAddress") or interface_member.get("MACAddress")

                    port_inventory = NetworkPort(
                        id=interface_member.get("Id"),
                        name=interface_member.get("Name"),
                        health_status=status_data.get("Health"),
                        operation_status=status_data.get("State"),
                        link_status=interface_member.get("LinkStatus"),
                        addresses=format_interface_addresses(addresses),
                        current_speed=interface_member.get("SpeedMbps"),
                        system_ids=system_id
                    )

                    if plugin_object.cli_args.verbose:
                        port_inventory.source_data = interface_member

                    # add relations
                    port_inventory.add_relation(plugin_object.rf.get_system_properties(), interface_member.get("Links"))
                    port_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                                interface_member.get("RelatedItem"))

                    plugin_object.inventory.add(port_inventory)

    def add_port_status(port_inventory_item):

        plugin_status = port_status = port_inventory_item.health_status

        if port_status is None:
            port_status = port_inventory_item.operation_status

        if plugin_status is None and port_status == "Enabled":
            plugin_status = "OK"

        if plugin_status is None:
            plugin_status = "OK"

        ip_addresses_string = None
        ip_addresses = [*port_inventory_item.ipv4_addresses, *port_inventory_item.ipv6_addresses]
        if len(ip_addresses) > 0:
            ip_addresses_string = "/".join(ip_addresses)

        duplex = autoneg = None
        if port_inventory_item.full_duplex is not None:
            duplex = "full" if port_inventory_item.full_duplex is True else "half"
        if port_inventory_item.autoneg is not None:
            autoneg = "on" if port_inventory_item.autoneg is True else "off"

        status_text = f"Port {port_inventory_item.id} "

        if port_inventory_item.os_name is not None:
            status_text += f"(OS name: {port_inventory_item.os_name}) "

        if ip_addresses_string is not None:
            status_text += f"(IPs: {ip_addresses_string}) "

        status_text += f"(type: {port_inventory_item.link_type}, " \
                       f"speed: {port_inventory_item.current_speed}, " \
                       f"autoneg: {autoneg}, duplex: {duplex}) "

        if port_status is not None:
            status_text += f"status: {port_status}, "

        status_text += f"link: {port_inventory_item.link_status}"

        plugin_object.add_output_data("CRITICAL" if plugin_status not in ["OK", "WARNING"] else plugin_status,
                                      status_text)

    adapter_inventory = plugin_object.inventory.get(NetworkAdapter)
    port_inventory = plugin_object.inventory.get(NetworkPort)

    num_adapters = len(adapter_inventory)
    num_ports = len(port_inventory)

    for network_adapter in adapter_inventory:

        plugin_status = adapter_status = network_adapter.health_status

        if adapter_status is None:
            adapter_status = network_adapter.operation_status

        if plugin_status is None and adapter_status == "Enabled":
            plugin_status = "OK"

        if plugin_status is None:
            plugin_status = "OK"

        adapter_name = network_adapter.model \
            if len(network_adapter.model or '') > len(network_adapter.name or '') else network_adapter.name

        if plugin_object.rf.vendor in ["Huawei", "Cisco", "Dell"] and \
                not all(v is None for v in [network_adapter.model, network_adapter.manufacturer]):
            adapter_name = f"{network_adapter.manufacturer} {network_adapter.model}"

        status_text = f"Adapter {adapter_name} (FW: {network_adapter.firmware}) status: {adapter_status}"

        plugin_object.add_output_data("CRITICAL" if plugin_status not in ["OK", "WARNING"] else plugin_status,
                                      status_text)

        for network_port in port_inventory:
            if str(network_port.adapter_id) == str(network_adapter.id):
                add_port_status(network_port)

    for network_port in port_inventory:
        if network_port.adapter_id is None:
            add_port_status(network_port)

    if num_ports == 0:
        plugin_object.add_output_data("UNKNOWN", f"No network adapter or interface data "
                                                 f"returned for API URL '{network_adapter_path}'")

    plugin_object.add_output_data("OK", f"All network adapter ({num_adapters}) and "
                                        f"ports ({num_ports}) are in good condition", summary=True)

    return
Exemplo n.º 2
0
    def get_network_port(port_data=None, network_function_id=None, return_data=False):

        # could be
        #  * a string
        #  * a dict with just the link
        #  * a dict with full data
        port_response = None
        redfish_path = None
        if isinstance(port_data, dict):

            if port_data.get("Id") is not None:
                port_response = port_data
            else:
                redfish_path = port_data.get("@odata.id")

        elif isinstance(port_data, str):
            redfish_path = port_data

        # query data
        if port_response is None and redfish_path is not None:
            port_response = plugin_object.rf.get_view(f"{redfish_path}{plugin_object.rf.vendor_data.expand_string}")

        if port_response is None:
            return NetworkPort()

        # get health status
        status_data = get_status_data(port_response.get("Status"))

        # get Link speed
        current_speed = \
            port_response.get("CurrentLinkSpeedMbps") or \
            grab(port_response, "SupportedLinkCapabilities.0.LinkSpeedMbps") or \
            grab(port_response, "SupportedLinkCapabilities.LinkSpeedMbps")

        if isinstance(current_speed, str):
            current_speed = current_speed.replace("Gbps", "000")

        if str(current_speed) == "-":
            current_speed = None

        # get port number
        if port_response.get("PhysicalPortNumber"):
            nic_port_name = "Port " + port_response.get("PhysicalPortNumber")
        else:
            nic_port_name = port_response.get("Name")

        if plugin_object.rf.vendor == "Cisco" and network_function_id is not None:
            port_id = f"{network_function_id}.{port_response.get('Id')}"
        else:
            port_id = port_response.get('Id')

        if plugin_object.rf.vendor != "Dell":
            port_id = f"{adapter_id}.{port_id}"

        # check if port has already be added
        if port_id in [p.id for p in plugin_object.inventory.get(NetworkPort)]:
            print(f"ALREADY in INVENTORY: {port_id}")
            return

        network_port_inventory = NetworkPort(
            id=port_id,
            name=port_response.get("Name"),
            port_name=nic_port_name,
            health_status=status_data.get("Health"),
            operation_status=status_data.get("State"),
            addresses=format_interface_addresses(grab(port_response, "AssociatedNetworkAddresses")),
            link_type=port_response.get("ActiveLinkTechnology"),
            autoneg=grab(port_response, "SupportedLinkCapabilities.0.AutoSpeedNegotiation"),
            current_speed=current_speed,
            capable_speed=grab(port_response, "SupportedLinkCapabilities.0.CapableLinkSpeedMbps.0"),
            link_status=f"{port_response.get('LinkStatus') or ''}".replace("Link", ""),
            system_ids=system_id
        )

        network_port_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                            port_response.get("Links"))
        network_port_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                            port_response.get("RelatedItem"))

        plugin_object.inventory.add(network_port_inventory)

        if plugin_object.cli_args.verbose:
            network_port_inventory.source_data = {"port": port_response}

        if return_data is True:
            return network_port_inventory

        return
Exemplo n.º 3
0
def get_bmc_info_generic(plugin_object, redfish_url):
    """
    Possible Info to add
    * NTP Status
    * NTP servers configured
    * BMC accounts
    * BIOS settings (maybe, varies a lot between vendors)
    """

    view_response = plugin_object.rf.get_view(f"{redfish_url}{plugin_object.rf.vendor_data.expand_string}")

    if view_response.get("error"):
        plugin_object.add_data_retrieval_error(Manager, view_response, redfish_url)
        return

    # HPE iLO 5 view
    if view_response.get("ILO"):
        manager_response = view_response.get("ILO")[0]
    else:
        manager_response = view_response

    # get model
    bmc_model = manager_response.get("Model")
    bmc_fw_version = manager_response.get("FirmwareVersion")

    if plugin_object.rf.vendor == "HPE":
        bmc_model = " ".join(bmc_fw_version.split(" ")[0:2])

    if plugin_object.rf.vendor == "Dell":
        if bmc_model == "13G Monolithic":
            bmc_model = "iDRAC 8"
        if bmc_model in ["14G Monolithic", "15G Monolithic"]:
            bmc_model = "iDRAC 9"

    # some Cisco Systems have a second manager with no attributes which needs to be skipped
    if plugin_object.rf.vendor == "Cisco":
        if manager_response.get("Status") is None:
            return

    status_text = f"BMC: {bmc_model} (Firmware: {bmc_fw_version})"

    # get status data
    status_data = get_status_data(manager_response.get("Status"))
    manager_inventory = Manager(
        id=manager_response.get("Id"),
        type=manager_response.get("ManagerType"),
        name=manager_response.get("Name"),
        health_status=status_data.get("Health"),
        operation_status=status_data.get("State"),
        model=bmc_model,
        firmware=bmc_fw_version
    )

    if plugin_object.cli_args.verbose:
        manager_inventory.source_data = manager_response

    # add relations
    manager_inventory.add_relation(plugin_object.rf.get_system_properties(), manager_response.get("Links"))

    plugin_object.inventory.add(manager_inventory)

    # workaround for older ILO versions
    if manager_inventory.health_status is not None:
        bmc_status = manager_inventory.health_status
    elif manager_inventory.operation_status == "Enabled":
        bmc_status = "OK"
    else:
        bmc_status = "UNKNOWN"

    # BMC Network interfaces
    manager_nic_response = None
    manager_nic_member = None

    if plugin_object.rf.vendor == "HPE" and view_response.get("ILOInterfaces") is not None:
        manager_nic_response = {"Members": view_response.get("ILOInterfaces")}
    else:
        manager_nics_link = grab(manager_response, "EthernetInterfaces/@odata.id", separator="/")
        if manager_nics_link is not None:
            redfish_url = f"{manager_nics_link}{plugin_object.rf.vendor_data.expand_string}"
            manager_nic_response = plugin_object.rf.get(redfish_url)

            if manager_nic_response.get("error"):
                plugin_object.add_data_retrieval_error(NetworkPort, manager_nic_response, redfish_url)

    if manager_nic_response is not None:

        if manager_nic_response.get("Members") is None or len(manager_nic_response.get("Members")) == 0:

            status_text = f"{status_text} but no information about the BMC network interfaces found"

            plugin_object.inventory.add_issue(NetworkPort, "No information about the BMC network interfaces found")
        else:

            # if args.detailed is False:
            status_text = f"{status_text} and all nics are in 'OK' state."

            for manager_nic_member in manager_nic_response.get("Members"):

                if manager_nic_member.get("@odata.context"):
                    manager_nic = manager_nic_member
                else:
                    manager_nic = plugin_object.rf.get(manager_nic_member.get("@odata.id"))

                    if manager_nic.get("error"):
                        plugin_object.add_data_retrieval_error(NetworkPort, manager_nic,
                                                               manager_nic_member.get("@odata.id"))
                        continue

                status_data = get_status_data(manager_nic.get("Status"))

                if plugin_object.rf.vendor == "Dell":
                    interface_id = manager_nic.get("Id")
                else:
                    interface_id = "{}:{}".format(manager_inventory.id, manager_nic.get("Id"))

                vlan_id = grab(manager_nic, "VLAN.VLANId")
                if vlan_id is None:
                    vlan_id = grab(manager_nic, "VLANId")

                vlan_enabled = grab(manager_nic, "VLAN.VLANEnable")
                if vlan_enabled is None:
                    vlan_enabled = grab(manager_nic, "VLANEnable")

                network_inventory = NetworkPort(
                    id=interface_id,
                    name=manager_nic.get("Name"),
                    health_status=status_data.get("Health"),
                    operation_status=status_data.get("State"),
                    current_speed=manager_nic.get("SpeedMbps"),
                    autoneg=manager_nic.get("AutoNeg"),
                    full_duplex=manager_nic.get("FullDuplex"),
                    hostname=manager_nic.get("HostName"),
                    addresses=format_interface_addresses(manager_nic.get("PermanentMACAddress")),
                    manager_ids=manager_inventory.id,
                    system_ids=manager_inventory.system_ids,
                    chassi_ids=manager_inventory.chassi_ids,
                    ipv4_addresses=get_interface_ip_addresses(manager_nic, "IPv4Addresses"),
                    ipv6_addresses=get_interface_ip_addresses(manager_nic, "IPv6Addresses"),
                    link_type="Ethernet",
                    link_status=f"{manager_nic.get('LinkStatus') or ''}".replace("Link", ""),
                    vlan_id=vlan_id,
                    vlan_enabled=vlan_enabled,
                )

                if plugin_object.cli_args.verbose:
                    network_inventory.source_data = manager_nic

                plugin_object.inventory.add(network_inventory)

                # if we are connected wie via interface IP address then we can assume the link is up
                if network_inventory.link_status is None:
                    for address in network_inventory.ipv4_addresses + network_inventory.ipv6_addresses:
                        if address in plugin_object.cli_args.host:
                            network_inventory.link_status = "Up"

                if plugin_object.rf.vendor == "Cisco" and manager_nic.get("InterfaceEnabled") is True:
                    network_inventory.operation_status = "Enabled"

                # Huawei is completely missing any status information
                if plugin_object.rf.vendor == "Huawei" and network_inventory.operation_status is None:
                    network_inventory.operation_status = "Enabled"

                if network_inventory.health_status:
                    nic_status = network_inventory.health_status
                elif network_inventory.operation_status == "Enabled":
                    nic_status = "OK"
                else:
                    nic_status = "UNKNOWN"

                if network_inventory.operation_status in ["Disabled", None]:
                    continue

                host_name = network_inventory.hostname or "no hostname set"

                ip_addresses_string = None
                ip_addresses = [*network_inventory.ipv4_addresses, *network_inventory.ipv6_addresses]
                if len(ip_addresses) > 0:
                    ip_addresses_string = "/".join(ip_addresses)

                duplex = autoneg = None
                if network_inventory.full_duplex is not None:
                    duplex = "full" if network_inventory.full_duplex is True else "half"
                    if nic_status == "OK" and duplex == "half" and network_inventory.current_speed is not None:
                        nic_status = "WARNING"
                        duplex += f" ({nic_status})"

                if network_inventory.autoneg is not None:
                    autoneg = "on" if network_inventory.autoneg is True else "off"

                nic_status_text = f"NIC {network_inventory.id} '{host_name}' (IPs: {ip_addresses_string}) "
                nic_status_text += f"(speed: {network_inventory.current_speed}, " \
                                   f"autoneg: {autoneg}, duplex: {duplex}) status: {nic_status}"

                plugin_object.add_output_data("CRITICAL" if nic_status not in ["OK", "WARNING"] else nic_status,
                                              nic_status_text, location=f"Manager {manager_inventory.id}")

    # get vendor information
    vendor_data = grab(manager_response, f"Oem.{plugin_object.rf.vendor_dict_key}")

    # get license information
    bmc_licenses = list()
    if plugin_object.rf.vendor == "HPE":

        ilo_license_string = grab(vendor_data, "License.LicenseString")
        ilo_license_key = grab(vendor_data, "License.LicenseKey")

        bmc_licenses.append(f"{ilo_license_string} ({ilo_license_key})")

    elif plugin_object.rf.vendor == "Lenovo":

        fod_link = grab(vendor_data, "FoD/@odata.id", separator="/")

        if fod_link is not None:
            fod_url = f"{fod_link}/Keys{plugin_object.rf.vendor_data.expand_string}"
            fod_data = plugin_object.rf.get(fod_url)

            if fod_data.get("error"):
                plugin_object.add_data_retrieval_error(Manager, fod_data, fod_url)

            for fod_member in fod_data.get("Members", list()):
                if manager_nic_member is not None and manager_nic_member.get("@odata.context"):
                    licenses_data = fod_member
                else:
                    licenses_data = plugin_object.rf.get(fod_member.get("@odata.id"))

                lic_status = licenses_data.get("Status")  # valid
                lic_expire_date = licenses_data.get("Expires")  # NO CONSTRAINTS
                lic_description = licenses_data.get("Description")

                license_string = f"{lic_description}"
                if lic_expire_date != "NO CONSTRAINTS":
                    license_string += " (expires: {lic_expire_date}"

                license_string += f" Status: {lic_status}"
                bmc_licenses.append(license_string)

    elif plugin_object.rf.vendor == "Fujitsu":

        # get configuration
        irmc_configuration_link = grab(vendor_data, f"iRMCConfiguration/@odata.id", separator="/")

        irmc_configuration = None
        if irmc_configuration_link is not None:
            irmc_configuration = plugin_object.rf.get(irmc_configuration_link)

            if irmc_configuration.get("error"):
                plugin_object.add_data_retrieval_error(Manager, irmc_configuration, irmc_configuration_link)

        license_information = None
        license_information_link = grab(irmc_configuration, f"Licenses/@odata.id", separator="/")
        if license_information_link is not None:
            license_information = plugin_object.rf.get(license_information_link)

            if license_information.get("error"):
                plugin_object.add_data_retrieval_error(Manager, license_information, license_information_link)

        if license_information is not None and license_information.get("*****@*****.**") > 0:
            for bmc_license in license_information.get("Keys"):
                bmc_licenses.append("%s (%s)" % (bmc_license.get("Name"), bmc_license.get("Type")))

    elif plugin_object.rf.vendor == "Huawei":

        ibmc_license_link = vendor_data.get("LicenseService")

        if ibmc_license_link is not None and len(ibmc_license_link) > 0:
            ibmc_lic = plugin_object.rf.get(ibmc_license_link.get("@odata.id"))

            if ibmc_lic.get("error"):
                plugin_object.add_data_retrieval_error(Manager, ibmc_lic, ibmc_license_link.get("@odata.id"))

            bmc_licenses.append("%s (%s)" % (ibmc_lic.get("InstalledStatus"), ibmc_lic.get("LicenseClass")))

    manager_inventory.licenses = bmc_licenses

    for bmc_license in bmc_licenses:
        plugin_object.add_output_data("OK", f"BMC License: {bmc_license}", location=f"Manager {manager_inventory.id}")

    # HP ILO specific stuff
    if plugin_object.rf.vendor == "HPE":

        # iLO Self Test
        for self_test in vendor_data.get("iLOSelfTestResults"):

            self_test_status = self_test.get("Status")

            if self_test_status in ["Informational", None]:
                continue

            self_test_status = self_test_status.upper()

            self_test_name = self_test.get("SelfTestName")
            self_test_notes = self_test.get("Notes")

            if self_test_notes is not None and len(self_test_notes) != 0:
                self_test_notes = self_test_notes.strip()
                self_test_status_text = f"BMC SelfTest {self_test_name} ({self_test_notes}) status: {self_test_status}"
            else:
                self_test_status_text = f"BMC SelfTest {self_test_name} status: {self_test_status}"

            plugin_object.add_output_data("CRITICAL" if self_test_status not in ["OK", "WARNING"] else self_test_status,
                                          self_test_status_text, location=f"Manager {manager_inventory.id}")

    # Lenovo specific stuff
    if plugin_object.rf.vendor == "Lenovo":
        redfish_chassi_url = grab(manager_response, "Links/ManagerForChassis/0/@odata.id", separator="/")

        chassi_response = None
        if redfish_chassi_url is not None:
            chassi_response = plugin_object.rf.get(redfish_chassi_url)

            if chassi_response.get("error"):
                plugin_object.add_data_retrieval_error(Manager, chassi_response, redfish_chassi_url)

        located_data = grab(chassi_response, f"Oem.{plugin_object.rf.vendor_dict_key}.LocatedIn")

        if located_data is not None:
            descriptive_name = located_data.get("DescriptiveName")
            rack = located_data.get("Rack")

            system_name_string = f"System name: {descriptive_name} ({rack})"
            if plugin_object.cli_args.detailed:
                plugin_object.add_output_data("OK", f"BMC {system_name_string}",
                                              location=f"Manager {manager_inventory.id}")
            else:
                status_text += f" {system_name_string}"

    # get running firmware information from Fujitsu server
    if plugin_object.rf.vendor == "Fujitsu":

        for bmc_firmware in get_firmware_info_fujitsu(plugin_object, redfish_url, True):
            plugin_object.add_output_data("OK", "BMC Firmware: %s: %s" %
                                          (bmc_firmware.get("name"), bmc_firmware.get("version")),
                                          location=f"Manager {manager_inventory.id}")

    # get Huawei Server location data
    if plugin_object.rf.vendor == "Huawei":

        ibmc_location = vendor_data.get("DeviceLocation")
        if ibmc_location is not None and len(ibmc_location) > 0:

            location_string = f"Location: {ibmc_location}"
            if plugin_object.cli_args.detailed:
                plugin_object.add_output_data("OK", f"BMC {location_string}",
                                              location=f"Manager {manager_inventory.id}")
            else:
                status_text += f" {location_string}"

    plugin_object.add_output_data("CRITICAL" if bmc_status not in ["OK", "WARNING"] else bmc_status, status_text,
                                  summary=True, location=f"Manager {manager_inventory.id}")

    return