Esempio n. 1
0
def discover_log_services(plugin_object, event_type, system_manager_id):
    # try to discover log service
    redfish_url = None

    system_manager_data = plugin_object.rf.get(system_manager_id)

    log_services = None
    log_services_link = grab(system_manager_data, "LogServices/@odata.id", separator="/")
    if log_services_link is not None:
        log_services = plugin_object.rf.get(log_services_link)

    if grab(log_services, "Members") is not None and len(log_services.get("Members")) > 0:

        for log_service in log_services.get("Members"):

            log_service_data = plugin_object.rf.get(log_service.get("@odata.id"))

            # check if "Name" contains "System" or "Manager"
            if log_service_data.get("Name") is not None and \
                    event_type.lower() in log_service_data.get("Name").lower():

                if log_service_data.get("Entries") is not None:
                    redfish_url = log_service_data.get("Entries").get("@odata.id")
                    break

    return redfish_url
Esempio n. 2
0
    def determine_vendor(self):

        vendor_string = ""

        if self.connection.root.get("Oem"):

            if len(self.connection.root.get("Oem")) > 0:
                vendor_string = list(self.connection.root.get("Oem"))[0]

            self.vendor_dict_key = vendor_string

            if vendor_string in ["Hpe", "Hp"]:

                self.vendor_data = VendorHPEData()

                manager_data = grab(self.connection.root, f"Oem.{vendor_string}.Manager.0")

                if manager_data is not None:
                    self.vendor_data.ilo_hostname = manager_data.get("HostName")
                    self.vendor_data.ilo_version = manager_data.get("ManagerType")
                    self.vendor_data.ilo_firmware_version = manager_data.get("ManagerFirmwareVersion")

                    if self.vendor_data.ilo_version.lower() == "ilo 5":
                        self.vendor_data.view_supported = True

            if vendor_string in ["Lenovo"]:

                self.vendor_data = VendorLenovoData()

            if vendor_string in ["Dell"]:

                self.vendor_data = VendorDellData()

            if vendor_string in ["Huawei"]:

                self.vendor_data = VendorHuaweiData()

            if vendor_string in ["ts_fujitsu"]:

                self.vendor_data = VendorFujitsuData()

        # Cisco does not provide a OEM property in root object
        if "CIMC" in str(self.get_system_properties("managers")):

            self.vendor_data = VendorCiscoData()
            self.vendor_dict_key = self.vendor_data.name

        if self.vendor_data is None:

            self.vendor_data = VendorGeneric()

            if vendor_string is not None and len(vendor_string) > 0:
                self.vendor_data.name = vendor_string

        self.vendor = self.vendor_data.name

        return
Esempio n. 3
0
    def get_error(redfish_data, redfish_url):

        return_data = None
        if isinstance(redfish_data, dict) and redfish_data.get("error"):
            error = grab(redfish_data,
                         "error/@Message.ExtendedInfo/0",
                         separator="/")
            return_data = "got '%s/%s' for API path '%s'" % (
                error.get("MessageId"), error.get("Message"), redfish_url)

        return return_data
Esempio n. 4
0
def get_interface_ip_addresses(interface_data, protocol_type):
    list_of_addresses = list()

    ip_addresses = grab(interface_data, protocol_type)

    # Cisco
    if isinstance(ip_addresses, dict):
        if ip_addresses.get("Address") is not None:
            list_of_addresses.append(ip_addresses.get("Address"))

    if isinstance(ip_addresses, list):
        for ip_address in ip_addresses:
            if ip_address.get("Address") is not None:
                list_of_addresses.append(ip_address.get("Address"))

    list_of_addresses = list(set(list_of_addresses))

    return [address for address in list_of_addresses if address not in ['', '::', '0.0.0.0']]
Esempio n. 5
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
Esempio n. 6
0
def get_event_log_huawei(plugin_object, event_type, system_manager_id):

    num_entry = 0
    data_now = datetime.datetime.now()
    date_warning = None
    date_critical = None
    log_entries = list()

    if event_type == "System":
        redfish_url = f"{system_manager_id}/LogServices/Log1/Entries"

        log_entries = plugin_object.rf.get(redfish_url).get("Members")
    else:

        manager_data = plugin_object.rf.get(system_manager_id)

        if manager_data.get("LogServices") is None or len(manager_data.get("LogServices")) == 0:
            plugin_object.add_output_data("UNKNOWN", f"No 'LogServices' found for redfish URL '{system_manager_id}'",
                                          summary=not plugin_object.cli_args.detailed)
            return

        log_services_data = plugin_object.rf.get(grab(manager_data, "LogServices/@odata.id", separator="/")) or dict()

        # this should loop over following LogServices
        # https://device_ip/redfish/v1/Managers/1/LogServices/OperateLog/Entries
        # https://device_ip/redfish/v1/Managers/1/LogServices/RunLog/Entries
        # https://device_ip/redfish/v1/Managers/1/LogServices/SecurityLog/Entries

        for manager_log_service in log_services_data.get("Members") or list():
            log_entries.extend(plugin_object.rf.get(manager_log_service.get("@odata.id") + "/Entries").get("Members"))

    if plugin_object.cli_args.warning:
        date_warning = data_now - datetime.timedelta(days=int(plugin_object.cli_args.warning))
    if plugin_object.cli_args.critical:
        date_critical = data_now - datetime.timedelta(days=int(plugin_object.cli_args.critical))

    if event_type == "Manager":
        log_entries = sorted(log_entries, key=lambda i: i['Created'], reverse=True)

    for log_entry in log_entries:

        if log_entry.get("Id") is None:
            event_entry = plugin_object.rf.get(log_entry.get("@odata.id"))
        else:
            event_entry = log_entry

        num_entry += 1

        """
        It is not really clear what a "Asserted" and a "Deasserted" event looks like.
        We could assume that an "Asserted" event contains a "MessageId" and a
        "Deasserted" event doesn't. And the Only relation between these events is the
        exact same "Message" text. The "EventID" isn't really helpful either.
        And a clearing (Deasserted) of an alarm doesn't seem to work reliably either.
        It is also not possible to mark an event as "repaired" in iBMC.

        Due to all the above stated issues we implement a simple critical and warnings
        days logic as with HP Manager event logs. Otherwise uncleared events will alarm
        forever.
        """

        severity = event_entry.get("Severity")
        message = event_entry.get("Message")
        date = event_entry.get("Created")
        entry_date = get_log_entry_time(date)
        log_name = event_entry.get("Name")
        source = ""
        status = "OK"

        if severity is not None:
            severity = severity.upper()
        else:
            severity = "OK"

        # get log source information
        if event_type == "System":
            log_name = "%s/%s" % (event_entry.get("EntryType"), event_entry.get("EventType"))
            source = "[%s]" % grab(event_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.Level")
        elif log_name == "Operate Log":
            oem_data = grab(event_entry, f"Oem.{plugin_object.rf.vendor_dict_key}")
            if oem_data is not None:
                source = "[%s/%s/%s]" % \
                         (oem_data.get("Interface"), oem_data.get("User"), oem_data.get("Address"))

        elif log_name == "Run Log":
            alert_level = grab(event_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.Level")
            source = f"[{alert_level}]"
            if alert_level == "WARN":
                severity = "WARNING"
            if alert_level == "CRIT":
                severity = "CRITICAL"

        elif log_name == "Security Log":
            oem_data = grab(event_entry, f"Oem.{plugin_object.rf.vendor_dict_key}")
            if oem_data is not None:
                source = "%s/%s" % (oem_data.get("Host"), oem_data.get("Interface"))

        # check for WARNING and CRITICAL
        if date_critical is not None:
            if entry_date > date_critical.astimezone(entry_date.tzinfo) and severity != "OK":
                status = "CRITICAL" if severity not in list(plugin_status_types.keys()) else severity
        if date_warning is not None:
            if entry_date > date_warning.astimezone(entry_date.tzinfo) and status != "CRITICAL" and severity != "OK":
                status = "WARNING" if severity not in list(plugin_status_types.keys()) else severity

        plugin_object.add_log_output_data(status, f"{date}: {log_name}: {source}: {message}")

        # obey max results returned
        if plugin_object.cli_args.max is not None and num_entry >= plugin_object.cli_args.max:
            return

    return
Esempio n. 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
Esempio n. 8
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
Esempio n. 9
0
def get_event_log_generic(plugin_object, event_type, redfish_path):

    num_entry = 0
    data_now = datetime.datetime.now()
    date_warning = None
    date_critical = None
    max_entries = None

    # define locations for known vendors
    if plugin_object.rf.vendor == "Dell":
        log_service_data = plugin_object.rf.get(redfish_path)
        if grab(log_service_data, "Entries") is not None:
            redfish_path = log_service_data.get("Entries").get("@odata.id")

    if plugin_object.cli_args.warning:
        date_warning = data_now - datetime.timedelta(days=int(plugin_object.cli_args.warning))
    if plugin_object.cli_args.critical:
        date_critical = data_now - datetime.timedelta(days=int(plugin_object.cli_args.critical))

    # on dell systems max entries need to be limited during request
    if plugin_object.rf.vendor == "Dell":
        max_entries = plugin_object.cli_args.max

    event_entries = plugin_object.rf.get(redfish_path, max_members=max_entries).get("Members")

    if len(event_entries) == 0:
        plugin_object.add_output_data("OK", f"No {event_type} log entries found in '{redfish_path}'.",
                                      summary=not plugin_object.cli_args.detailed)
        return

    assoc_id_status = dict()
    processed_ids = list()

    # reverse list from newest to oldest entry
    if plugin_object.rf.vendor == "Lenovo":
        event_entries.reverse()

    for event_entry_item in event_entries:

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

        if event_entry_item.get("Id") in processed_ids:
            continue

        message = event_entry.get("Message")

        if message is not None:
            message = message.strip().strip("\n").strip()

        num_entry += 1

        severity = event_entry.get("Severity")
        if severity is not None:
            severity = severity.upper()

        # CISCO WHY?
        if severity in ["NORMAL", "INFORMATIONAL"]:
            severity = "OK"

        date = event_entry.get("Created", "1970-01-01T00:00:00-00:00")

        status = "OK"

        # keep track of message IDs
        # newer message can clear a status for older messages
        if event_type == "System":

            # get log entry id to associate older log entries
            assoc_id = event_entry.get("SensorNumber")

            # found an old message that has been cleared
            if assoc_id is not None and assoc_id_status.get(assoc_id) == "cleared" and severity != "OK":
                message += " (severity '%s' cleared)" % severity
                severity = "OK"
            # Fujitsu uncleared messages
            elif plugin_object.rf.vendor == "Fujitsu" and event_entry.get("MessageId") == "0x180055":
                message += " (severity '%s' (will be) cleared due to lack of clear event)" % severity
            elif severity is not None:
                if severity == "WARNING" and date_warning is None:
                    status = severity
                elif severity != "OK" and date_critical is None:
                    status = "CRITICAL"

            # keep track of messages that clear an older message
            if event_entry.get("SensorNumber") is not None and severity == "OK":
                assoc_id_status[assoc_id] = "cleared"

        if (date_critical is not None or date_warning is not None) and severity is not None:

            entry_date = get_log_entry_time(date)

            if entry_date is not None and date_critical is not None:
                if entry_date > date_critical.astimezone(entry_date.tzinfo) and severity != "OK":
                    status = "CRITICAL"
            if entry_date is not None and date_warning is not None:
                if entry_date > date_warning.astimezone(
                        entry_date.tzinfo) and status != "CRITICAL" and severity != "OK":
                    status = "WARNING"

        plugin_object.add_log_output_data(status, "%s: %s" % (date, message))

        processed_ids.append(event_entry_item.get("Id"))

        # obey max results returned
        if plugin_object.cli_args.max is not None and num_entry >= plugin_object.cli_args.max:
            return

    return
Esempio n. 10
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
Esempio n. 11
0
def get_event_log_hpe(plugin_object, event_type, redfish_path):

    limit_of_returned_items = plugin_object.cli_args.max
    forced_limit = False
    data_now = datetime.datetime.now()
    date_warning = None
    date_critical = None

    if plugin_object.rf.vendor_data.ilo_version.lower() != "ilo 5":
        ilo4_limit = 30
        if plugin_object.cli_args.max:
            limit_of_returned_items = min(plugin_object.cli_args.max, ilo4_limit)
            if plugin_object.cli_args.max > ilo4_limit:
                forced_limit = True
        else:
            forced_limit = True
            limit_of_returned_items = ilo4_limit

    if event_type == "Manager":

        if plugin_object.cli_args.warning:
            date_warning = data_now - datetime.timedelta(days=int(plugin_object.cli_args.warning))
        if plugin_object.cli_args.critical:
            date_critical = data_now - datetime.timedelta(days=int(plugin_object.cli_args.critical))

    event_entries = plugin_object.rf.get(redfish_path).get("Members")

    if len(event_entries) == 0:
        plugin_object.add_output_data("OK", f"No {event_type} log entries found.",
                                      summary=not plugin_object.cli_args.detailed)
        return

    # reverse list from newest to oldest entry
    event_entries.reverse()

    num_entry = 0
    for event_entry_item in event_entries:

        if event_entry_item.get("@odata.context"):
            event_entry = event_entry_item
        else:
            event_entry = plugin_object.rf.get(event_entry_item.get("@odata.id"))

        num_entry += 1

        message = event_entry.get("Message")
        severity = event_entry.get("Severity")
        if severity is not None:
            severity = severity.upper()
        date = event_entry.get("Created") or "1970-01-01T00:00:00Z"
        entry_date = get_log_entry_time(date)
        repaired = grab(event_entry, f"Oem.{plugin_object.rf.vendor_dict_key}.Repaired") or False

        status = "OK"

        if event_type == "System":
            if severity == "WARNING" and repaired is False:
                status = "WARNING"
            elif severity != "OK" and repaired is False:
                status = "CRITICAL"
        else:

            if plugin_object.cli_args.critical and date_critical is not None:
                if entry_date > date_critical.astimezone(entry_date.tzinfo) and severity != "OK":
                    status = "CRITICAL"
            if plugin_object.cli_args.warning and date_warning is not None:
                if entry_date > date_warning.astimezone(entry_date.tzinfo) \
                        and status != "CRITICAL" and severity != "OK":
                    status = "WARNING"

        plugin_object.add_log_output_data(status, "%s: %s" % (date, message))

        # obey max results returned
        if limit_of_returned_items is not None and num_entry >= limit_of_returned_items:
            if forced_limit:
                plugin_object.add_log_output_data("OK", f"This is an {plugin_object.rf.vendor_data.ilo_version}, "
                                                        f"limited {event_type} log results to "
                                                        f"{limit_of_returned_items} entries")
            return

    return
Esempio n. 12
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
Esempio n. 13
0
def get_firmware_info_fujitsu(plugin_object, system_id, bmc_only=False):
    # there is room for improvement

    # list of dicts: keys: {name, version, location}
    firmware_entries = list()

    # get iRMC firmware
    manager_ids = plugin_object.rf.get_system_properties("managers")

    if manager_ids is not None and len(manager_ids) > 0:

        manager_response = plugin_object.rf.get(manager_ids[0])

        # get configuration
        irmc_configuration_link = grab(manager_response,
                                       f"Oem/{plugin_object.rf.vendor_dict_key}/iRMCConfiguration/@odata.id",
                                       separator="/")

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

        irmc_firmware_information = None
        firmware_information_link = grab(irmc_configuration, f"FWUpdate/@odata.id", separator="/")
        if firmware_information_link is not None:
            irmc_firmware_information = plugin_object.rf.get(firmware_information_link)

        if irmc_firmware_information is not None:
            for bmc_fw_bank in ["iRMCFwImageHigh", "iRMCFwImageLow"]:
                fw_info = irmc_firmware_information.get(bmc_fw_bank)
                if fw_info is not None:
                    firmware_entries.append(
                        {"id": bmc_fw_bank,
                         "name": "%s iRMC" % fw_info.get("FirmwareRunningState"),
                         "version": "%s, Booter %s, SDDR: %s/%s (%s)" % (
                             fw_info.get("FirmwareVersion"),
                             fw_info.get("BooterVersion"),
                             fw_info.get("SDRRVersion"),
                             fw_info.get("SDRRId"),
                             fw_info.get("FirmwareBuildDate")
                         ),
                         "location": "System Board"
                         }
                    )

        # special case:
        #   Firmware information was requested from bmc check.
        #   So we just return the bmc firmware list
        if bmc_only is True:
            return firmware_entries

    # get power supply firmware
    chassi_ids = plugin_object.rf.get_system_properties("chassis")

    if chassi_ids is not None and len(chassi_ids) > 0:

        for chassi_id in chassi_ids:
            power_data = plugin_object.rf.get(f"{chassi_id}/Power")

            if power_data.get("PowerSupplies") is not None and len(power_data.get("PowerSupplies")) > 0:

                for ps_data in power_data.get("PowerSupplies"):
                    ps_manufacturer = ps_data.get("Manufacturer")
                    ps_location = ps_data.get("Name")
                    ps_model = ps_data.get("Model")
                    ps_fw_version = ps_data.get("FirmwareVersion")

                    firmware_entries.append({
                        "id": f"{ps_location}",
                        "name": f"Power Supply {ps_manufacturer} {ps_model}",
                        "version": f"{ps_fw_version}",
                        "location": f"{ps_location}"
                    })

    # get hard drive firmware
    redfish_url = f"{system_id}/Storage" + "%s" % plugin_object.rf.vendor_data.expand_string

    storage_response = plugin_object.rf.get(redfish_url)

    for storage_member in storage_response.get("Members"):

        if storage_member.get("@odata.context"):
            controller_response = storage_member
        else:
            controller_response = plugin_object.rf.get(storage_member.get("@odata.id"))

        for controller_drive in controller_response.get("Drives"):
            drive_response = plugin_object.rf.get(controller_drive.get("@odata.id"))

            if drive_response.get("Name") is not None:
                drive_name = drive_response.get("Name")
                drive_firmware = drive_response.get("Revision")
                drive_slot = grab(drive_response, f"Oem.{plugin_object.rf.vendor_dict_key}.SlotNumber")
                drive_storage_controller = controller_response.get("Id")

                firmware_entries.append({
                    "id": f"Drive:{drive_storage_controller}:{drive_slot}",
                    "name": f"Drive {drive_name}",
                    "version": f"{drive_firmware}",
                    "location": f"{drive_storage_controller}:{drive_slot}"
                })

    # get other firmware
    redfish_url = f"{system_id}/Oem/%s/FirmwareInventory/" % plugin_object.rf.vendor_dict_key

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

    firmware_response = plugin_object.rf.get(redfish_url)

    # get BIOS
    if firmware_response.get("SystemBIOS"):
        firmware_entries.append({
            "id": f"System:{system_id_num}",
            "name": "SystemBIOS",
            "version": "%s" % firmware_response.get("SystemBIOS"),
            "location": "System Board"
        })

    # get other components
    for key, value in firmware_response.items():

        if key.startswith("@"):
            continue

        if isinstance(value, dict) and value.get("@odata.id") is not None:
            component_type = value.get("@odata.id").rstrip("/").split("/")[-1]
            component_fw_data = plugin_object.rf.get(value.get("@odata.id"))

            if component_fw_data.get("Ports") is not None and len(component_fw_data.get("Ports")) > 0:

                component_id = 0
                for component_entry in component_fw_data.get("Ports"):
                    component_id += 1

                    component_name = component_entry.get("AdapterName")
                    component_location = component_entry.get("ModuleName")
                    component_bios_version = component_entry.get("BiosVersion")
                    component_fw_version = component_entry.get("FirmwareVersion")
                    component_slot = component_entry.get("SlotId")
                    component_port = component_entry.get("PortId")

                    firmware_entries.append({
                        "id": f"{component_type}_Port_{component_id}",
                        "name": f"{component_name}",
                        "version": f"{component_fw_version} (BIOS: {component_bios_version})",
                        "location": f"{component_location} {component_slot}/{component_port}"
                    })

            if component_fw_data.get("Adapters") is not None and len(component_fw_data.get("Adapters")) > 0:

                component_id = 0
                for component_entry in component_fw_data.get("Adapters"):
                    component_id += 1

                    component_name = component_entry.get("ModuleName")
                    component_pci_segment = component_entry.get("PciSegment")
                    component_bios_version = component_entry.get("BiosVersion")
                    component_fw_version = component_entry.get("FirmwareVersion")

                    firmware_entries.append({
                        "id": f"{component_type}_Adapter_{component_id}",
                        "name": f"{component_name} controller",
                        "version": f"{component_fw_version} (BIOS: {component_bios_version})",
                        "location": f"{system_id_num}:{component_pci_segment}"
                    })

    # add firmware entry to inventory
    for fw_entry in firmware_entries:

        firmware_inventory = Firmware(**fw_entry)

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

        plugin_object.inventory.add(firmware_inventory)

    return
Esempio n. 14
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
Esempio n. 15
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
Esempio n. 16
0
def get_firmware_info_fujitsu(plugin_object, system_id, bmc_only=False):
    # there is room for improvement

    # list of dicts: keys: {name, version, location}
    firmware_entries = list()

    # get iRMC firmware
    manager_ids = plugin_object.rf.get_system_properties("managers")

    if manager_ids is not None and len(manager_ids) > 0:

        manager_response = plugin_object.rf.get(manager_ids[0])

        if manager_response.get("error"):
            plugin_object.add_data_retrieval_error(Firmware, manager_response,
                                                   manager_ids[0])
            return

        # get configuration
        irmc_configuration_link = grab(
            manager_response,
            f"Oem/{plugin_object.rf.vendor_dict_key}/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(
                    Firmware, irmc_configuration, irmc_configuration_link)

        irmc_firmware_information = None
        firmware_information_link = grab(irmc_configuration,
                                         f"FWUpdate/@odata.id",
                                         separator="/")
        if firmware_information_link is not None:
            irmc_firmware_information = plugin_object.rf.get(
                firmware_information_link)

            if irmc_firmware_information.get("error"):
                plugin_object.add_data_retrieval_error(
                    Firmware, irmc_firmware_information,
                    irmc_configuration_link)

        if irmc_firmware_information is not None:
            for bmc_fw_bank in ["iRMCFwImageHigh", "iRMCFwImageLow"]:
                fw_info = irmc_firmware_information.get(bmc_fw_bank)
                if fw_info is not None:
                    firmware_entries.append({
                        "id":
                        bmc_fw_bank,
                        "name":
                        "%s iRMC" % fw_info.get("FirmwareRunningState"),
                        "version":
                        "%s, Booter %s, SDDR: %s/%s (%s)" %
                        (fw_info.get("FirmwareVersion"),
                         fw_info.get("BooterVersion"),
                         fw_info.get("SDRRVersion"), fw_info.get("SDRRId"),
                         fw_info.get("FirmwareBuildDate")),
                        "location":
                        "System Board"
                    })

        # special case:
        #   Firmware information was requested from bmc check.
        #   So we just return the bmc firmware list
        if bmc_only is True:
            return firmware_entries

    # get power supply and storage firmware
    plugin_object.in_firmware_collection_mode(True)
    if any(x in plugin_object.cli_args.requested_query
           for x in ['power', 'all']) is False:
        get_chassi_data(plugin_object, PowerSupply)
    if any(x in plugin_object.cli_args.requested_query
           for x in ['storage', 'all']) is False:
        get_storage(plugin_object)
    plugin_object.in_firmware_collection_mode(False)

    for power_supply in plugin_object.inventory.get(PowerSupply):

        firmware_entries.append({
            "id": f"{power_supply.name}",
            "name": f"Power Supply {power_supply.vendor} {power_supply.model}",
            "version": f"{power_supply.firmware}",
            "location": f"{power_supply.name}"
        })

    for drive in plugin_object.inventory.get(PhysicalDrive):

        firmware_entries.append({
            "id": f"Drive:{drive.id}",
            "name": f"Drive {drive.name}",
            "version": f"{drive.firmware}",
            "location": f"Slot {drive.bay}"
        })

    # get other firmware
    redfish_url = f"{system_id}/Oem/%s/FirmwareInventory/" % plugin_object.rf.vendor_dict_key

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

    firmware_response = plugin_object.rf.get(redfish_url)

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

    # get BIOS
    if firmware_response.get("SystemBIOS"):
        firmware_entries.append({
            "id":
            f"System:{system_id_num}",
            "name":
            "SystemBIOS",
            "version":
            "%s" % firmware_response.get("SystemBIOS"),
            "location":
            "System Board"
        })

    # get other components
    for key, value in firmware_response.items():

        if key.startswith("@"):
            continue

        if isinstance(value, dict) and value.get("@odata.id") is not None:
            component_type = value.get("@odata.id").rstrip("/").split("/")[-1]
            component_fw_data = plugin_object.rf.get(value.get("@odata.id"))

            if component_fw_data.get("error"):
                plugin_object.add_data_retrieval_error(Firmware,
                                                       component_fw_data,
                                                       value.get("@odata.id"))

            component_id = 0
            for component_entry in component_fw_data.get("Ports", list()):
                component_id += 1

                component_name = component_entry.get("AdapterName")
                component_location = component_entry.get("ModuleName")
                component_bios_version = component_entry.get("BiosVersion")
                component_fw_version = component_entry.get("FirmwareVersion")
                component_slot = component_entry.get("SlotId")
                component_port = component_entry.get("PortId")

                firmware_entries.append({
                    "id":
                    f"{component_type}_Port_{component_id}",
                    "name":
                    f"{component_name}",
                    "version":
                    f"{component_fw_version} (BIOS: {component_bios_version})",
                    "location":
                    f"{component_location} {component_slot}/{component_port}"
                })

            component_id = 0
            for component_entry in component_fw_data.get("Adapters", list()):
                component_id += 1

                component_name = component_entry.get("ModuleName")
                component_pci_segment = component_entry.get("PciSegment")
                component_bios_version = component_entry.get("BiosVersion")
                component_fw_version = component_entry.get("FirmwareVersion")

                firmware_entries.append({
                    "id":
                    f"{component_type}_Adapter_{component_id}",
                    "name":
                    f"{component_name} controller",
                    "version":
                    f"{component_fw_version} (BIOS: {component_bios_version})",
                    "location":
                    f"{system_id_num}:{component_pci_segment}"
                })

    # add firmware entry to inventory
    for fw_entry in firmware_entries:

        firmware_inventory = Firmware(**fw_entry)

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

        plugin_object.inventory.add(firmware_inventory)

    return
Esempio n. 17
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
Esempio n. 18
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
Esempio n. 19
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
Esempio n. 20
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
Esempio n. 21
0
    def determine_vendor(self):

        vendor_string = ""

        if self.connection.root.get("Oem"):

            if len(self.connection.root.get("Oem")) > 0:
                vendor_string = list(self.connection.root.get("Oem"))[0]

            self.vendor_dict_key = vendor_string

        if vendor_string == "" and self.connection.root.get(
                "Vendor") is not None:

            vendor_string = self.connection.root.get("Vendor")

            self.vendor_dict_key = vendor_string

        if vendor_string in ["Hpe", "Hp"]:

            self.vendor_data = VendorHPEData()

            manager_data = grab(self.connection.root,
                                f"Oem.{vendor_string}.Manager.0")

            if manager_data is not None:
                self.vendor_data.ilo_version = manager_data.get("ManagerType")
                if self.vendor_data.ilo_version is None:
                    # Fix for iLO 5 version >2.3.0
                    self.vendor_data.ilo_version = \
                        grab(self.connection.root, f"Oem.{vendor_string}.Moniker.PRODGEN")

                self.vendor_data.ilo_firmware_version = manager_data.get(
                    "ManagerFirmwareVersion")
                if self.vendor_data.ilo_firmware_version is None:
                    # Fix for iLO 5 version >2.3.0
                    self.vendor_data.ilo_firmware_version = grab(
                        manager_data, "Languages.0.Version")

                if self.vendor_data.ilo_version is None:
                    self.exit_on_error(
                        "Cannot determine HPE iLO version information.")

                if self.vendor_data.ilo_version.lower() == "ilo 5":
                    self.vendor_data.view_supported = True

        if vendor_string in ["Lenovo"]:

            self.vendor_data = VendorLenovoData()

        if vendor_string in ["Dell"]:

            self.vendor_data = VendorDellData()

        if vendor_string in ["Huawei"]:

            self.vendor_data = VendorHuaweiData()

        if vendor_string in ["ts_fujitsu"]:

            self.vendor_data = VendorFujitsuData()

        # Cisco does not provide a OEM property in root object
        if "CIMC" in str(self.get_system_properties("managers")):

            self.vendor_data = VendorCiscoData()
            self.vendor_dict_key = self.vendor_data.name

        if self.vendor_data is None:

            self.vendor_data = VendorGeneric()

            if vendor_string is not None and len(vendor_string) > 0:
                self.vendor_data.name = vendor_string

        self.vendor = self.vendor_data.name

        return
Esempio n. 22
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
Esempio n. 23
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
Esempio n. 24
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