mirror of
https://github.com/netbox-community/devicetype-library.git
synced 2025-08-08 22:54:52 +02:00
Adding Tests: Device Power (#1463)
* broke component validation out to its own function. Adding logic for validating device power input. * Added console-port poe true for adapters. Updating devices to add proper power sources. * Adding switches to allow for tests to properly determine POE status. * Fixing files with missing power definitions.
This commit is contained in:
@ -8,6 +8,7 @@ class DeviceType:
|
||||
def __init__(self, definition, file_path):
|
||||
self.file_path = file_path
|
||||
self.isDevice = True
|
||||
self.definition = definition
|
||||
self.manufacturer = definition.get('manufacturer')
|
||||
self._slug_manufacturer = self._slugify_manufacturer()
|
||||
self.slug = definition.get('slug')
|
||||
@ -60,6 +61,59 @@ class DeviceType:
|
||||
KNOWN_SLUGS.add(self.slug)
|
||||
return True
|
||||
|
||||
def validate_power(self):
|
||||
# Check if power-ports exists
|
||||
if self.definition.get('power-ports', False):
|
||||
# Verify that is_powered is not set to False. If so, there should not be any power-ports defined
|
||||
if not self.definition.get('is_powered', True):
|
||||
self.failureMessage = f'{self.file_path} has is_powered set to False, but "power-ports" are defined.'
|
||||
return False
|
||||
return True
|
||||
|
||||
# Lastly, check if interfaces exists and has a poe_mode defined
|
||||
interfaces = self.definition.get('interfaces', False)
|
||||
if interfaces:
|
||||
for interface in interfaces:
|
||||
poe_mode = interface.get('poe_mode', "")
|
||||
if poe_mode != "" and poe_mode == "pd":
|
||||
return True
|
||||
|
||||
console_ports = self.definition.get('console-ports', False)
|
||||
if console_ports:
|
||||
for console_port in console_ports:
|
||||
poe = console_port.get('poe', False)
|
||||
if poe:
|
||||
return True
|
||||
|
||||
rear_ports = self.definition.get('rear-ports', False)
|
||||
if rear_ports:
|
||||
for rear_port in rear_ports:
|
||||
poe = rear_port.get('poe', False)
|
||||
if poe:
|
||||
return True
|
||||
|
||||
# Check if the device is a child device, and if so, assume it has a valid power source from the parent
|
||||
subdevice_role = self.definition.get('subdevice_role', False)
|
||||
if subdevice_role:
|
||||
if subdevice_role == "child":
|
||||
return True
|
||||
|
||||
# Check if module-bays exists
|
||||
if self.definition.get('module-bays', False):
|
||||
# There is not a standardized way to define PSUs that are module bays, so we will just assume they are valid
|
||||
return True
|
||||
|
||||
# As the very last case, check if is_powered is defined and is False. Otherwise assume the device is powered
|
||||
if not self.definition.get('is_powered', True): # is_powered defaults to True
|
||||
# Arriving here means is_powered is set to False, so verify that there are no power-outlets defined
|
||||
if self.definition.get('power-outlets', False):
|
||||
self.failureMessage = f'{self.file_path} has is_powered set to False, but "power-outlets" are defined.'
|
||||
return False
|
||||
return True
|
||||
|
||||
self.failureMessage = f'{self.file_path} has does not appear to have a valid power source. Ensure either "power-ports" or "interfaces" with "poe_mode" is defined.'
|
||||
return False
|
||||
|
||||
class ModuleType:
|
||||
def __new__(cls, *args, **kwargs):
|
||||
return super().__new__(cls)
|
||||
@ -67,6 +121,7 @@ class ModuleType:
|
||||
def __init__(self, definition, file_path):
|
||||
self.file_path = file_path
|
||||
self.isDevice = False
|
||||
self.definition = definition
|
||||
self.manufacturer = definition.get('manufacturer')
|
||||
self.model = definition.get('model')
|
||||
self._slug_model = self._slugify_model()
|
||||
@ -96,4 +151,26 @@ def verify_filename(device: (DeviceType or ModuleType)):
|
||||
device.failureMessage = f'{device.file_path} file name is invalid. Must be either the model "{device._slug_model}" or part_number "{device.part_number} / {device._slug_part_number}"'
|
||||
return False
|
||||
|
||||
return True
|
||||
return True
|
||||
|
||||
def validate_components(component_types, device_or_module):
|
||||
for component_type in component_types:
|
||||
known_names = set()
|
||||
defined_components = device_or_module.definition.get(component_type, [])
|
||||
if not isinstance(defined_components, list):
|
||||
device_or_module.failureMessage = f'{device_or_module.file_path} has an invalid definition for {component_type}.'
|
||||
return False
|
||||
for idx, component in enumerate(defined_components):
|
||||
if not isinstance(component, dict):
|
||||
device_or_module.failureMessage = f'{device_or_module.file_path} has an invalid definition for {component_type} ({idx}).'
|
||||
return False
|
||||
name = component.get('name')
|
||||
if not isinstance(name, str):
|
||||
device_or_module.failureMessage = f'{device_or_module.file_path} has an invalid definition for {component_type} name ({idx}).'
|
||||
return False
|
||||
if name in known_names:
|
||||
device_or_module.failureMessage = f'{device_or_module.file_path} has duplicated names within {component_type} ({name}).'
|
||||
return False
|
||||
known_names.add(name)
|
||||
|
||||
return True
|
||||
|
Reference in New Issue
Block a user