Exemple #1
0
def get_single_chassi_info(plugin_object, redfish_url):
    chassi_response = plugin_object.rf.get(redfish_url)

    # get status data
    status_data = get_status_data(chassi_response.get("Status"))

    chassi_inventory = Chassi(
        id=chassi_response.get("Id"),
        name=chassi_response.get("Name"),
        manufacturer=chassi_response.get("Manufacturer"),
        serial=chassi_response.get("SerialNumber"),
        health_status=status_data.get("Health"),
        operation_status=status_data.get("State"),
        sku=chassi_response.get("SKU"),
        indicator_led=chassi_response.get("IndicatorLED"),
        model=chassi_response.get("Model"),
        type=chassi_response.get("ChassisType"))

    if plugin_object.cli_args.verbose:
        chassi_inventory.source_data = chassi_response

    # add relations
    chassi_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                  chassi_response.get("Links"))

    plugin_object.inventory.add(chassi_inventory)

    return
Exemple #2
0
def get_single_chassi_info(plugin_object, redfish_url):
    chassi_response = plugin_object.rf.get(redfish_url)

    if chassi_response is None:
        plugin_object.inventory.add_issue(Chassi, f"No chassi information data returned for API URL '{redfish_url}'")
        return
    elif chassi_response.get("error"):
        plugin_object.add_data_retrieval_error(Chassi, chassi_response, redfish_url)
        return

    # get status data
    status_data = get_status_data(chassi_response.get("Status"))

    chassi_inventory = Chassi(
        id=chassi_response.get("Id"),
        name=chassi_response.get("Name"),
        manufacturer=chassi_response.get("Manufacturer"),
        serial=chassi_response.get("SerialNumber"),
        health_status=status_data.get("Health"),
        operation_status=status_data.get("State"),
        sku=chassi_response.get("SKU"),
        indicator_led=chassi_response.get("IndicatorLED"),
        model=chassi_response.get("Model"),
        type=chassi_response.get("ChassisType")
    )

    if plugin_object.cli_args.verbose:
        chassi_inventory.source_data = chassi_response

    # add relations
    chassi_inventory.add_relation(plugin_object.rf.get_system_properties(), chassi_response.get("Links"))

    plugin_object.inventory.add(chassi_inventory)

    return
Exemple #3
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
Exemple #4
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
Exemple #5
0
    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
Exemple #6
0
def get_single_chassi_temp(plugin_object, redfish_url):

    plugin_object.set_current_command("Temp")

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

    redfish_url = f"{redfish_url}/Thermal"

    thermal_data = plugin_object.rf.get_view(redfish_url)

    if thermal_data.get("error"):
        plugin_object.add_data_retrieval_error(Temperature, thermal_data,
                                               redfish_url)
        return

    default_text = ""
    temp_num = 0
    if "Temperatures" in thermal_data:

        for temp in thermal_data.get("Temperatures"):

            status_data = get_status_data(grab(temp, "Status"))

            status = status_data.get("Health")
            state = status_data.get("State")

            name = temp.get("Name")
            member_id = grab(temp, "MemberId")

            if member_id is None:
                member_id = name

            temp_inventory = Temperature(
                name=name,
                id=member_id,
                health_status=status,
                operation_status=state,
                physical_context=temp.get("PhysicalContext"),
                min_reading=temp.get("MinReadingRangeTemp"),
                max_reading=temp.get("MaxReadingRangeTemp"),
                lower_threshold_non_critical=None
                if temp.get("LowerThresholdNonCritical") == "N/A" else
                temp.get("LowerThresholdNonCritical"),
                lower_threshold_critical=None
                if temp.get("LowerThresholdCritical") == "N/A" else
                temp.get("LowerThresholdCritical"),
                lower_threshold_fatal=None if temp.get("LowerThresholdFatal")
                == "N/A" else temp.get("LowerThresholdFatal"),
                upper_threshold_non_critical=None
                if temp.get("UpperThresholdNonCritical") == "N/A" else
                temp.get("UpperThresholdNonCritical"),
                upper_threshold_critical=None
                if temp.get("UpperThresholdCritical") == "N/A" else
                temp.get("UpperThresholdCritical"),
                upper_threshold_fatal=None if temp.get("UpperThresholdFatal")
                == "N/A" else temp.get("UpperThresholdFatal"),
                chassi_ids=chassi_id)

            if plugin_object.cli_args.verbose:
                temp_inventory.source_data = temp

            temp_inventory.reading_unit = "Celsius"
            if temp.get("ReadingCelsius") is not None:
                temp_inventory.reading = temp.get("ReadingCelsius")
            elif temp.get("ReadingFahrenheit") is not None:
                temp_inventory.reading = temp.get("ReadingFahrenheit")
                temp_inventory.reading_unit = "Fahrenheit"
            else:
                temp_inventory.reading = 0

            # add relations
            temp_inventory.add_relation(
                plugin_object.rf.get_system_properties(), temp.get("Links"))
            temp_inventory.add_relation(
                plugin_object.rf.get_system_properties(),
                temp.get("RelatedItem"))

            plugin_object.inventory.add(temp_inventory)

            if state in ["Absent", "Disabled", "UnavailableOffline"]:
                continue

            if status is None:
                status = "OK" if state == "Enabled" else state

            current_temp = temp_inventory.reading
            critical_temp = temp_inventory.upper_threshold_critical
            warning_temp = temp_inventory.upper_threshold_non_critical

            temp_num += 1

            if str(warning_temp) in ["0", "N/A"]:
                warning_temp = None

            if warning_temp is not None and float(current_temp) >= float(
                    warning_temp):
                status = "WARNING"

            if str(critical_temp) in ["0", "N/A"]:
                critical_temp = None

            if critical_temp is not None and float(current_temp) >= float(
                    critical_temp):
                status = "CRITICAL"

            critical_temp_text = "N/A"
            if critical_temp is not None:
                critical_temp_text = "%.1f" % float(critical_temp)

            status_text = f"Temp sensor {temp_inventory.name} status is: " \
                          f"{status} (%.1f °C) (max: {critical_temp_text} °C)" % current_temp

            plugin_object.add_output_data(
                "CRITICAL" if status not in ["OK", "WARNING"] else status,
                status_text,
                location=f"Chassi {chassi_id}")

            plugin_object.add_perf_data(f"temp_{temp_inventory.name}",
                                        float(current_temp),
                                        warning=warning_temp,
                                        critical=critical_temp,
                                        location=f"Chassi {chassi_id}")

        default_text = f"All temp sensors ({temp_num}) are in good condition"
    else:
        default_text = "no temp sensors detected"
        plugin_object.inventory.add_issue(
            Temperature,
            f"No temp sensor data returned for API URL '{redfish_url}'")

    plugin_object.add_output_data("OK",
                                  default_text,
                                  summary=True,
                                  location=f"Chassi {chassi_id}")

    return
Exemple #7
0
def get_single_system_info(plugin_object, redfish_url):
    system_response = plugin_object.rf.get(redfish_url)

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

    if system_response is None:
        plugin_object.inventory.add_issue(System, f"No system information data returned for API URL '{redfish_url}'")
        return
    elif system_response.get("error"):
        plugin_object.add_data_retrieval_error(System, system_response, redfish_url)
        return

    # get model data
    model = system_response.get("Model")
    # Huawei system
    if plugin_object.rf.vendor == "Huawei":
        huawei_model = grab(system_response, f"Oem.{plugin_object.rf.vendor_dict_key}.ProductName")

        if huawei_model is not None:
            model = huawei_model

    # get memory size
    mem_size = grab(system_response, "MemorySummary.TotalSystemMemoryGiB")

    # Dell system
    # just WHY?
    if plugin_object.rf.vendor == "Dell" and mem_size is not None and int(mem_size) % 16 != 0:
        mem_size = round(mem_size * 1024 ** 3 / 1000 ** 3)

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

    system_inventory = System(
        id=system_response.get("Id"),
        name=system_response.get("Name"),
        manufacturer=system_response.get("Manufacturer"),
        serial=system_response.get("SerialNumber"),
        health_status=status_data.get("Health"),
        operation_status=status_data.get("State"),
        power_state=system_response.get("PowerState"),
        bios_version=system_response.get("BiosVersion"),
        host_name=system_response.get("HostName"),
        indicator_led=system_response.get("IndicatorLED"),
        cpu_num=grab(system_response, "ProcessorSummary.Count"),
        part_number=system_response.get("PartNumber"),
        mem_size=mem_size,
        model=model,
        type=system_response.get("SystemType")
    )

    if plugin_object.cli_args.verbose:
        system_inventory.source_data = system_response

    # add relations
    system_inventory.add_relation(plugin_object.rf.get_system_properties(), system_response.get("Links"))

    plugin_object.inventory.add(system_inventory)

    host_name = "NOT SET"
    if system_inventory.host_name is not None and len(system_inventory.host_name) > 0:
        host_name = system_inventory.host_name

    status_text = f"INFO: {system_inventory.manufacturer} {system_inventory.model} " \
                  f"(CPU: {system_inventory.cpu_num}, MEM: {system_inventory.mem_size}GB) - " \
                  f"BIOS: {system_inventory.bios_version} - " \
                  f"Serial: {system_inventory.serial} - " \
                  f"Power: {system_inventory.power_state} - Name: {host_name}"

    system_health_print_status = \
        "CRITICAL" if system_inventory.health_status not in ["OK", "WARNING"] else system_inventory.health_status

    # add DellSensorCollection if present
    dell_sensors = list()
    if plugin_object.rf.vendor == "Dell":

        dell_empty_slots = list()

        dell_slot_collection = \
            grab(system_response, f"Links.Oem.{plugin_object.rf.vendor_dict_key}.DellSlotCollection")

        # collect info about empty slots
        if dell_slot_collection is not None and dell_slot_collection.get("@odata.id") is not None:
            collection_response = plugin_object.rf.get(dell_slot_collection.get("@odata.id"))

            if collection_response is not None and (
                    collection_response.get("Members") is None or len(collection_response.get("Members")) > 0):

                for dell_slot in collection_response.get("Members"):

                    if dell_slot.get("EmptySlot") is True:
                        dell_empty_slots.append(dell_slot.get("Id"))

        dell_sensor_collection = \
            grab(system_response, f"Links.Oem.{plugin_object.rf.vendor_dict_key}.DellSensorCollection")

        if dell_sensor_collection is not None and dell_sensor_collection.get("@odata.id") is not None:
            collection_response = plugin_object.rf.get(dell_sensor_collection.get("@odata.id"))

            num_members = 0
            if collection_response is not None and (
                    collection_response.get("Members") is None or len(collection_response.get("Members")) > 0):

                for dell_sensor in collection_response.get("Members"):

                    # skip if sensor slot is empty
                    if any(x.startswith(dell_sensor.get("Id")) for x in dell_empty_slots):
                        continue

                    # skip unknown DIMM and CPU status for systems without DELL slot collection
                    # CPU Status as name
                    if dell_slot_collection is None or \
                            ("Status" in dell_sensor.get('ElementName') and "CPU" in dell_sensor.get('ElementName')):
                        if dell_sensor.get('CurrentState') == dell_sensor.get('HealthState') and \
                                dell_sensor.get('HealthState').upper() == "UNKNOWN":
                            continue

                    num_members += 1

                    this_sensor_status = "OK"

                    if dell_sensor.get('EnabledState') == "Enabled":
                        if "WARNING" in dell_sensor.get('HealthState').upper():
                            this_sensor_status = "WARNING"
                        elif dell_sensor.get('HealthState') != "OK":
                            this_sensor_status = "CRITICAL"

                    dell_sensors.append({this_sensor_status: 'Sensor "%s": %s (%s/%s)' % (
                        dell_sensor.get('ElementName'),
                        dell_sensor.get('HealthState'),
                        dell_sensor.get('EnabledState'),
                        dell_sensor.get('CurrentState')
                    )})

        # get the most severe state from system and sensors
        if len(dell_sensors) > 0:
            dell_sensor_states = [k for d in dell_sensors for k in d]
            system_health_print_status = \
                plugin_object.return_highest_status(dell_sensor_states + [system_health_print_status])

            if plugin_object.cli_args.detailed is False:
                dell_sensor_text = list()
                for status_type_name, _ in sorted(plugin_status_types.items(), key=lambda item: item[1], reverse=True):
                    state_count = dell_sensor_states.count(status_type_name)
                    if state_count == 1:
                        dell_sensor_text.append(f"{state_count} health sensor in '{status_type_name}' state")
                    elif state_count > 1:
                        dell_sensor_text.append(f"{state_count} health sensors are in '{status_type_name}' state")

                status_text += " - " + ", ".join(dell_sensor_text)

    plugin_object.add_output_data(system_health_print_status, status_text,
                                  summary=True,
                                  location=f"System {system_id}")

    for dell_sensor in dell_sensors:
        for status, sensor in dell_sensor.items():
            plugin_object.add_output_data(status, sensor, location=f"System {system_id}")

    # add ILO data
    if plugin_object.rf.vendor == "HPE":
        plugin_object.add_output_data("OK", "%s - FW: %s" %
                                      (plugin_object.rf.vendor_data.ilo_version,
                                       plugin_object.rf.vendor_data.ilo_firmware_version),
                                      location=f"System {system_id}")

    # add SDCard status
    if plugin_object.rf.vendor == "Fujitsu":
        sd_card = plugin_object.rf.get(redfish_url + "/Oem/ts_fujitsu/SDCard")

        if sd_card.get("Inserted") is True and sd_card.get("Mounted") is True:
            sd_card_status = sd_card.get("Status")
            sd_card_capacity = sd_card.get("CapacityMB")
            sd_card_free_space = sd_card.get("FreeSpaceMB")

            status_text = f"SDCard Capacity {sd_card_capacity}MB and {sd_card_free_space}MB free space left."
            plugin_object.add_output_data("CRITICAL" if sd_card_status not in ["OK", "WARNING"] else sd_card_status,
                                          status_text, location=f"System {system_id}")

    return
Exemple #8
0
def get_single_system_mem(plugin_object, redfish_url):
    plugin_object.set_current_command("Mem")

    systems_response = plugin_object.rf.get(redfish_url)

    if systems_response.get("MemorySummary"):

        memory_status = get_status_data(
            grab(systems_response, "MemorySummary.Status"))

        # DELL is HealthRollUp not HealthRollup
        # Fujitsu is just Health an not HealthRollup
        health = memory_status.get("HealthRollup") or memory_status.get(
            "Health")

        if health == "OK" and plugin_object.cli_args.detailed is False and plugin_object.cli_args.inventory is False:

            total_mem = grab(systems_response,
                             "MemorySummary.TotalSystemMemoryGiB") or 0

            if plugin_object.rf.vendor == "Dell" and total_mem % 1024 != 0:
                total_mem = total_mem * 1024**3 / 1000**3

            plugin_object.add_output_data(
                "OK",
                "All memory modules (Total %dGB) are in good condition" %
                total_mem,
                summary=True)
            return

    system_response_memory_key = "Memory"
    if grab(
            systems_response,
            f"Oem.{plugin_object.rf.vendor_dict_key}.Links.{system_response_memory_key}"
    ):
        memory_path_dict = grab(
            systems_response, f"Oem.{plugin_object.rf.vendor_dict_key}.Links")
    else:
        memory_path_dict = systems_response

    if memory_path_dict.get(system_response_memory_key) is None:
        issue_text = f"Returned data from API URL '{redfish_url}' has no attribute '{system_response_memory_key}'"
        plugin_object.inventory.add_issue(Memory, issue_text)
        plugin_object.add_output_data("UNKNOWN", issue_text)
        return

    redfish_url = memory_path_dict.get(system_response_memory_key).get(
        "@odata.id") + "%s" % plugin_object.rf.vendor_data.expand_string

    memory_response = plugin_object.rf.get_view(redfish_url)

    num_dimms = 0
    size_sum = 0

    if memory_response.get("Members") or memory_response.get(
            system_response_memory_key):

        for mem_module in memory_response.get(
                "Members") or memory_response.get(system_response_memory_key):

            if mem_module.get("@odata.context"):
                mem_module_response = mem_module
            else:
                mem_module_response = plugin_object.rf.get(
                    mem_module.get("@odata.id"))

            if mem_module_response.get("Id"):

                # get size
                module_size = mem_module_response.get(
                    "SizeMB") or mem_module_response.get("CapacityMiB") or 0

                module_size = int(module_size)

                # DELL fix for iDRAC 8
                if plugin_object.rf.vendor == "Dell" and module_size % 1024 != 0:
                    module_size = round(module_size * 1024**2 / 1000**2)

                # get name
                module_name = mem_module_response.get(
                    "SocketLocator") or mem_module_response.get(
                        "DeviceLocator") or mem_module_response.get("Name")

                if module_name is None:
                    module_name = "UnknownNameLocation"

                # get status
                status_data = get_status_data(
                    mem_module_response.get("Status"))

                if plugin_object.rf.vendor == "HPE" and grab(
                        mem_module_response,
                        f"Oem.{plugin_object.rf.vendor_dict_key}.DIMMStatus"):
                    status_data["State"] = grab(
                        mem_module_response,
                        f"Oem.{plugin_object.rf.vendor_dict_key}.DIMMStatus")

                elif mem_module_response.get("DIMMStatus"):

                    status_data["State"] = mem_module_response.get(
                        "DIMMStatus")

                mem_inventory = Memory(
                    name=module_name,
                    id=mem_module_response.get("Id"),
                    health_status=status_data.get("Health"),
                    operation_status=status_data.get("State"),
                    size_in_mb=module_size,
                    manufacturer=mem_module_response.get("Manufacturer"),
                    serial=mem_module_response.get("SerialNumber"),
                    socket=grab(mem_module_response, "MemoryLocation.Socket"),
                    slot=grab(mem_module_response, "MemoryLocation.Slot"),
                    channel=grab(mem_module_response,
                                 "MemoryLocation.Channel"),
                    speed=mem_module_response.get("OperatingSpeedMhz"),
                    part_number=mem_module_response.get("PartNumber"),
                    type=mem_module_response.get("MemoryDeviceType")
                    or mem_module_response.get("MemoryType"),
                    base_type=mem_module_response.get("BaseModuleType"),
                    system_ids=systems_response.get("Id"))

                if plugin_object.cli_args.verbose:
                    mem_inventory.source_data = mem_module_response

                plugin_object.inventory.add(mem_inventory)

                if mem_inventory.operation_status in ["Absent", "NotPresent"]:
                    continue

                num_dimms += 1
                size_sum += module_size

                if mem_inventory.operation_status in ["GoodInUse", "Operable"]:
                    plugin_status = "OK"
                    status_text = mem_inventory.operation_status
                else:
                    plugin_status = mem_inventory.health_status
                    status_text = plugin_status

                status_text = f"Memory module {mem_inventory.name} (%.1fGB) status is: {status_text}" % (
                    mem_inventory.size_in_mb / 1024)

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

            else:
                plugin_object.add_output_data(
                    "UNKNOWN", "No memory data returned for API URL '%s'" %
                    mem_module.get("@odata.id"))

    if num_dimms == 0:
        plugin_object.add_output_data(
            "UNKNOWN", f"No memory data returned for API URL '{redfish_url}'")
    else:
        plugin_object.add_output_data(
            "OK",
            f"All {num_dimms} memory modules (Total %.1fGB) are in good condition"
            % (size_sum / 1024),
            summary=True)

    return
Exemple #9
0
def get_firmware_info_generic(plugin_object):

    if plugin_object.rf.connection.root.get("UpdateService") is None:
        plugin_object.inventory.add_issue(
            Firmware, "URL '/redfish/v1/UpdateService' unavailable. "
            "Unable to retrieve firmware information.")
        return

    redfish_url = f"/redfish/v1/UpdateService/FirmwareInventory{plugin_object.rf.vendor_data.expand_string}"

    firmware_response = plugin_object.rf.get(redfish_url)

    if firmware_response.get("error"):
        plugin_object.add_data_retrieval_error(Firmware, firmware_response,
                                               redfish_url)

    # older Cisco CIMC versions reported Firmware inventory in a different fashion
    if plugin_object.rf.vendor == "Cisco":
        if firmware_response.get("@odata.id") is None:
            redfish_url = f"/redfish/v1/UpdateService/{plugin_object.rf.vendor_data.expand_string}"
            firmware_response = plugin_object.rf.get(redfish_url)
            if firmware_response.get("error"):
                plugin_object.add_data_retrieval_error(Firmware,
                                                       firmware_response,
                                                       redfish_url)

        if firmware_response.get("FirmwareInventory") is not None:
            firmware_response["Members"] = firmware_response.get(
                "FirmwareInventory")

    for firmware_member in firmware_response.get("Members"):

        if firmware_member.get("@odata.type"):
            firmware_entry = firmware_member
        else:
            firmware_entry = plugin_object.rf.get(
                firmware_member.get("@odata.id"))

            if firmware_entry.get("error"):
                plugin_object.add_data_retrieval_error(
                    Firmware, firmware_entry, firmware_member.get("@odata.id"))
                continue

        # get name and id
        component_name = f"{firmware_entry.get('Name')}"
        component_id = firmware_entry.get("Id")

        if component_id == component_name and firmware_entry.get(
                "SoftwareId") is not None:
            component_name = firmware_entry.get("SoftwareId")

        if component_id is None:
            component_id = component_name

        # on Dell system skip power supplies and disk and collect them separately
        # only one of the disk and power supply is reported not all of them
        if plugin_object.rf.vendor == "Dell" and component_name is not None:
            if "power supply" in component_name.lower():
                continue
            if "disk " in component_name.lower():
                continue

        if component_name.lower().startswith("firmware:"):
            component_name = component_name[9:]

        # get firmware version
        component_version = firmware_entry.get("Version")
        if component_version is not None:
            component_version = component_version.strip().replace("\n", "")

        if grab(firmware_entry,
                f"Oem.{plugin_object.rf.vendor_dict_key}.FirmwareBuild"
                ) is not None:
            component_version = f"{component_version} %s" % \
                                grab(firmware_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.FirmwareBuild")

        # get location
        component_location = grab(
            firmware_entry,
            f"Oem.{plugin_object.rf.vendor_dict_key}.PositionId")

        if plugin_object.rf.vendor == "HPE":
            component_location = grab(
                firmware_entry,
                f"Oem.{plugin_object.rf.vendor_dict_key}.DeviceContext")

        if component_location is None and firmware_entry.get(
                "SoftwareId") is not None:
            component_location = firmware_entry.get("SoftwareId")

        # get status
        status_data = get_status_data(firmware_entry.get("Status"))

        firmware_inventory = Firmware(
            id=component_id,
            name=component_name,
            health_status=status_data.get("Health"),
            operation_status=status_data.get("State"),
            version=component_version,
            location=component_location,
            updateable=firmware_entry.get("Updateable"))

        if plugin_object.cli_args.verbose:
            firmware_inventory.source_data = firmware_entry

        plugin_object.inventory.add(firmware_inventory)

    if plugin_object.rf.vendor in ["Dell", "Cisco", "Lenovo"]:
        get_drives = True
        get_controllers = False
        get_power = True
        plugin_object.in_firmware_collection_mode(True)
        if any(x in plugin_object.cli_args.requested_query
               for x in ['storage', 'all']) is False:
            get_storage(plugin_object)
        if any(x in plugin_object.cli_args.requested_query
               for x in ['power', 'all']) is False:
            get_chassi_data(plugin_object, PowerSupply)
        plugin_object.in_firmware_collection_mode(False)

        # vendor specific conditions
        if plugin_object.rf.vendor == "Cisco":
            get_controllers = True
        if plugin_object.rf.vendor == "Lenovo":
            for fw_object in plugin_object.inventory.get(Firmware):
                if fw_object.name.lower().startswith("disk"):
                    get_drives = False
                if fw_object.name.lower().startswith("power"):
                    get_power = False

        fw_id = len(plugin_object.inventory.get(Firmware)) - 1
        if get_drives is True:
            for drive in plugin_object.inventory.get(PhysicalDrive):
                fw_id += 1

                firmware_inventory = Firmware(id=fw_id,
                                              name=f"Drive {drive.name}",
                                              version=drive.firmware,
                                              location=drive.location)
                if plugin_object.cli_args.verbose:
                    firmware_inventory.source_data = drive.source_data

                plugin_object.inventory.add(firmware_inventory)

        if get_controllers is True:
            for storage_controller in plugin_object.inventory.get(
                    StorageController):
                fw_id += 1

                if storage_controller.firmware is None:
                    continue

                firmware_inventory = Firmware(
                    id=fw_id,
                    name=f"Storage Controller {storage_controller.name}",
                    version=storage_controller.firmware,
                    location=storage_controller.location)
                if plugin_object.cli_args.verbose:
                    firmware_inventory.source_data = storage_controller.source_data

                plugin_object.inventory.add(firmware_inventory)

        for storage_enclosure in plugin_object.inventory.get(StorageEnclosure):
            fw_id += 1

            if storage_enclosure.firmware is None:
                continue

            firmware_inventory = Firmware(id=fw_id,
                                          name="Storage Enclosure",
                                          version=storage_enclosure.firmware,
                                          location=storage_enclosure.bay)
            if plugin_object.cli_args.verbose:
                firmware_inventory.source_data = storage_enclosure.source_data

            plugin_object.inventory.add(firmware_inventory)

        if get_power is True:
            for power_supply in plugin_object.inventory.get(PowerSupply):
                fw_id += 1

                if power_supply.firmware is None:
                    continue

                firmware_inventory = Firmware(
                    id=fw_id,
                    name=f"Power Supply {power_supply.model}",
                    version=power_supply.firmware,
                    location=f"Slot {power_supply.bay}")
                if plugin_object.cli_args.verbose:
                    firmware_inventory.source_data = power_supply.source_data

                plugin_object.inventory.add(firmware_inventory)

    return
Exemple #10
0
def get_single_system_procs(plugin_object, redfish_url):
    plugin_object.set_current_command("Procs")

    systems_response = plugin_object.rf.get(redfish_url)

    if systems_response.get("ProcessorSummary"):

        proc_status = get_status_data(
            grab(systems_response, "ProcessorSummary.Status"))

        # DELL is HealthRollUp not HealthRollup
        # Fujitsu is just Health an not HealthRollup
        health = proc_status.get("HealthRollup") or proc_status.get("Health")

        proc_count = grab(systems_response, "ProcessorSummary.Count")
        proc_count_text = ""
        if proc_count is not None:
            proc_count_text = f"({proc_count}) "

        if health == "OK" and plugin_object.cli_args.detailed is False and plugin_object.cli_args.inventory is False:
            plugin_object.add_output_data(
                "OK",
                f"All processors {proc_count_text}are in good condition",
                summary=True)
            return

    system_response_proc_key = "Processors"
    if systems_response.get(system_response_proc_key) is None:
        issue_text = f"Returned data from API URL '{redfish_url}' has no attribute '{system_response_proc_key}'"
        plugin_object.inventory.add_issue(Processor, issue_text)
        plugin_object.add_output_data("UNKNOWN", issue_text)
        return

    processors_link = grab(systems_response,
                           f"{system_response_proc_key}/@odata.id",
                           separator="/")

    processors_response = plugin_object.rf.get_view(
        f"{processors_link}{plugin_object.rf.vendor_data.expand_string}")

    if processors_response.get(
            "Members") is not None or processors_response.get(
                system_response_proc_key) is not None:

        num_procs = 0
        for proc in processors_response.get(
                "Members") or processors_response.get(
                    system_response_proc_key) or list():

            if proc.get("@odata.context"):
                proc_response = proc
            else:
                proc_response = plugin_object.rf.get(proc.get("@odata.id"))

            if proc_response.get("Id"):

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

                model = proc_response.get("Model")

                vendor_data = grab(proc_response,
                                   f"Oem.{plugin_object.rf.vendor_dict_key}")

                if plugin_object.rf.vendor == "Dell" and grab(
                        vendor_data, "DellProcessor") is not None:
                    vendor_data = grab(vendor_data, "DellProcessor")

                # get current/regular speed
                current_speed = grab(vendor_data, "CurrentClockSpeedMHz") or grab(vendor_data, "RatedSpeedMHz") or \
                    grab(vendor_data, "FrequencyMHz")

                # try to extract speed from model if current_speed is None
                # Intel XEON CPUs
                if current_speed is None and model is not None and "GHz" in model:
                    model_speed = model.split("@")[-1].strip().replace(
                        "GHz", "")
                    try:
                        current_speed = int(float(model_speed) * 1000)
                    except Exception:
                        pass

                # get cache information
                level_1_cache_kib = grab(vendor_data, "L1CacheKiB")
                level_2_cache_kib = grab(vendor_data, "L2CacheKiB")
                level_3_cache_kib = grab(vendor_data, "L3CacheKiB")

                if plugin_object.rf.vendor == "Dell":
                    level_1_cache_kib = grab(vendor_data,
                                             "Cache1InstalledSizeKB")
                    level_2_cache_kib = grab(vendor_data,
                                             "Cache2InstalledSizeKB")
                    level_3_cache_kib = grab(vendor_data,
                                             "Cache3InstalledSizeKB")

                #                   HPE                           Lenovo
                vendor_cache_data = grab(vendor_data, "Cache") or grab(
                    vendor_data, "CacheInfo")

                if vendor_cache_data is not None:

                    for cpu_cache in vendor_cache_data:

                        #            HPE                                 Lenovo
                        cache_size = cpu_cache.get(
                            "InstalledSizeKB") or cpu_cache.get(
                                "InstalledSizeKByte")
                        cache_level = cpu_cache.get("Name") or cpu_cache.get(
                            "CacheLevel")

                        if cache_size is None or cache_level is None:
                            continue

                        if "L1" in cache_level:
                            level_1_cache_kib = cache_size * 1000 / 1024
                        if "L2" in cache_level:
                            level_2_cache_kib = cache_size * 1000 / 1024
                        if "L3" in cache_level:
                            level_3_cache_kib = cache_size * 1000 / 1024

                proc_inventory = Processor(
                    name=proc_response.get("Name"),
                    id=proc_response.get("Id"),
                    model=model,
                    socket=proc_response.get("Socket"),
                    health_status=status_data.get("Health"),
                    operation_status=status_data.get("State"),
                    cores=proc_response.get("TotalCores"),
                    threads=proc_response.get("TotalThreads"),
                    current_speed=current_speed,
                    max_speed=proc_response.get("MaxSpeedMHz"),
                    manufacturer=proc_response.get("Manufacturer"),
                    instruction_set=proc_response.get("InstructionSet"),
                    architecture=proc_response.get("ProcessorArchitecture"),
                    serial=grab(
                        proc_response,
                        f"Oem.{plugin_object.rf.vendor_dict_key}.SerialNumber"
                    ),
                    system_ids=systems_response.get("Id"),
                    L1_cache_kib=level_1_cache_kib,
                    L2_cache_kib=level_2_cache_kib,
                    L3_cache_kib=level_3_cache_kib)

                if plugin_object.cli_args.verbose:
                    proc_inventory.source_data = proc_response

                plugin_object.inventory.add(proc_inventory)

                if proc_inventory.operation_status == "Absent":
                    continue

                num_procs += 1

                status_text = f"Processor {proc_inventory.socket} ({proc_inventory.model}) status is: " \
                              f"{proc_inventory.health_status}"

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

            else:
                plugin_object.add_output_data(
                    "UNKNOWN", "No processor data returned for API URL '%s'" %
                    proc_response.get("@odata.id"))

        if num_procs == 0:
            issue_text = f"Returned data from API URL '{processors_link}' contains no processor information"
            plugin_object.inventory.add_issue(Processor, issue_text)
            plugin_object.add_output_data(
                "UNKNOWN",
                issue_text,
                summary=not plugin_object.cli_args.detailed)

        elif plugin_object.cli_args.detailed is False:
            plugin_object.add_output_data(
                "OK",
                "All processors (%d) are in good condition" % num_procs,
                summary=True)
    else:
        plugin_object.add_output_data(
            "UNKNOWN",
            f"No processor data returned for API URL '{redfish_url}'")

    return
Exemple #11
0
def get_single_chassi_power(plugin_object, redfish_url):
    plugin_object.set_current_command("Power")

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

    redfish_url = f"{redfish_url}/Power"

    power_data = plugin_object.rf.get_view(redfish_url)

    if power_data.get("error"):
        plugin_object.add_data_retrieval_error(PowerSupply, power_data,
                                               redfish_url)
        return

    power_supplies = power_data.get("PowerSupplies", list())

    fujitsu_power_sensors = None
    if plugin_object.rf.vendor == "Fujitsu":
        fujitsu_power_sensors = grab(
            power_data,
            f"Oem.{plugin_object.rf.vendor_dict_key}.ChassisPowerSensors")

    ps_num = 0
    ps_absent = 0
    if len(power_supplies) > 0:
        for ps in power_supplies:

            ps_num += 1

            status_data = get_status_data(grab(ps, "Status"))

            health = status_data.get("Health")
            operational_status = status_data.get("State")
            part_number = ps.get("PartNumber")
            model = ps.get("Model") or part_number
            last_power_output = ps.get("LastPowerOutputWatts") or ps.get(
                "PowerOutputWatts")
            capacity_in_watt = ps.get("PowerCapacityWatts")
            bay = None

            oem_data = grab(ps, f"Oem.{plugin_object.rf.vendor_dict_key}")

            if oem_data is not None:

                if plugin_object.rf.vendor == "HPE":
                    bay = grab(oem_data, "BayNumber")
                    ps_hp_status = grab(oem_data, "PowerSupplyStatus.State")
                    if ps_hp_status is not None and ps_hp_status == "Unknown":
                        health = "CRITICAL"

                elif plugin_object.rf.vendor == "Lenovo":
                    bay = grab(oem_data, "Location.Info")

                if last_power_output is None and grab(
                        oem_data, "PowerOutputWatts") is not None:
                    last_power_output = grab(oem_data, "PowerOutputWatts")

            if bay is None:
                bay = ps_num

            if capacity_in_watt is None:
                capacity_in_watt = grab(ps, "InputRanges.0.OutputWattage")

            # special Fujitsu case
            if fujitsu_power_sensors is not None and last_power_output is None:
                for fujitsu_power_sensor in fujitsu_power_sensors:
                    if fujitsu_power_sensor.get("Designation") == ps.get(
                            "Name"):
                        last_power_output = fujitsu_power_sensor.get(
                            "CurrentPowerConsumptionW")

            ps_inventory = PowerSupply(
                id=grab(ps, "MemberId") or ps_num,
                name=ps.get("Name"),
                model=model,
                bay=bay,
                health_status=health,
                operation_status=operational_status,
                last_power_output=last_power_output,
                serial=ps.get("SerialNumber"),
                type=ps.get("PowerSupplyType"),
                capacity_in_watt=capacity_in_watt,
                firmware=ps.get("FirmwareVersion"),
                vendor=ps.get("Manufacturer"),
                input_voltage=ps.get("LineInputVoltage"),
                part_number=ps.get("SparePartNumber") or ps.get("PartNumber"),
                chassi_ids=chassi_id)

            if plugin_object.cli_args.verbose:
                ps_inventory.source_data = ps

            plugin_object.inventory.add(ps_inventory)

            printed_status = health
            printed_model = ""

            if operational_status == "Absent":
                printed_status = operational_status
                health = "OK"
                ps_absent += 1

            if health is None and operational_status == "Enabled":
                printed_status = operational_status
                health = "OK"

            if model is not None:
                printed_model = "(%s) " % model.strip()

            status_text = "Power supply {bay} {model}status is: {status}".format(
                bay=str(bay), model=printed_model, status=printed_status)

            plugin_object.add_output_data(
                "CRITICAL" if health not in ["OK", "WARNING"] else health,
                status_text,
                location=f"Chassi {chassi_id}")

            if last_power_output is not None:
                plugin_object.add_perf_data(f"ps_{bay}",
                                            int(last_power_output),
                                            location=f"Chassi {chassi_id}")

        default_text = "All power supplies (%d) are in good condition" % (
            ps_num - ps_absent)

    else:
        default_text = "No power supplies detected"
        plugin_object.inventory.add_issue(
            PowerSupply,
            f"No power supply data returned for API URL '{redfish_url}'")

    # get PowerRedundancy status
    power_redundancies = power_data.get("PowerRedundancy") or power_data.get(
        "Redundancy")

    if power_redundancies:
        pr_status_summary_text = ""
        pr_num = 0
        for power_redundancy in power_redundancies:

            pr_status = power_redundancy.get("Status")

            if pr_status is not None:
                status = pr_status.get("Health")
                state = pr_status.get("State")

                if status is not None:
                    pr_num += 1
                    status = status.upper()

                    status_text = f"Power redundancy {pr_num} status is: {state}"

                    pr_status_summary_text += f" {status_text}"

                    plugin_object.add_output_data(
                        "CRITICAL"
                        if status not in ["OK", "WARNING"] else status,
                        status_text,
                        location=f"Chassi {chassi_id}")

        if len(pr_status_summary_text) != 0:
            default_text += f" and{pr_status_summary_text}"

    # get Voltages status
    voltages = power_data.get("Voltages")

    if voltages is not None:
        voltages_num = 0
        for voltage in voltages:

            voltage_status = voltage.get("Status")

            if voltage_status is not None:
                status = voltage_status.get("Health")
                state = voltage_status.get("State")
                reading = voltage.get("ReadingVolts")
                name = voltage.get("Name")

                if status is not None:
                    voltages_num += 1
                    status = status.upper()

                    status_text = f"Voltage {name} (status: {status}/{state}): {reading}V"

                    plugin_object.add_output_data(
                        "CRITICAL"
                        if status not in ["OK", "WARNING"] else status,
                        status_text,
                        location=f"Chassi {chassi_id}")

                    if reading is not None and name is not None:
                        try:
                            plugin_object.add_perf_data(
                                f"voltage_{name}",
                                float(reading),
                                location=f"Chassi {chassi_id}")
                        except Exception:
                            pass

        if voltages_num > 0:
            default_text += f" and {voltages_num} Voltages are OK"

    plugin_object.add_output_data("OK",
                                  default_text,
                                  summary=True,
                                  location=f"Chassi {chassi_id}")

    return
Exemple #12
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
Exemple #13
0
def get_single_system_info(plugin_object, redfish_url):
    system_response = plugin_object.rf.get(redfish_url)

    if system_response is None:
        plugin_object.add_output_data(
            "UNKNOWN",
            f"No system information data returned for API URL '{redfish_url}'")
        return

    # get model data
    model = system_response.get("Model")
    # Huawei system
    if plugin_object.rf.vendor == "Huawei":
        model = grab(system_response,
                     f"Oem.{plugin_object.rf.vendor_dict_key}.ProductName")

    # get memory size
    mem_size = grab(system_response, "MemorySummary.TotalSystemMemoryGiB")

    # Dell system
    # just WHY?
    if plugin_object.rf.vendor == "Dell" and mem_size is not None and int(
            mem_size) % 1024 != 0:
        mem_size = round(mem_size * 1024**3 / 1000**3)

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

    system_inventory = System(
        id=system_response.get("Id"),
        name=system_response.get("Name"),
        manufacturer=system_response.get("Manufacturer"),
        serial=system_response.get("SerialNumber"),
        health_status=status_data.get("Health"),
        operation_status=status_data.get("State"),
        power_state=system_response.get("PowerState"),
        bios_version=system_response.get("BiosVersion"),
        host_name=system_response.get("HostName"),
        indicator_led=system_response.get("IndicatorLED"),
        cpu_num=grab(system_response, "ProcessorSummary.Count"),
        part_number=system_response.get("PartNumber"),
        mem_size=mem_size,
        model=model,
        type=system_response.get("SystemType"))

    if plugin_object.cli_args.verbose:
        system_inventory.source_data = system_response

    # add relations
    system_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                  system_response.get("Links"))

    plugin_object.inventory.add(system_inventory)

    host_name = "NOT SET"
    if system_inventory.host_name is not None and len(
            system_inventory.host_name) > 0:
        host_name = system_inventory.host_name

    status_text = f"Type: {system_inventory.manufacturer} {system_inventory.model} " \
                  f"(CPU: {system_inventory.cpu_num}, MEM: {system_inventory.mem_size}GB) - " \
                  f"BIOS: {system_inventory.bios_version} - " \
                  f"Serial: {system_inventory.serial} - " \
                  f"Power: {system_inventory.power_state} - Name: {host_name}"

    plugin_object.add_output_data(
        "CRITICAL" if system_inventory.health_status not in ["OK", "WARNING"]
        else system_inventory.health_status,
        status_text,
        summary=not plugin_object.cli_args.detailed)

    if plugin_object.cli_args.detailed is True:

        # add ILO data
        if plugin_object.rf.vendor == "HPE":
            plugin_object.add_output_data(
                "OK", "%s - FW: %s" %
                (plugin_object.rf.vendor_data.ilo_version,
                 plugin_object.rf.vendor_data.ilo_firmware_version))
        # add SDCard status
        if plugin_object.rf.vendor == "Fujitsu":
            sd_card = plugin_object.rf.get(redfish_url +
                                           "/Oem/ts_fujitsu/SDCard")

            if sd_card.get("Inserted") is True:
                sd_card_status = sd_card.get("Status")
                sd_card_capacity = sd_card.get("CapacityMB")
                sd_card_free_space = sd_card.get("FreeSpaceMB")

                status_text = f"SDCard Capacity {sd_card_capacity}MB and {sd_card_free_space}MB free space left."
                plugin_object.add_output_data(
                    "CRITICAL" if sd_card_status not in ["OK", "WARNING"] else
                    sd_card_status, status_text)

    return
Exemple #14
0
def get_single_system_info(plugin_object, redfish_url):
    system_response = plugin_object.rf.get(redfish_url)

    if system_response is None:
        plugin_object.add_output_data(
            "UNKNOWN",
            f"No system information data returned for API URL '{redfish_url}'")
        return

    # get model data
    model = system_response.get("Model")
    # Huawei system
    if plugin_object.rf.vendor == "Huawei":
        huawei_model = grab(
            system_response,
            f"Oem.{plugin_object.rf.vendor_dict_key}.ProductName")

        if huawei_model is not None:
            model = huawei_model

    # get memory size
    mem_size = grab(system_response, "MemorySummary.TotalSystemMemoryGiB")

    # Dell system
    # just WHY?
    if plugin_object.rf.vendor == "Dell" and mem_size is not None and int(
            mem_size) % 1024 != 0:
        mem_size = round(mem_size * 1024**3 / 1000**3)

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

    system_inventory = System(
        id=system_response.get("Id"),
        name=system_response.get("Name"),
        manufacturer=system_response.get("Manufacturer"),
        serial=system_response.get("SerialNumber"),
        health_status=status_data.get("Health"),
        operation_status=status_data.get("State"),
        power_state=system_response.get("PowerState"),
        bios_version=system_response.get("BiosVersion"),
        host_name=system_response.get("HostName"),
        indicator_led=system_response.get("IndicatorLED"),
        cpu_num=grab(system_response, "ProcessorSummary.Count"),
        part_number=system_response.get("PartNumber"),
        mem_size=mem_size,
        model=model,
        type=system_response.get("SystemType"))

    if plugin_object.cli_args.verbose:
        system_inventory.source_data = system_response

    # add relations
    system_inventory.add_relation(plugin_object.rf.get_system_properties(),
                                  system_response.get("Links"))

    plugin_object.inventory.add(system_inventory)

    host_name = "NOT SET"
    if system_inventory.host_name is not None and len(
            system_inventory.host_name) > 0:
        host_name = system_inventory.host_name

    status_text = f"Type: {system_inventory.manufacturer} {system_inventory.model} " \
                  f"(CPU: {system_inventory.cpu_num}, MEM: {system_inventory.mem_size}GB) - " \
                  f"BIOS: {system_inventory.bios_version} - " \
                  f"Serial: {system_inventory.serial} - " \
                  f"Power: {system_inventory.power_state} - Name: {host_name}"

    system_health_print_status = \
        "CRITICAL" if system_inventory.health_status not in ["OK", "WARNING"] else system_inventory.health_status

    plugin_object.add_output_data(system_health_print_status,
                                  status_text,
                                  summary=not plugin_object.cli_args.detailed)

    # add DellSensorCollection if present
    if plugin_object.rf.vendor == "Dell":

        dell_empty_slots = list()

        dell_slot_collection = \
            grab(system_response, f"Links.Oem.{plugin_object.rf.vendor_dict_key}.DellSlotCollection")

        # collect info about empty slots
        if dell_slot_collection is not None and dell_slot_collection.get(
                "@odata.id") is not None:
            collection_response = plugin_object.rf.get(
                dell_slot_collection.get("@odata.id"))

            if collection_response is not None and (
                    collection_response.get("Members") is None
                    or len(collection_response.get("Members")) > 0):

                for dell_slot in collection_response.get("Members"):

                    if dell_slot.get("EmptySlot") is True:
                        dell_empty_slots.append(dell_slot.get("Id"))

        dell_sensor_collection = \
            grab(system_response, f"Links.Oem.{plugin_object.rf.vendor_dict_key}.DellSensorCollection")

        if dell_sensor_collection is not None and dell_sensor_collection.get(
                "@odata.id") is not None:
            collection_response = plugin_object.rf.get(
                dell_sensor_collection.get("@odata.id"))

            num_members = 0
            if collection_response is not None and (
                    collection_response.get("Members") is None
                    or len(collection_response.get("Members")) > 0):

                for dell_sensor in collection_response.get("Members"):

                    # skip if sensor slot is empty
                    if any(
                            x.startswith(dell_sensor.get("Id"))
                            for x in dell_empty_slots):
                        continue

                    num_members += 1

                    this_sensor_status = "OK"

                    if dell_sensor.get('EnabledState') == "Enabled":
                        if "Warning" in dell_sensor.get('HealthState'):
                            this_sensor_status = "WARNING"
                        elif dell_sensor.get('HealthState') != "OK":
                            this_sensor_status = "CRITICAL"

                    plugin_object.add_output_data(
                        this_sensor_status, 'Sensor "%s": %s (%s/%s)' %
                        (dell_sensor.get('ElementName'),
                         dell_sensor.get('HealthState'),
                         dell_sensor.get('EnabledState'),
                         dell_sensor.get('CurrentState')))

            if plugin_object.cli_args.detailed is False:
                plugin_object.add_output_data(
                    system_health_print_status,
                    f"{status_text} - {num_members} health sensors are in 'OK' state",
                    summary=True)

    if plugin_object.cli_args.detailed is True:

        # add ILO data
        if plugin_object.rf.vendor == "HPE":
            plugin_object.add_output_data(
                "OK", "%s - FW: %s" %
                (plugin_object.rf.vendor_data.ilo_version,
                 plugin_object.rf.vendor_data.ilo_firmware_version))
        # add SDCard status
        if plugin_object.rf.vendor == "Fujitsu":
            sd_card = plugin_object.rf.get(redfish_url +
                                           "/Oem/ts_fujitsu/SDCard")

            if sd_card.get("Inserted") is True and sd_card.get(
                    "Mounted") is True:
                sd_card_status = sd_card.get("Status")
                sd_card_capacity = sd_card.get("CapacityMB")
                sd_card_free_space = sd_card.get("FreeSpaceMB")

                status_text = f"SDCard Capacity {sd_card_capacity}MB and {sd_card_free_space}MB free space left."
                plugin_object.add_output_data(
                    "CRITICAL" if sd_card_status not in ["OK", "WARNING"] else
                    sd_card_status, status_text)

    return
Exemple #15
0
def get_firmware_info_generic(plugin_object):

    if plugin_object.rf.connection.root.get("UpdateService") is None:
        plugin_object.add_output_data("UNKNOWN",
                                      "URL '/redfish/v1/UpdateService' unavailable. "
                                      "Unable to retrieve firmware information.",
                                      summary=not plugin_object.cli_args.detailed)
        return

    redfish_url = f"/redfish/v1/UpdateService/FirmwareInventory{plugin_object.rf.vendor_data.expand_string}"

    firmware_response = plugin_object.rf.get(redfish_url)

    # older Cisco CIMC versions reported Firmware inventory in a different fashion
    if plugin_object.rf.vendor == "Cisco":
        if firmware_response.get("@odata.id") is None:
            redfish_url = f"/redfish/v1/UpdateService/{plugin_object.rf.vendor_data.expand_string}"
            firmware_response = plugin_object.rf.get(redfish_url)
        if firmware_response.get("FirmwareInventory") is not None:
            firmware_response["Members"] = firmware_response.get("FirmwareInventory")

    for firmware_member in firmware_response.get("Members"):

        if firmware_member.get("@odata.type"):
            firmware_entry = firmware_member
        else:
            firmware_entry = plugin_object.rf.get(firmware_member.get("@odata.id"))

        # get name and id
        component_name = firmware_entry.get("Name")
        component_id = firmware_entry.get("Id")

        if component_id == component_name and firmware_entry.get("SoftwareId") is not None:
            component_name = firmware_entry.get("SoftwareId")

        if component_id is None:
            component_id = component_name

        # get firmware version
        component_version = firmware_entry.get("Version")
        if component_version is not None:
            component_version = component_version.strip().replace("\n", "")

        if grab(firmware_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.FirmwareBuild") is not None:
            component_version = f"{component_version} %s" % \
                                grab(firmware_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.FirmwareBuild")

        # get location
        component_location = grab(firmware_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.PositionId")

        if plugin_object.rf.vendor == "HPE":
            component_location = grab(firmware_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.DeviceContext")

        if component_location is None and firmware_entry.get("SoftwareId") is not None:
            component_location = firmware_entry.get("SoftwareId")

        # get status
        status_data = get_status_data(firmware_entry.get("Status"))

        firmware_inventory = Firmware(
            id=component_id,
            name=component_name,
            health_status=status_data.get("Health"),
            operation_status=status_data.get("State"),
            version=component_version,
            location=component_location,
            updateable=firmware_entry.get("Updateable")
        )

        if plugin_object.cli_args.verbose:
            firmware_inventory.source_data = firmware_entry

        plugin_object.inventory.add(firmware_inventory)

    return
Exemple #16
0
def get_single_chassi_fan(plugin_object, redfish_url):
    plugin_object.set_current_command("Fan")

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

    redfish_url = f"{redfish_url}/Thermal"

    thermal_data = plugin_object.rf.get_view(redfish_url)

    default_text = ""
    fan_num = 0
    if "Fans" in thermal_data:
        for fan in thermal_data.get("Fans"):

            status_data = get_status_data(grab(fan, "Status"))

            member_id = grab(fan, "MemberId")
            name = fan.get("FanName") or fan.get("Name")

            if member_id is None:
                member_id = name

            # This helps on systems where the same MemberId could be assigned to multiple instances
            if grab(fan, "SensorNumber") is not None:
                member_id = f"{member_id}.{grab(fan, 'SensorNumber')}"

            physical_context = fan.get("PhysicalContext")

            oem_data = grab(fan, f"Oem.{plugin_object.rf.vendor_dict_key}")
            if physical_context is None:
                physical_context = grab(oem_data, "Location") or grab(
                    oem_data, "Position")

            fan_inventory = Fan(
                id=member_id,
                name=name,
                health_status=status_data.get("Health"),
                operation_status=status_data.get("State"),
                physical_context=physical_context,
                min_reading=fan.get("MinReadingRange"),
                max_reading=fan.get("MaxReadingRange"),
                lower_threshold_non_critical=fan.get(
                    "LowerThresholdNonCritical"),
                lower_threshold_critical=fan.get("LowerThresholdCritical"),
                lower_threshold_fatal=fan.get("LowerThresholdFatal"),
                upper_threshold_non_critical=fan.get(
                    "UpperThresholdNonCritical"),
                upper_threshold_critical=fan.get("UpperThresholdCritical"),
                upper_threshold_fatal=fan.get("UpperThresholdFatal"),
                location=grab(
                    fan,
                    f"Oem.{plugin_object.rf.vendor_dict_key}.Location.Info"),
                chassi_ids=chassi_id)

            if plugin_object.cli_args.verbose:
                fan_inventory.source_data = fan

            text_units = ""
            fan_status = fan_inventory.health_status

            # add relations
            fan_inventory.add_relation(
                plugin_object.rf.get_system_properties(), fan.get("Links"))
            fan_inventory.add_relation(
                plugin_object.rf.get_system_properties(),
                fan.get("RelatedItem"))

            perf_units = ""

            # DELL, Fujitsu, Huawei
            if fan.get("ReadingRPM") is not None or fan.get(
                    "ReadingUnits") == "RPM":
                fan_inventory.reading = fan.get("ReadingRPM") or fan.get(
                    "Reading")
                fan_inventory.reading_unit = "RPM"

                text_units = " RPM"

            # HP, Lenovo
            else:
                fan_inventory.reading = fan.get("Reading")
                fan_inventory.reading_unit = fan.get("ReadingUnits")

                if fan_inventory.reading_unit == "Percent":
                    text_units = "%"
                    perf_units = "%"

            text_speed = f" ({fan_inventory.reading}{text_units})"

            plugin_object.inventory.add(fan_inventory)

            if fan_inventory.operation_status == "Absent":
                continue

            if fan_inventory.health_status is None:
                fan_status = "OK" if fan_inventory.operation_status == "Enabled" else fan_inventory.operation_status

            fan_num += 1

            status_text = f"Fan '{fan_inventory.name}'{text_speed} status is: {fan_status}"

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

            if fan_inventory.reading is not None:
                plugin_object.add_perf_data(
                    f"Fan_{fan_inventory.name}",
                    int(fan_inventory.reading),
                    perf_uom=perf_units,
                    warning=plugin_object.cli_args.warning,
                    critical=plugin_object.cli_args.critical)

        default_text = f"All fans ({fan_num}) are in good condition"
    else:
        plugin_object.add_output_data(
            "UNKNOWN", f"No thermal data returned for API URL '{redfish_url}'")

    # get FanRedundancy status
    fan_redundancies = plugin_object.rf.get_view(redfish_url).get(
        "FanRedundancy")
    if fan_redundancies is None:
        fan_redundancies = plugin_object.rf.get_view(redfish_url).get(
            "Redundancy")

    if fan_redundancies:
        status_text = ""
        for fan_redundancy in fan_redundancies:

            fr_status = get_status_data(fan_redundancy.get("Status"))

            status = fr_status.get("Health")

            if status is not None:
                status_text = "fan redundancy status is: %s" % fr_status.get(
                    "State")

                plugin_object.add_output_data(
                    "CRITICAL" if status not in ["OK", "WARNING"] else status,
                    status_text[0].upper() + status_text[1:])

        if len(status_text) != 0:
            default_text += f" and {status_text}"

    plugin_object.add_output_data("OK", default_text, summary=True)

    return plugin_object