Loading src/nbi/service/__main__.py +2 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ from common.Constants import ServiceNameEnum from common.Settings import ( ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_log_level, get_metrics_port, wait_for_environment_variables) from src.nbi.service.rest_server.nbi_plugins.ietf_hardware import register_ietf_hardware from .NbiService import NbiService from .rest_server.RestServer import RestServer from .rest_server.nbi_plugins.etsi_bwm import register_etsi_bwm_api Loading @@ -27,6 +27,7 @@ from .rest_server.nbi_plugins.ietf_l3vpn import register_ietf_l3vpn from .rest_server.nbi_plugins.ietf_network import register_ietf_network from .rest_server.nbi_plugins.ietf_network_slice import register_ietf_nss from .rest_server.nbi_plugins.tfs_api import register_tfs_api from .rest_server.nbi_plugins.ietf_hardware import register_ietf_hardware terminate = threading.Event() LOGGER = None Loading src/nbi/service/rest_server/nbi_plugins/ietf_hardware/Hardware.py +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ class Hardware(Resource): if device is None: raise Exception('Device({:s}) not found in database'.format(str(device_uuid))) yang_handler = YangHandler('ietf-hardware') yang_handler = YangHandler() hardware_reply = yang_handler.compose(device) yang_handler.destroy() Loading src/nbi/service/rest_server/nbi_plugins/ietf_hardware/YangHandler.py +46 −10 Original line number Diff line number Diff line Loading @@ -2,17 +2,27 @@ import libyang, os from common.proto.context_pb2 import Device from typing import Dict, Optional import logging import re import datetime LOGGER = logging.getLogger(__name__) YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') MODULE_NAME = 'ietf-hardware' YANG_MODULES = [ 'iana-hardware', 'ietf-hardware' ] class YangHandler: def __init__(self) -> None: self._yang_context = libyang.Context(YANG_DIR) self._yang_module = self._yang_context.load_module(MODULE_NAME) self._yang_module.feature_enable_all() for yang_module_name in YANG_MODULES: LOGGER.info('Loading module: {:s}'.format(str(yang_module_name))) self._yang_context.load_module(yang_module_name).feature_enable_all() def parse_to_dict(self, message : Dict) -> Dict: dnode : Optional[libyang.DNode] = self._yang_module.parse_data_dict( yang_module = self._yang_context.get_module('ietf-hardware') dnode : Optional[libyang.DNode] = yang_module.parse_data_dict( message, validate_present=True, validate=True, strict=True ) if dnode is None: raise Exception('Unable to parse Message({:s})'.format(str(message))) Loading @@ -20,11 +30,31 @@ class YangHandler: dnode.free() return message @staticmethod def convert_to_iso_date(date_str: str) -> Optional[str]: date_str = date_str.strip('"') # Define the regex pattern for ISO 8601 date format pattern = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[\+\-]\d{2}:\d{2})" # Check if the input date string matches the pattern if re.match(pattern, date_str): return date_str # Already in ISO format else: try: # Parse the input date string as a datetime object datetime_obj = datetime.datetime.strptime(date_str, "%Y-%m-%d") # Convert to ISO format iso_date = datetime_obj.isoformat() + "Z" return iso_date except ValueError: return None # Invalid date format def compose(self, device : Device) -> Dict: # compose device iterating through the components hardware = self._yang_context.create_data_path('/ietf-hardware:hardware') physical_index = 0 physical_index = 1 for component in device.components: attributes = component.attributes Loading @@ -39,29 +69,35 @@ class YangHandler: if component_type == "FRU" : component_type = "slack" component_new.create_path('isfru', True) component_new.create_path('is-fru', True) else : component_new.create_path('isfru', False) component_new.create_path('is-fru', False) component_type = component_type.replace("_", "-").lower() component_type = 'iana-hardware:' + component_type component_new.create_path('class', component_type) #Añadir resto de atributos en IETF physical_index += physical_index physical_index += 1 component_new.create_path('physical-index', physical_index) component_new.create_path('description', attributes["description"]) component_new.create_path('parent', component.parent) if attributes["mfg-date"] != "": mfg_date = self.convert_to_iso_date(attributes["mfg-date"]) LOGGER.info('component[name="{:s}"]'.format(attributes["mfg-date"])) component_new.create_path('mfg-date', mfg_date) component_new.create_path('hardware-rev', attributes["hardware-rev"]) component_new.create_path('software-rev', attributes["software-rev"]) component_new.create_path('firmware-rev', attributes["firmware-version"]) component_new.create_path('serial-num', attributes["serial-num"]) component_new.create_path('mfg-name', attributes["mfg-name"]) component_new.create_path('mfg-date', attributes["mfg-date"]) if attributes["id"]: component_new.create_path('parent-rel-pos', attributes["id"]) component_new.create_path('uri', component.name) Loading src/nbi/service/rest_server/nbi_plugins/ietf_hardware/__init__.py +1 −1 Original line number Diff line number Diff line from nbi.service.rest_server.nbi_plugins.ietf_hardware.Hardware import Hardware from nbi.service.rest_server.RestServer import RestServer URL_PREFIX = "/restconf/data/device=<device_uuid>/ietf-hardware:hardware" URL_PREFIX = "/restconf/data/device=<path:device_uuid>/ietf-hardware:hardware" def register_ietf_hardware(rest_server: RestServer): rest_server.add_resource(Hardware, URL_PREFIX) No newline at end of file src/nbi/service/rest_server/nbi_plugins/tfs_api/__init__.py +3 −3 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ from nbi.service.rest_server.RestServer import RestServer from .Resources import ( Connection, ConnectionIds, Connections, Context, ContextIds, Contexts, Device, DeviceIds, Deviceshw, Device, DeviceIds, Devices, Deviceshw, DummyContexts, Link, LinkIds, Links, PolicyRule, PolicyRuleIds, PolicyRules, Loading Loading @@ -46,11 +46,11 @@ RESOURCES = [ ('api.slice_ids', SliceIds, '/context/<path:context_uuid>/slice_ids'), ('api.slices', Slices, '/context/<path:context_uuid>/slices'), ('api.slice', Slice, '/context/<path:context_uuid>/slice/<path:slice_uuid>'), ''' ('api.device_ids', DeviceIds, '/device_ids'), ('api.devices', Devices, '/devices'), ('api.device', Device, '/device/<path:device_uuid>'), ''' ('api.deviceshw', Deviceshw, '/device/<path:device_uuid>/hardware'), ('api.link_ids', LinkIds, '/link_ids'), Loading Loading
src/nbi/service/__main__.py +2 −1 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ from common.Constants import ServiceNameEnum from common.Settings import ( ENVVAR_SUFIX_SERVICE_HOST, ENVVAR_SUFIX_SERVICE_PORT_GRPC, get_env_var_name, get_log_level, get_metrics_port, wait_for_environment_variables) from src.nbi.service.rest_server.nbi_plugins.ietf_hardware import register_ietf_hardware from .NbiService import NbiService from .rest_server.RestServer import RestServer from .rest_server.nbi_plugins.etsi_bwm import register_etsi_bwm_api Loading @@ -27,6 +27,7 @@ from .rest_server.nbi_plugins.ietf_l3vpn import register_ietf_l3vpn from .rest_server.nbi_plugins.ietf_network import register_ietf_network from .rest_server.nbi_plugins.ietf_network_slice import register_ietf_nss from .rest_server.nbi_plugins.tfs_api import register_tfs_api from .rest_server.nbi_plugins.ietf_hardware import register_ietf_hardware terminate = threading.Event() LOGGER = None Loading
src/nbi/service/rest_server/nbi_plugins/ietf_hardware/Hardware.py +1 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ class Hardware(Resource): if device is None: raise Exception('Device({:s}) not found in database'.format(str(device_uuid))) yang_handler = YangHandler('ietf-hardware') yang_handler = YangHandler() hardware_reply = yang_handler.compose(device) yang_handler.destroy() Loading
src/nbi/service/rest_server/nbi_plugins/ietf_hardware/YangHandler.py +46 −10 Original line number Diff line number Diff line Loading @@ -2,17 +2,27 @@ import libyang, os from common.proto.context_pb2 import Device from typing import Dict, Optional import logging import re import datetime LOGGER = logging.getLogger(__name__) YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang') MODULE_NAME = 'ietf-hardware' YANG_MODULES = [ 'iana-hardware', 'ietf-hardware' ] class YangHandler: def __init__(self) -> None: self._yang_context = libyang.Context(YANG_DIR) self._yang_module = self._yang_context.load_module(MODULE_NAME) self._yang_module.feature_enable_all() for yang_module_name in YANG_MODULES: LOGGER.info('Loading module: {:s}'.format(str(yang_module_name))) self._yang_context.load_module(yang_module_name).feature_enable_all() def parse_to_dict(self, message : Dict) -> Dict: dnode : Optional[libyang.DNode] = self._yang_module.parse_data_dict( yang_module = self._yang_context.get_module('ietf-hardware') dnode : Optional[libyang.DNode] = yang_module.parse_data_dict( message, validate_present=True, validate=True, strict=True ) if dnode is None: raise Exception('Unable to parse Message({:s})'.format(str(message))) Loading @@ -20,11 +30,31 @@ class YangHandler: dnode.free() return message @staticmethod def convert_to_iso_date(date_str: str) -> Optional[str]: date_str = date_str.strip('"') # Define the regex pattern for ISO 8601 date format pattern = r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[\+\-]\d{2}:\d{2})" # Check if the input date string matches the pattern if re.match(pattern, date_str): return date_str # Already in ISO format else: try: # Parse the input date string as a datetime object datetime_obj = datetime.datetime.strptime(date_str, "%Y-%m-%d") # Convert to ISO format iso_date = datetime_obj.isoformat() + "Z" return iso_date except ValueError: return None # Invalid date format def compose(self, device : Device) -> Dict: # compose device iterating through the components hardware = self._yang_context.create_data_path('/ietf-hardware:hardware') physical_index = 0 physical_index = 1 for component in device.components: attributes = component.attributes Loading @@ -39,29 +69,35 @@ class YangHandler: if component_type == "FRU" : component_type = "slack" component_new.create_path('isfru', True) component_new.create_path('is-fru', True) else : component_new.create_path('isfru', False) component_new.create_path('is-fru', False) component_type = component_type.replace("_", "-").lower() component_type = 'iana-hardware:' + component_type component_new.create_path('class', component_type) #Añadir resto de atributos en IETF physical_index += physical_index physical_index += 1 component_new.create_path('physical-index', physical_index) component_new.create_path('description', attributes["description"]) component_new.create_path('parent', component.parent) if attributes["mfg-date"] != "": mfg_date = self.convert_to_iso_date(attributes["mfg-date"]) LOGGER.info('component[name="{:s}"]'.format(attributes["mfg-date"])) component_new.create_path('mfg-date', mfg_date) component_new.create_path('hardware-rev', attributes["hardware-rev"]) component_new.create_path('software-rev', attributes["software-rev"]) component_new.create_path('firmware-rev', attributes["firmware-version"]) component_new.create_path('serial-num', attributes["serial-num"]) component_new.create_path('mfg-name', attributes["mfg-name"]) component_new.create_path('mfg-date', attributes["mfg-date"]) if attributes["id"]: component_new.create_path('parent-rel-pos', attributes["id"]) component_new.create_path('uri', component.name) Loading
src/nbi/service/rest_server/nbi_plugins/ietf_hardware/__init__.py +1 −1 Original line number Diff line number Diff line from nbi.service.rest_server.nbi_plugins.ietf_hardware.Hardware import Hardware from nbi.service.rest_server.RestServer import RestServer URL_PREFIX = "/restconf/data/device=<device_uuid>/ietf-hardware:hardware" URL_PREFIX = "/restconf/data/device=<path:device_uuid>/ietf-hardware:hardware" def register_ietf_hardware(rest_server: RestServer): rest_server.add_resource(Hardware, URL_PREFIX) No newline at end of file
src/nbi/service/rest_server/nbi_plugins/tfs_api/__init__.py +3 −3 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ from nbi.service.rest_server.RestServer import RestServer from .Resources import ( Connection, ConnectionIds, Connections, Context, ContextIds, Contexts, Device, DeviceIds, Deviceshw, Device, DeviceIds, Devices, Deviceshw, DummyContexts, Link, LinkIds, Links, PolicyRule, PolicyRuleIds, PolicyRules, Loading Loading @@ -46,11 +46,11 @@ RESOURCES = [ ('api.slice_ids', SliceIds, '/context/<path:context_uuid>/slice_ids'), ('api.slices', Slices, '/context/<path:context_uuid>/slices'), ('api.slice', Slice, '/context/<path:context_uuid>/slice/<path:slice_uuid>'), ''' ('api.device_ids', DeviceIds, '/device_ids'), ('api.devices', Devices, '/devices'), ('api.device', Device, '/device/<path:device_uuid>'), ''' ('api.deviceshw', Deviceshw, '/device/<path:device_uuid>/hardware'), ('api.link_ids', LinkIds, '/link_ids'), Loading