WIP: adds more custom fields for a better data representation

This commit is contained in:
ricardo.bartels@telekom.de
2021-09-10 12:37:43 +02:00
parent 37715b2fa7
commit 34d11017ac
2 changed files with 98 additions and 55 deletions

View File

@@ -790,24 +790,22 @@ class NBCustomField(NetBoxObject):
prune = False
# used by this software
valid_content_types = [
"dcim.device",
"dcim.interface",
"dcim.inventoryitem",
"dcim.powerport",
"virtualization.vminterface"
]
def __init__(self, *args, **kwargs):
self.data_model = {
"content_types": list,
"type": ["text", "integer", "boolean", "date", "url", "select", "multiselect"],
"name": 50,
"label": 50,
"description": 200,
"required": bool,
"default": str,
"choices": list
}
super().__init__(*args, **kwargs)
data_model = {
"content_types": list,
"type": ["text", "integer", "boolean", "date", "url", "select", "multiselect"],
"name": 50,
"label": 50,
"description": 200,
"required": bool,
"default": str,
"choices": list
}
def update(self, data=None, read_from_netbox=False, source=None):
"""

View File

@@ -22,6 +22,15 @@ from module.netbox.inventory import interface_speed_type_mapping
log = get_logger()
#
# ToDo:
# * fix custom field merging data dicts
# * get inventory for this device depending on the type
# * match source inventory items witch NetBox items
# * delete items which don't exist anymore
# * add interface IPs
# * implement checking for permitted IPs
class CheckRedfish:
@@ -133,7 +142,7 @@ class CheckRedfish:
def apply(self):
self.add_firmware_custom_field()
self.add_necessary_custom_fields()
for filename in glob.glob(f"{self.inventory_file_path}/*.json"):
@@ -259,6 +268,8 @@ class CheckRedfish:
# compile inventory item data
self._update_item({
"inventory_type": "Power Supply",
"health": health_status,
"device": device_object,
"description": description,
"full_name": name,
@@ -284,7 +295,7 @@ class CheckRedfish:
if capacity_in_watt is not None:
ps_data["maximum_draw"] = capacity_in_watt
if firmware is not None:
ps_data["custom_fields"] = {"firmware": firmware}
ps_data["custom_fields"] = {"firmware": firmware, "health": health_status}
# add/update power supply data
ps_object = grab(current_ps, f"{ps_index}")
@@ -312,10 +323,12 @@ class CheckRedfish:
description.append(f"Context: {physical_context}")
self._update_item({
"inventory_type": "Fan",
"device": device_object,
"description": description,
"name_start": fan_name,
"full_name": fan_name
"full_name": fan_name,
"health": health_status
})
def update_memory(self, device_object, inventory_data):
@@ -358,13 +371,15 @@ class CheckRedfish:
description.append(f"Slot: {slot}")
self._update_item({
"inventory_type": "DIMM",
"device": device_object,
"description": description,
"name_start": memory_name,
"full_name": name,
"serial": get_string_or_none(grab(memory, "serial")),
"manufacturer": get_string_or_none(grab(memory, "manufacturer")),
"part_number": get_string_or_none(grab(memory, "part_number"))
"part_number": get_string_or_none(grab(memory, "part_number")),
"health": health_status
})
def update_proc(self, device_object, inventory_data):
@@ -380,6 +395,7 @@ class CheckRedfish:
cores = get_string_or_none(grab(processor, "cores"))
threads = get_string_or_none(grab(processor, "threads"))
socket = get_string_or_none(grab(processor, "socket"))
health_status = get_string_or_none(grab(processor, "health_status"))
name = f"{socket} ({model})"
@@ -394,12 +410,14 @@ class CheckRedfish:
description.append(f"Threads: {threads}")
self._update_item({
"inventory_type": "CPU",
"device": device_object,
"description": description,
"manufacturer": get_string_or_none(grab(processor, "manufacturer")),
"full_name": name,
"name_start": socket,
"serial": get_string_or_none(grab(processor, "serial"))
"serial": get_string_or_none(grab(processor, "serial")),
"health": health_status
})
def update_physical_drive(self, device_object, inventory_data):
@@ -448,16 +466,13 @@ class CheckRedfish:
name += f" ({' '.join(name_details)})"
description = list()
if health_status is not None:
description.append(f"Health: {health_status}")
if interface_type is not None:
description.append(f"Interface: {interface_type}")
if speed_in_rpm is not None:
description.append(f"Speed: {speed_in_rpm}RPM")
if firmware is not None:
description.append(f"Firmware: {firmware}")
self._update_item({
"inventory_type": "Physical Drive",
"device": device_object,
"description": description,
"manufacturer": get_string_or_none(grab(pd, "manufacturer")),
@@ -465,7 +480,8 @@ class CheckRedfish:
"name_start": pd_name,
"serial": serial,
"part_number": get_string_or_none(grab(pd, "part_number")),
"firmware": firmware
"firmware": firmware,
"health": health_status
})
def update_storage_controller(self, device_object, inventory_data):
@@ -490,20 +506,15 @@ class CheckRedfish:
if location is not None and location not in name:
name += f" {location}"
description = list()
if health_status is not None:
description.append(f"Health: {health_status}")
if firmware is not None:
description.append(f"Firmware: {firmware}")
self._update_item({
"inventory_type": "Storage Controller",
"device": device_object,
"description": description,
"manufacturer": get_string_or_none(grab(sc, "manufacturer")),
"full_name": name,
"name_start": sc_name,
"serial": serial,
"firmware": firmware
"firmware": firmware,
"health": health_status
})
def update_network_adapter(self, device_object, inventory_data):
@@ -530,21 +541,16 @@ class CheckRedfish:
if num_ports is not None:
name += f" ({num_ports} ports)"
description = list()
if health_status is not None:
description.append(f"Health: {health_status}")
if firmware is not None:
description.append(f"Firmware: {firmware}")
self._update_item({
"inventory_type": "NIC",
"device": device_object,
"description": description,
"manufacturer": get_string_or_none(grab(adapter, "manufacturer")),
"full_name": name,
"name_start": adapter_name,
"serial": serial,
"part_number": get_string_or_none(grab(adapter, "part_number")),
"firmware": firmware
"firmware": firmware,
"health": health_status
})
def update_network_interface(self, device_object, inventory_data):
@@ -564,6 +570,7 @@ class CheckRedfish:
link_status = get_string_or_none(grab(nic_port, "link_status"))
manager_ids = grab(nic_port, "manager_ids", fallback=list())
hostname = get_string_or_none(grab(nic_port, "hostname"))
health_status = get_string_or_none(grab(nic_port, "health_status"))
if port_name is None:
port_name = port_id
@@ -592,13 +599,15 @@ class CheckRedfish:
enabled = True
port_data_dict[port_name] = {
"inventory_type": "NIC Port",
"name": port_name,
"device": device_object,
"mac_address": normalize_mac_address(mac_address),
"enabled": enabled,
"description": ", ".join(description),
"type": interface_speed_type_mapping.get(link_speed, "other"),
"mgmt_only": mgmt_only
"mgmt_only": mgmt_only,
"health": health_status
}
data = map_object_interfaces_to_current_interfaces(self.inventory, device_object, port_data_dict)
@@ -639,6 +648,8 @@ class CheckRedfish:
serial = item_data.get("serial")
description = item_data.get("description")
firmware = item_data.get("firmware")
health = item_data.get("health")
inventory_type = item_data.get("inventory_type")
if device is None or name_start is None:
return False
@@ -653,6 +664,7 @@ class CheckRedfish:
"name": full_name,
}
custom_fields = dict()
if description is not None and len(description) > 0:
inventory_data["description"] = description
if serial is not None:
@@ -663,8 +675,17 @@ class CheckRedfish:
inventory_data["part_id"] = part_number
if label is not None:
inventory_data["label"] = label
# custom fields
if firmware is not None:
inventory_data["custom_fields"] = {"firmware": firmware}
custom_fields["firmware"] = firmware
if health is not None:
custom_fields["health"] = health
if inventory_type is not None:
custom_fields["inventory-type"] = inventory_type
if len(custom_fields.keys()) > 0:
inventory_data["custom_fields"] = custom_fields
# find inventory item
inventory_object = None
@@ -699,25 +720,49 @@ class CheckRedfish:
return True
def add_firmware_custom_field(self):
content_types = [
"dcim.inventoryitem",
"dcim.powerport"
]
data = {
"name": "firmware",
"label": "Firmware",
"content_types": content_types,
"type": "text",
"description": "Item Firmware"
}
def add_update_custom_field(self, data):
custom_field = self.inventory.get_by_data(NBCustomField, data={"name": data.get("name")})
if custom_field is None:
self.inventory.add_object(NBCustomField, data=data, source=self)
else:
custom_field.update(data={"content_types": content_types}, source=self)
custom_field.update(data={"content_types": data.get("content_types")}, source=self)
def add_necessary_custom_fields(self):
# add Firmware
self.add_update_custom_field({
"name": "firmware",
"label": "Firmware",
"content_types": [
"dcim.inventoryitem",
"dcim.powerport"
],
"type": "text",
"description": "Item Firmware"
})
# add inventory type
self.add_update_custom_field({
"name": "inventory-type",
"label": "Type",
"content_types": ["dcim.inventoryitem"],
"type": "text",
"description": "Describes the type of inventory"
})
# add health status
self.add_update_custom_field({
"name": "health",
"label": "Health",
"content_types": [
"dcim.inventoryitem",
"dcim.powerport",
"dcim.device"
],
"type": "text",
"description": "Shows the currently discovered health status"
})
# EOF