Skip to content

Commit

Permalink
fixes issue with redfish and vcenter interface sync overlap #342
Browse files Browse the repository at this point in the history
  • Loading branch information
bb-Ricardo committed Feb 13, 2024
1 parent 3460a86 commit 288165a
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 22 deletions.
57 changes: 41 additions & 16 deletions module/sources/check_redfish/import_inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class CheckRedfish(SourceBase):

device_object = None
inventory_file_content = None
manager_name = None

def __init__(self, name=None):

Expand Down Expand Up @@ -110,35 +111,47 @@ def apply(self):
try:
inventory_id = int(inventory_id)
except (ValueError, TypeError):
log.error(f"Value for meta.inventory_id '{inventory_id}' must be an integer. "
f"Cannot use inventory_id to match device in NetBox.")
log.warning(f"Value for meta.inventory_id '{inventory_id}' must be an integer. "
f"Cannot use inventory_id to match device in NetBox.")

self.device_object = self.inventory.get_by_id(NBDevice, inventory_id)

# try to find device by serial of first system in inventory
device_serial = grab(self.inventory_file_content, "inventory.system.0.serial")
if self.device_object is None:
self.device_object = self.inventory.get_by_data(NBDevice, data={
"serial": device_serial
})
if self.device_object is not None:
log.debug2("Found a matching %s object '%s' based on inventory id '%d'" %
(self.device_object.name,
self.device_object.get_display_name(including_second_key=True),
inventory_id))

if self.device_object is None:
log.error(f"Unable to find {NBDevice.name} with id '{inventory_id}' or "
f"serial '{device_serial}' in NetBox inventory from inventory file {filename}")
continue
else:
# try to find device by serial of first system in inventory
device_serial = grab(self.inventory_file_content, "inventory.system.0.serial")
if self.device_object is None:
self.device_object = self.inventory.get_by_data(NBDevice, data={
"serial": device_serial
})

if self.device_object is None:
log.error(f"Unable to find {NBDevice.name} with id '{inventory_id}' or "
f"serial '{device_serial}' in NetBox inventory from inventory file {filename}")
continue
else:
log.debug2("Found a matching %s object '%s' based on serial '%s'" %
(self.device_object.name,
self.device_object.get_display_name(including_second_key=True),
device_serial))

# parse all components
self.update_device()
self.update_power_supply()
self.update_fan()
self.update_memory()
self.update_proc()
self.update_manager() # reads manager name to set it via update_network_interface for BMC
self.update_physical_drive()
self.update_storage_controller()
self.update_storage_enclosure()
self.update_network_adapter()
self.update_network_interface()
self.update_manager()

def reset_inventory_state(self):
"""
Expand All @@ -147,6 +160,7 @@ def reset_inventory_state(self):

self.inventory_file_content = None
self.device_object = None
self.manager_name = None

# reset interface types
self.interface_adapter_type_dict = dict()
Expand Down Expand Up @@ -755,10 +769,15 @@ def update_network_interface(self):

# get enabled state
enabled = False

# assume that a mgmt_only interface is always enabled as we retrieved data via redfish
if "up" in f"{link_status}".lower() or mgmt_only is True:
enabled = True

# set BMC interface to manager name
if mgmt_only is True and self.manager_name is not None:
port_name = f"{self.manager_name} ({port_id})"

port_data_dict[port_name] = {
"inventory_type": "NIC Port",
"name": port_name,
Expand All @@ -771,6 +790,9 @@ def update_network_interface(self):
"health": health_status
}

if mgmt_only is True:
port_data_dict[port_name]["mode"] = "access"

# collect ip addresses
nic_ips[port_name] = list()
for ipv4_address in grab(nic_port, "ipv4_addresses", fallback=list()):
Expand All @@ -785,7 +807,7 @@ def update_network_interface(self):

nic_ips[port_name].append(ipv6_address)

data = self.map_object_interfaces_to_current_interfaces(self.device_object, port_data_dict)
data = self.map_object_interfaces_to_current_interfaces(self.device_object, port_data_dict, True)

for port_name, port_data in port_data_dict.items():

Expand Down Expand Up @@ -822,8 +844,8 @@ def update_network_interface(self):

# update nic object
nic_object.update(data=data_to_update, source=self)

self.add_update_interface(nic_object, self.device_object, port_data, nic_ips.get(port_name, list()))
else:
self.add_update_interface(nic_object, self.device_object, port_data, nic_ips.get(port_name, list()))

def update_manager(self):

Expand All @@ -840,6 +862,9 @@ def update_manager(self):
if model is not None and model not in name:
name += f" {model}"

if self.manager_name is None:
self.manager_name = name

description = None
if len(licenses) > 0:
description = f"Licenses: %s" % (", ".join(licenses))
Expand Down
20 changes: 14 additions & 6 deletions module/sources/common/source_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ def implements(cls, source_type):
def finish(self):
pass

def map_object_interfaces_to_current_interfaces(self, device_vm_object, interface_data_dict=None):
def map_object_interfaces_to_current_interfaces(self, device_vm_object, interface_data_dict=None,
append_unmatched_interfaces=False):
"""
Try to match current object interfaces to discovered ones. This will be done
by multiple approaches. Order as following listing whatever matches first will be chosen.
Expand All @@ -73,6 +74,8 @@ def map_object_interfaces_to_current_interfaces(self, device_vm_object, interfac
object type to look for
interface_data_dict: dict
dictionary with interface data to compare to existing machine
append_unmatched_interfaces: bool
if True add unmatched interfaces as new interfaces instead of trying to assign to en unmatched on
Returns
-------
Expand Down Expand Up @@ -163,12 +166,17 @@ def map_object_interfaces_to_current_interfaces(self, device_vm_object, interfac
current_object_interface_names.sort()
unmatched_interface_names.sort()

matching_nics = dict(zip(unmatched_interface_names, current_object_interface_names))
# Don't match to existing interfaces, just append additionally to list of interfaces
if append_unmatched_interfaces is True:
for int_name in unmatched_interface_names:
return_data[int_name] = None
else:
matching_nics = dict(zip(unmatched_interface_names, current_object_interface_names))

for new_int, current_int in matching_nics.items():
current_int_object = current_object_interfaces.get(current_int)
log.debug2(f"Matching '{new_int}' to NetBox Interface '{current_int_object.get_display_name()}'")
return_data[new_int] = current_int_object
for new_int, current_int in matching_nics.items():
current_int_object = current_object_interfaces.get(current_int)
log.debug2(f"Matching '{new_int}' to NetBox Interface '{current_int_object.get_display_name()}'")
return_data[new_int] = current_int_object

return return_data

Expand Down

0 comments on commit 288165a

Please sign in to comment.