From 72bbd345c11c057b2da0abfe09514639bcdecd10 Mon Sep 17 00:00:00 2001 From: ismaeel <mohammad.ismaael@cnit.it> Date: Mon, 15 Apr 2024 06:05:03 +0000 Subject: [PATCH] Roadm endpoints auto discovery --- src/context/service/database/OpticalConfig.py | 6 +- .../database/models/OpticalConfigModel.py | 4 +- .../service/drivers/oc_driver/OCDriver.py | 48 ++++++----- .../drivers/oc_driver/templates/Tools.py | 84 ++++++++++++++----- 4 files changed, 99 insertions(+), 43 deletions(-) diff --git a/src/context/service/database/OpticalConfig.py b/src/context/service/database/OpticalConfig.py index 8251af887..3884e5f57 100644 --- a/src/context/service/database/OpticalConfig.py +++ b/src/context/service/database/OpticalConfig.py @@ -72,9 +72,9 @@ def set_opticalconfig(db_engine : Engine, request : OpticalConfig): { "opticalconfig_uuid": request.opticalconfig_id.opticalconfig_uuid, "transcievers" : transceivers, - "interfaces" : json.dumps(config["interfaces"]["interface"]), - "channel_namespace" : config["channel_namespace"], - "endpoints" : [json.dumps(endpoint) for endpoint in config["endpoints"]],} + "interfaces" :"", + "channel_namespace" : config.get("channel_namespace",None), + "endpoints" : [json.dumps(endpoint) for endpoint in config.get("endpoints",[])],} ) diff --git a/src/context/service/database/models/OpticalConfigModel.py b/src/context/service/database/models/OpticalConfigModel.py index 9937f342d..a2007886c 100644 --- a/src/context/service/database/models/OpticalConfigModel.py +++ b/src/context/service/database/models/OpticalConfigModel.py @@ -38,9 +38,9 @@ class OpticalConfigModel(_Base): return { "channels" : [channel.dump() for channel in self.channels], "transceivers" : {"transceiver": [transciever for transciever in self.transcievers]}, - "interfaces" : {"interface": json.loads(self.interfaces)}, + "interfaces" : {"interface":json.loads(self.interfaces) if self.interfaces else ''}, "channel_namespace" : self.channel_namespace, - "endpoints" : [json.loads(endpoint) for endpoint in self.endpoints], + "endpoints" : [json.loads(endpoint) for endpoint in self.endpoints if endpoint], } diff --git a/src/device/service/drivers/oc_driver/OCDriver.py b/src/device/service/drivers/oc_driver/OCDriver.py index 1e9ea74c9..3f91df18c 100644 --- a/src/device/service/drivers/oc_driver/OCDriver.py +++ b/src/device/service/drivers/oc_driver/OCDriver.py @@ -38,7 +38,7 @@ from common.proto.context_pb2 import ( OpticalConfig, ConfigActionEnum, Device, DeviceDriverEnum, DeviceId, DeviceList, DeviceOperationalStatusEnum, Empty ,OpticalConfigId,Uuid) -from .templates.Tools import extractor +from .templates.Tools import roadm_values_extractor, transponder_values_extractor from .Tools import generate_uuid_from_numbers DEBUG_MODE = False logging.getLogger('ncclient.manager').setLevel(logging.DEBUG if DEBUG_MODE else logging.WARNING) @@ -83,6 +83,7 @@ class NetconfSessionHandler: self.__manager_params = settings.get('manager_params', {}) self.__nc_params = settings.get('nc_params', {}) self.__message_renderer = settings.get('message_renderer','jinja') + self.__manager : Manager = None self.__candidate_supported = False @@ -198,6 +199,7 @@ class OCDriver(_Driver): super().__init__(DRIVER_NAME, address, port, **settings) self.__logger = logging.getLogger('{:s}:[{:s}:{:s}]'.format(str(__name__), str(self.address), str(self.port))) self.__lock = threading.Lock() + #self.__initial = TreeNode('.') #self.__running = TreeNode('.') self.__subscriptions = TreeNode('.') @@ -212,13 +214,12 @@ class OCDriver(_Driver): self._temp_address=f"{address}{port}" self.__out_samples = queue.Queue() self.__netconf_handler = NetconfSessionHandler(self.address, self.port, **(self.settings)) - + self.__type = self.settings.get("type","optical-transponder") self.__device_uuid=device_uuid self.Connect() - #self.GetConfig() - #self.__samples_cache = SamplesCache(self.__netconf_handler, self.__logger) - + logging.info(f"settings {settings}") + def Connect(self) -> bool: with self.__lock: if self.__started.is_set(): return True @@ -251,21 +252,35 @@ class OCDriver(_Driver): chk_type('resources', resource_keys, list) results = [] opticalConfig= OpticalConfig() - j=0 + with self.__lock: context_client.connect() config={} - channels_lst=[] + transceivers={} + oc_values={} + ports_result=[] try: xml_data = self.__netconf_handler.get().data_xml - transceivers,interfaces,channels_lst,channel_namespace,endpoints,ports_result=extractor(data_xml=xml_data,resource_keys=filter_fields,dic=config) - - logging.info(f"xml response {xml_data}") + + if (self.__type == "optical-transponder"): + extracted_values=transponder_values_extractor(data_xml=xml_data,resource_keys=filter_fields,dic=config) + transceivers,optical_channels_params,channel_namespace,endpoints,ports_result=extracted_values + oc_values["channels"]=optical_channels_params + oc_values["transceivers"]=transceivers + oc_values["channel_namespace"]=channel_namespace + oc_values["endpoints"]=endpoints + oc_values["ports"]=ports_result + else : + extracted_values=roadm_values_extractor(data_xml=xml_data,resource_keys=filter_fields,dic=config) + ports_result = extracted_values[0] + + + except Exception as e: # pylint: disable=broad-except MSG = 'Exception retrieving {:s}' @@ -276,15 +291,10 @@ class OCDriver(_Driver): #///////////////////////// store optical configurtaion //////////////////////////////////////////////////////// - value_dic={} - value_dic["channels"]=channels_lst - value_dic["transceivers"]=transceivers - value_dic["interfaces"]=interfaces - value_dic["channel_namespace"]=channel_namespace - value_dic["endpoints"]=endpoints - value_dic["ports"]=ports_result - logging.info(f"parameters {value_dic}") - opticalConfig.config=json.dumps(value_dic) + + + logging.info(f"parameters {oc_values}") + opticalConfig.config=json.dumps(oc_values) opticalConfig.opticalconfig_id.opticalconfig_uuid=self.__device_uuid if self.__device_uuid is not None else "" config_id=context_client.SetOpticalConfig(opticalConfig) diff --git a/src/device/service/drivers/oc_driver/templates/Tools.py b/src/device/service/drivers/oc_driver/templates/Tools.py index a088d4a1f..704cb76a4 100644 --- a/src/device/service/drivers/oc_driver/templates/Tools.py +++ b/src/device/service/drivers/oc_driver/templates/Tools.py @@ -238,40 +238,33 @@ def has_opticalbands(xml_data:str): return has_opticalbands def extract_ports_based_on_type (xml_data:str): - pattern = r'\bPORT\b' + pattern = r':\s*PORT\b' xml_bytes = xml_data.encode("utf-8") root = ET.fromstring(xml_bytes) - namespace = {'oc': 'http://openconfig.net/yang/platform', 'typex': 'http://openconfig.net/yang/platform-types'} ports = [] - components = root.findall('.//oc:type',namespace) - - + components = root.findall(".//oc:state[oc:type]",namespace) for component in components: - - - if component is not None and re.search(pattern,component.text): - - - name_element = component.getprevious() + type_ele = component.find(".//oc:type",namespace) + match = re.search(pattern, type_ele.text) + if match is not None : + name_element= component.find(".//oc:name",namespace) port_name =name_element.text port_index=name_element.text.split("-")[1] port = (port_name,port_index) ports.append(port) return ports -def extractor(data_xml:str,resource_keys:list,dic:dict): +def transponder_values_extractor(data_xml:str,resource_keys:list,dic:dict): endpoints=[] is_opticalband=has_opticalbands(xml_data=data_xml) - channel_namespace=extract_channel_xmlns(data_xml=data_xml,is_opticalband=is_opticalband) # channel_names=extract_channels_based_on_type(xml_data=data_xml) # if len(channel_names)==0 : channel_names= extract_channels_based_on_channelnamespace(xml_data=data_xml,channel_namespace=channel_namespace,is_opticalband=is_opticalband) ports = extract_ports_based_on_type(data_xml) - - lst_dic=[] + optical_channels_params=[] ports_result=[] if (is_opticalband): endpoints=channel_names @@ -282,13 +275,15 @@ def extractor(data_xml:str,resource_keys:list,dic:dict): for resource_key in resource_keys : if (resource_key != 'interface'): - dic=extract_value(dic=dic,resource_key=resource_key,xml_data=data_xml,channel_name=channel_name,channel_namespace=channel_namespace) + + dic=extract_value(dic=dic,resource_key=resource_key,xml_data=data_xml + ,channel_name=channel_name,channel_namespace=channel_namespace) dic["name"]=channel_name endpoints.append({"endpoint_uuid":{"uuid":channel_name}}) - lst_dic.append(dic) + optical_channels_params.append(dic) transceivers_dic=extract_tranceiver(data_xml=data_xml,dic={}) - interfaces_dic=extract_interface(xml_data=data_xml,dic={}) + #interfaces_dic=extract_interface(xml_data=data_xml,dic={}) if len(ports)>0 : for port in ports : endpoint_name,endpoint_id=port @@ -297,4 +292,55 @@ def extractor(data_xml:str,resource_keys:list,dic:dict): ports_result.append((resource_key, resource_value)) - return [transceivers_dic,interfaces_dic,lst_dic,channel_namespace,endpoints,ports_result] \ No newline at end of file + return [transceivers_dic,optical_channels_params,channel_namespace,endpoints,ports_result] + +######################################################################### + +#################################### ROADMAs ############################ + +########################################################################## + +def extract_roadm_ports (xml_data:str): + + ports =[] + pattern = r'\bMG_ON_OPTICAL_PORT_WAVEBAND\b' + xml_bytes = xml_data.encode("utf-8") + root = ET.fromstring(xml_bytes) + with open('xml.log', 'w') as f: + print(xml_bytes, file=f) + + + namespace = {'oc': 'http://openconfig.net/yang/platform'} + ports = [] + components = root.findall('.//oc:component',namespace) + print(f"component {components}") + + + for component in components: + + properties = component.find(".//oc:properties",namespace) + + if (properties is not None): + for property in properties : + value = property.find(".//oc:value",namespace) + + if (re.search(pattern,value.text)): + name_element= component.find(".//oc:name",namespace) + ports.append(name_element.text) + return ports + + + + +def roadm_values_extractor (data_xml:str,resource_keys:list,dic:dict): + ports_result=[] + ports = extract_roadm_ports(data_xml) + + if len(ports)>0 : + for port in ports : + + resource_key = '/endpoints/endpoint[{:s}]'.format(port) + resource_value = {'uuid': port, 'type':'MG_ON_OPTICAL_PORT_WAVEBAND'} + ports_result.append((resource_key, resource_value)) + + return [ports_result] \ No newline at end of file -- GitLab