def get_single_chassi_info(plugin_object, redfish_url): chassi_response = plugin_object.rf.get(redfish_url) # get status data status_data = get_status_data(chassi_response.get("Status")) chassi_inventory = Chassi( id=chassi_response.get("Id"), name=chassi_response.get("Name"), manufacturer=chassi_response.get("Manufacturer"), serial=chassi_response.get("SerialNumber"), health_status=status_data.get("Health"), operation_status=status_data.get("State"), sku=chassi_response.get("SKU"), indicator_led=chassi_response.get("IndicatorLED"), model=chassi_response.get("Model"), type=chassi_response.get("ChassisType")) if plugin_object.cli_args.verbose: chassi_inventory.source_data = chassi_response # add relations chassi_inventory.add_relation(plugin_object.rf.get_system_properties(), chassi_response.get("Links")) plugin_object.inventory.add(chassi_inventory) return
def get_single_chassi_info(plugin_object, redfish_url): chassi_response = plugin_object.rf.get(redfish_url) if chassi_response is None: plugin_object.inventory.add_issue(Chassi, f"No chassi information data returned for API URL '{redfish_url}'") return elif chassi_response.get("error"): plugin_object.add_data_retrieval_error(Chassi, chassi_response, redfish_url) return # get status data status_data = get_status_data(chassi_response.get("Status")) chassi_inventory = Chassi( id=chassi_response.get("Id"), name=chassi_response.get("Name"), manufacturer=chassi_response.get("Manufacturer"), serial=chassi_response.get("SerialNumber"), health_status=status_data.get("Health"), operation_status=status_data.get("State"), sku=chassi_response.get("SKU"), indicator_led=chassi_response.get("IndicatorLED"), model=chassi_response.get("Model"), type=chassi_response.get("ChassisType") ) if plugin_object.cli_args.verbose: chassi_inventory.source_data = chassi_response # add relations chassi_inventory.add_relation(plugin_object.rf.get_system_properties(), chassi_response.get("Links")) plugin_object.inventory.add(chassi_inventory) return
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_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
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
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
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
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
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
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
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
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
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
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
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
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