diff --git a/common_requirements.in b/common_requirements.in
index 12c6c778d107ebf27ad53a25b2da60ad2f65286e..38812dbf0d927293bd1c7996b685f4ec060c5438 100644
--- a/common_requirements.in
+++ b/common_requirements.in
@@ -25,3 +25,4 @@ pytest==6.2.5
pytest-benchmark==3.4.1
python-dateutil==2.8.2
pytest-depends==1.0.1
+PyYAML>=6.0
diff --git a/src/device/Dockerfile b/src/device/Dockerfile
index d8541912838a4e7c19923a6ad10c67d909a4a622..7ab74c2b4ceff3acfc479b96e7a834e4ce2a8037 100644
--- a/src/device/Dockerfile
+++ b/src/device/Dockerfile
@@ -55,6 +55,10 @@ RUN pip-compile --quiet --output-file=common_requirements.txt common_requirement
RUN python3 -m pip install -r common_requirements.txt
# Add common files into working directory
+WORKDIR /var/teraflow/inter_device_translation
+COPY src/inter_device_translation/. ./
+
+# Add device translation files into working directory
WORKDIR /var/teraflow/common
COPY src/common/. ./
RUN rm -rf proto
diff --git a/src/device/service/drivers/gnmi_openconfig/GnmiSessionHandler.py b/src/device/service/drivers/gnmi_openconfig/GnmiSessionHandler.py
index 6eb9271ab436c5ee85dae39795b346406916eee4..9ab3ff53af849e840de31bd8c9b15fec67e902d6 100644
--- a/src/device/service/drivers/gnmi_openconfig/GnmiSessionHandler.py
+++ b/src/device/service/drivers/gnmi_openconfig/GnmiSessionHandler.py
@@ -38,6 +38,7 @@ class GnmiSessionHandler:
self._username = settings.get('username')
self._password = settings.get('password')
self._use_tls = settings.get('use_tls', False)
+ self._vendor = settings.get('vendor')
self._channel : Optional[grpc.Channel] = None
self._stub : Optional[gNMIStub] = None
self._monit_thread = None
@@ -63,6 +64,10 @@ class GnmiSessionHandler:
@property
def out_samples(self): return self._out_samples
+
+ @property
+ def device_type(self):
+ return self._vendor.lower() if self._vendor else 'oc'
def connect(self):
with self._lock:
@@ -97,7 +102,7 @@ class GnmiSessionHandler:
try:
chk_string(str_resource_name, resource_key, allow_empty=False)
self._logger.debug('[GnmiSessionHandler:get] resource_key = {:s}'.format(str(resource_key)))
- str_path = get_path(resource_key)
+ str_path = get_path(resource_key, self.device_type)
self._logger.debug('[GnmiSessionHandler:get] str_path = {:s}'.format(str(str_path)))
get_request.path.append(path_from_string(str_path))
except Exception as e: # pylint: disable=broad-except
@@ -141,7 +146,7 @@ class GnmiSessionHandler:
value = decode_value(update.val)
#resource_key_tuple[1] = value
#resource_key_tuple[2] = True
- results.extend(parse(str_path, value, self._yang_handler))
+ results.extend(parse(str_path, value, self._yang_handler, self.device_type))
except Exception as e: # pylint: disable=broad-except
MSG = 'Exception processing update {:s}'
self._logger.exception(MSG.format(grpc_message_to_json_string(update)))
@@ -178,7 +183,7 @@ class GnmiSessionHandler:
#if resource_tuple is None: continue
#_, value, exists, operation_done = resource_tuple
if isinstance(resource_value, str): resource_value = json.loads(resource_value)
- str_path, str_data = compose(resource_key, resource_value, self._yang_handler, delete=False)
+ str_path, str_data = compose(resource_key, resource_value, self._yang_handler, delete=False, device_type=self.device_type)
if str_path is None: continue # nothing to set
#self._logger.info('---3')
#self._logger.info(str(str_path))
@@ -252,7 +257,7 @@ class GnmiSessionHandler:
#if not exists: continue
if isinstance(resource_value, str): resource_value = json.loads(resource_value)
# pylint: disable=unused-variable
- str_path, str_data = compose(resource_key, resource_value, self._yang_handler, delete=True)
+ str_path, str_data = compose(resource_key, resource_value, self._yang_handler, delete=True, device_type=self.device_type)
if str_path is None: continue # nothing to do with this resource_key
#self._logger.info('---3')
#self._logger.info(str(str_path))
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/Acl.py b/src/device/service/drivers/gnmi_openconfig/handlers/Acl.py
index c3c52fa857aa569361083439546b5118b8457c3f..33c93ed79d8f90cc9a28d1c25d858415d0db1470 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/Acl.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/Acl.py
@@ -18,6 +18,7 @@ from typing import Any, Dict, List, Tuple
import libyang
+from inter_device_translation import get_dict_helper
from ._Handler import _Handler
from .YangHandler import YangHandler
@@ -43,11 +44,14 @@ _OC_TFS_FWD_ACTION = {v: k for k, v in _TFS_OC_FWD_ACTION.items()}
class AclHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type or 'oc')
+
def get_resource_key(self) -> str:
return '/device/endpoint/acl_ruleset'
def get_path(self) -> str:
- return '/openconfig-acl:acl'
+ return self._dict_helper.get_path('acl')
def compose( # pylint: disable=too-many-locals
self,
@@ -66,7 +70,7 @@ class AclHandler(_Handler):
path = f'/acl/acl-sets/acl-set[name={rs_name}][type={oc_type}]'
return path, ''
- yang_acl: libyang.DContainer = yang.get_data_path('/openconfig-acl:acl')
+ yang_acl: libyang.DContainer = yang.get_data_path(self._dict_helper.get_path('acl'))
y_sets = yang_acl.create_path('acl-sets')
y_set = y_sets.create_path(f'acl-set[name="{rs_name}"][type="{oc_type}"]')
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/Component.py b/src/device/service/drivers/gnmi_openconfig/handlers/Component.py
index fab4722330a398330d1025bcf85fe0d975812960..581ea0adfae6b77d31a95c8c8441fee57099fcc8 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/Component.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/Component.py
@@ -17,15 +17,19 @@ from typing import Any, Dict, List, Tuple
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from ._Handler import _Handler
from .YangHandler import YangHandler
+from inter_device_translation import get_dict_helper
LOGGER = logging.getLogger(__name__)
-PATH_IF_CTR = '/openconfig-interfaces:interfaces/interface[name={:s}]/state/counters/{:s}'
+# Path will be constructed dynamically using device translation
#pylint: disable=abstract-method
class ComponentHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type or 'oc')
+
def get_resource_key(self) -> str: return '/endpoints/endpoint'
- def get_path(self) -> str: return '/openconfig-platform:components'
+ def get_path(self) -> str: return self._dict_helper.get_path('components')
def parse(
self, json_data : Dict, yang_handler : YangHandler
@@ -36,7 +40,8 @@ class ComponentHandler(_Handler):
json_data_valid = yang_handler.parse_to_dict(yang_components_path, json_data, fmt='json')
entries = []
- for component in json_data_valid['components']['component']:
+
+ for component in json_data_valid[self._dict_helper.get_object('components', plural=True)][self._dict_helper.get_object('components')]:
LOGGER.debug('component={:s}'.format(str(component)))
component_name = component['name']
@@ -59,12 +64,13 @@ class ComponentHandler(_Handler):
endpoint = {'uuid': interface_name, 'type': '-'}
endpoint['sample_types'] = {
- KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED : PATH_IF_CTR.format(interface_name, 'in-octets' ),
- KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED : PATH_IF_CTR.format(interface_name, 'out-octets'),
- KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED : PATH_IF_CTR.format(interface_name, 'in-pkts' ),
- KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED: PATH_IF_CTR.format(interface_name, 'out-pkts' ),
+ KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED : self._dict_helper.get_path('interface_counters', name=interface_name, counter='in-octets'),
+ KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED : self._dict_helper.get_path('interface_counters', name=interface_name, counter='out-octets'),
+ KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED : self._dict_helper.get_path('interface_counters', name=interface_name, counter='in-pkts'),
+ KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED: self._dict_helper.get_path('interface_counters', name=interface_name, counter='out-pkts'),
}
- entries.append(('/endpoints/endpoint[{:s}]'.format(endpoint['uuid']), endpoint))
+ resource_key = self._dict_helper.get_resource_key('endpoints_endpoint', uuid=endpoint['uuid'])
+ entries.append((resource_key, endpoint))
return entries
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py
index d59bff7a61cd1ef468f8220456bf7434b16bb0b6..4619c5a6d41b719d9e613359a86e440d1cec789a 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/Interface.py
@@ -17,12 +17,17 @@ from typing import Any, Dict, List, Tuple
from ._Handler import _Handler
from .Tools import get_bool, get_int, get_str
from .YangHandler import YangHandler
+from inter_device_translation import get_dict_helper
LOGGER = logging.getLogger(__name__)
class InterfaceHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type or 'oc')
+
def get_resource_key(self) -> str: return '/interface/subinterface'
- def get_path(self) -> str: return '/openconfig-interfaces:interfaces'
+ def get_path(self) -> str:
+ return self._dict_helper.get_path('interfaces')
def compose(
self, resource_key : str, resource_value : Dict, yang_handler : YangHandler, delete : bool = False
@@ -31,8 +36,7 @@ class InterfaceHandler(_Handler):
sif_index = get_int(resource_value, 'index', 0) # 0
if delete:
- PATH_TMPL = '/interfaces/interface[name={:s}]/subinterfaces/subinterface[index={:d}]'
- str_path = PATH_TMPL.format(if_name, sif_index)
+ str_path = self._dict_helper.get_path('interface_subinterface', name=if_name, index=sif_index)
str_data = json.dumps({})
root_node : libyang.DContainer = yang_handler.get_data_path(
@@ -58,7 +62,7 @@ class InterfaceHandler(_Handler):
address_prefix = get_int (resource_value, 'address_prefix') # 24
mtu = get_int (resource_value, 'mtu' ) # 1500
- yang_ifs : libyang.DContainer = yang_handler.get_data_path('/openconfig-interfaces:interfaces')
+ yang_ifs : libyang.DContainer = yang_handler.get_data_path(self._dict_helper.get_path('interfaces'))
yang_if_path = 'interface[name="{:s}"]'.format(if_name)
yang_if : libyang.DContainer = yang_ifs.create_path(yang_if_path)
yang_if.create_path('config/name', if_name )
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/InterfaceCounter.py b/src/device/service/drivers/gnmi_openconfig/handlers/InterfaceCounter.py
index f9aa55f4855274f4676c7238daa1c64394b238f8..19f79c26e867351ae5ce4e269013b1b469dfce35 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/InterfaceCounter.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/InterfaceCounter.py
@@ -16,13 +16,18 @@ import json, libyang, logging
from typing import Any, Dict, List, Tuple
from ._Handler import _Handler
from .YangHandler import YangHandler
+from inter_device_translation import get_dict_helper
LOGGER = logging.getLogger(__name__)
#pylint: disable=abstract-method
class InterfaceCounterHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type or 'oc')
+
def get_resource_key(self) -> str: return '/interface/counters'
- def get_path(self) -> str: return '/openconfig-interfaces:interfaces/interface/state/counters'
+ def get_path(self) -> str:
+ return self._dict_helper.get_path('interface_counters_path')
def parse(
self, json_data : Dict, yang_handler : YangHandler
@@ -58,7 +63,7 @@ class InterfaceCounterHandler(_Handler):
}
LOGGER.debug('interface = {:s}'.format(str(interface)))
- entry_interface_key = '/interface[{:s}]'.format(interface_name)
+ entry_interface_key = self._dict_helper.get_resource_key('interface', name=interface_name)
entries.append((entry_interface_key, _interface))
return entries
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py
index 2c4be4e8a8efe5052bb64aac264bc5716a3aeae8..811a52e0bcaae171f21f0b2b4804c171c6bf4cbb 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py
@@ -17,6 +17,7 @@ from typing import Any, Dict, List, Tuple
from ._Handler import _Handler
from .Tools import get_str
from .YangHandler import YangHandler
+from inter_device_translation import get_dict_helper
LOGGER = logging.getLogger(__name__)
@@ -38,8 +39,12 @@ MAP_NETWORK_INSTANCE_TYPE = {
}
class NetworkInstanceHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type)
+
def get_resource_key(self) -> str: return '/network_instance'
- def get_path(self) -> str: return '/openconfig-network-instance:network-instances'
+ def get_path(self) -> str:
+ return self._dict_helper.get_path('network_instances')
def compose(
self, resource_key : str, resource_value : Dict, yang_handler : YangHandler, delete : bool = False
@@ -47,21 +52,20 @@ class NetworkInstanceHandler(_Handler):
ni_name = get_str(resource_value, 'name') # test-svc
if delete:
- PATH_TMPL = '/network-instances/network-instance[name={:s}]'
- str_path = PATH_TMPL.format(ni_name)
+ str_path = self._dict_helper.get_path('network_instance', name=ni_name)
str_data = json.dumps({})
return str_path, str_data
ni_type = get_str(resource_value, 'type') # L3VRF / L2VSI / ...
ni_type = MAP_NETWORK_INSTANCE_TYPE.get(ni_type, ni_type)
- str_path = '/network-instances/network-instance[name={:s}]'.format(ni_name)
+ str_path = self._dict_helper.get_path('network_instance', name=ni_name)
#str_data = json.dumps({
# 'name': ni_name,
# 'config': {'name': ni_name, 'type': ni_type},
#})
- yang_nis : libyang.DContainer = yang_handler.get_data_path('/openconfig-network-instance:network-instances')
+ yang_nis : libyang.DContainer = yang_handler.get_data_path(self._dict_helper.get_path('network_instances'))
yang_ni_path = 'network-instance[name="{:s}"]'.format(ni_name)
yang_ni : libyang.DContainer = yang_nis.create_path(yang_ni_path)
yang_ni.create_path('config/name', ni_name)
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceInterface.py b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceInterface.py
index f24cb8662789067c236a86f6159b042b8d67443e..443068551c81f1adba88e3fb723622d98ccdbf78 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceInterface.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceInterface.py
@@ -17,14 +17,19 @@ from typing import Any, Dict, List, Tuple
from ._Handler import _Handler
from .Tools import get_int, get_str
from .YangHandler import YangHandler
+from inter_device_translation import get_dict_helper
LOGGER = logging.getLogger(__name__)
IS_CEOS = True
class NetworkInstanceInterfaceHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type or 'oc')
+
def get_resource_key(self) -> str: return '/network_instance/interface'
- def get_path(self) -> str: return '/openconfig-network-instance:network-instances/network-instance/interfaces'
+ def get_path(self) -> str:
+ return self._dict_helper.get_path('network_instance_interfaces')
def compose(
self, resource_key : str, resource_value : Dict, yang_handler : YangHandler, delete : bool = False
@@ -36,8 +41,7 @@ class NetworkInstanceInterfaceHandler(_Handler):
if IS_CEOS: ni_if_id = if_name
- PATH_TMPL = '/network-instances/network-instance[name={:s}]/interfaces/interface[id={:s}]'
- str_path = PATH_TMPL.format(ni_name, ni_if_id)
+ str_path = self._dict_helper.get_path('network_instance_interface', name=ni_name, interface_id=ni_if_id)
if delete:
str_data = json.dumps({})
@@ -48,7 +52,7 @@ class NetworkInstanceInterfaceHandler(_Handler):
# 'config': {'id': if_id, 'interface': if_name, 'subinterface': sif_index},
#})
- yang_nis : libyang.DContainer = yang_handler.get_data_path('/openconfig-network-instance:network-instances')
+ yang_nis : libyang.DContainer = yang_handler.get_data_path(self._dict_helper.get_path('network_instances'))
yang_ni : libyang.DContainer = yang_nis.create_path('network-instance[name="{:s}"]'.format(ni_name))
yang_ni_ifs : libyang.DContainer = yang_ni.create_path('interfaces')
yang_ni_if_path = 'interface[id="{:s}"]'.format(ni_if_id)
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceProtocol.py b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceProtocol.py
index f83597056f4ea3eee11a0a6c59adbb100ba697cd..f027a8b47cbe733f54cd2f7500c9f40aea4f7bff 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceProtocol.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceProtocol.py
@@ -17,13 +17,17 @@ from typing import Any, Dict, List, Tuple
from ._Handler import _Handler
from .Tools import get_str
from .YangHandler import YangHandler
+from inter_device_translation import get_dict_helper
LOGGER = logging.getLogger(__name__)
class NetworkInstanceProtocolHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type or 'oc')
+
def get_resource_key(self) -> str: return '/network_instance/protocols'
def get_path(self) -> str:
- return '/openconfig-network-instance:network-instances/network-instance/protocols/protocol'
+ return self._dict_helper.get_path('network_instance_protocols')
def compose(
self, resource_key : str, resource_value : Dict, yang_handler : YangHandler, delete : bool = False
@@ -34,8 +38,7 @@ class NetworkInstanceProtocolHandler(_Handler):
if ':' not in identifier:
identifier = 'openconfig-policy-types:{:s}'.format(identifier)
- PATH_TMPL = '/network-instances/network-instance[name={:s}]/protocols/protocol[identifier={:s}][name={:s}]'
- str_path = PATH_TMPL.format(ni_name, identifier, proto_name)
+ str_path = self._dict_helper.get_path('network_instance_protocol', name=ni_name, identifier=identifier, protocol_name=proto_name)
if delete:
str_data = json.dumps({})
@@ -56,7 +59,7 @@ class NetworkInstanceProtocolHandler(_Handler):
# }]}
#})
- yang_nis : libyang.DContainer = yang_handler.get_data_path('/openconfig-network-instance:network-instances')
+ yang_nis : libyang.DContainer = yang_handler.get_data_path(self._dict_helper.get_path('network_instances'))
yang_ni : libyang.DContainer = yang_nis.create_path('network-instance[name="{:s}"]'.format(ni_name))
yang_ni_prs : libyang.DContainer = yang_ni.create_path('protocols')
yang_ni_pr_path = 'protocol[identifier="{:s}"][name="{:s}"]'.format(identifier, proto_name)
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py
index 78d77c8cdeb9b47107941e55e013da6d99bdd769..93295cc46b8c3c3b88b8b91961e25b38ad5a8dd0 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py
@@ -21,9 +21,12 @@ from .YangHandler import YangHandler
LOGGER = logging.getLogger(__name__)
class NetworkInstanceStaticRouteHandler(_Handler):
+ def __init__(self, device_type=None):
+ self._dict_helper = get_dict_helper(device_type or 'oc')
+
def get_resource_key(self) -> str: return '/network_instance/protocols/static_route'
def get_path(self) -> str:
- return '/openconfig-network-instance:network-instances/network-instance/protocols/protocol/static-routes'
+ return self._dict_helper.get_path('network_instance_static_routes')
def compose(
self, resource_key : str, resource_value : Dict, yang_handler : YangHandler, delete : bool = False
@@ -37,9 +40,7 @@ class NetworkInstanceStaticRouteHandler(_Handler):
identifier = 'openconfig-policy-types:{:s}'.format(identifier)
if delete:
- PATH_TMPL = '/network-instances/network-instance[name={:s}]/protocols'
- PATH_TMPL += '/protocol[identifier={:s}][name={:s}]/static-routes/static[prefix={:s}]'
- str_path = PATH_TMPL.format(ni_name, identifier, proto_name, prefix)
+ str_path = self._dict_helper.get_path('network_instance_static_route', name=ni_name, identifier=identifier, protocol_name=proto_name, prefix=prefix)
str_data = json.dumps({})
return str_path, str_data
@@ -49,8 +50,7 @@ class NetworkInstanceStaticRouteHandler(_Handler):
if index is None:
index = 'AUTO_{:d}_{:s}'.format(metric, next_hop)
- PATH_TMPL = '/network-instances/network-instance[name={:s}]/protocols/protocol[identifier={:s}][name={:s}]'
- str_path = PATH_TMPL.format(ni_name, identifier, proto_name)
+ str_path = self._dict_helper.get_path('network_instance_protocol', name=ni_name, identifier=identifier, protocol_name=proto_name)
#str_data = json.dumps({
# 'identifier': identifier, 'name': name,
# 'config': {'identifier': identifier, 'name': name, 'enabled': True},
@@ -66,7 +66,7 @@ class NetworkInstanceStaticRouteHandler(_Handler):
# }]}
#})
- yang_nis : libyang.DContainer = yang_handler.get_data_path('/openconfig-network-instance:network-instances')
+ yang_nis : libyang.DContainer = yang_handler.get_data_path(self._dict_helper.get_path('network_instances'))
yang_ni : libyang.DContainer = yang_nis.create_path('network-instance[name="{:s}"]'.format(ni_name))
yang_ni_prs : libyang.DContainer = yang_ni.create_path('protocols')
yang_ni_pr_path = 'protocol[identifier="{:s}"][name="{:s}"]'.format(identifier, proto_name)
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/__init__.py b/src/device/service/drivers/gnmi_openconfig/handlers/__init__.py
index 3ce655353ecf78360931a008f7c69bb732749ea0..23b7fe5ec5e89e05c9808b90cabaf01764fbb6f3 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/__init__.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/__init__.py
@@ -29,15 +29,6 @@ from .YangHandler import YangHandler
LOGGER = logging.getLogger(__name__)
-comph = ComponentHandler()
-ifaceh = InterfaceHandler()
-ifctrh = InterfaceCounterHandler()
-nih = NetworkInstanceHandler()
-niifh = NetworkInstanceInterfaceHandler()
-niph = NetworkInstanceProtocolHandler()
-nisrh = NetworkInstanceStaticRouteHandler()
-aclh = AclHandler()
-
ALL_RESOURCE_KEYS = [
RESOURCE_ENDPOINTS,
RESOURCE_INTERFACES,
@@ -45,47 +36,65 @@ ALL_RESOURCE_KEYS = [
RESOURCE_ACL,
]
-RESOURCE_KEY_MAPPER = {
- RESOURCE_ENDPOINTS : comph.get_resource_key(),
- RESOURCE_INTERFACES : ifaceh.get_resource_key(),
- RESOURCE_NETWORK_INSTANCES : nih.get_resource_key(),
- RESOURCE_ACL : aclh.get_resource_key(),
-}
+RESOURCE_KEY_MAPPER = {}
+PATH_MAPPER = {}
+RESOURCE_KEY_TO_HANDLER = {}
+PATH_TO_HANDLER = {}
+
+def _load_device_specific_mappings(device_type):
+ global RESOURCE_KEY_MAPPER, PATH_MAPPER, RESOURCE_KEY_TO_HANDLER, PATH_TO_HANDLER
+
+ comph = ComponentHandler(device_type)
+ ifaceh = InterfaceHandler(device_type)
+ ifctrh = InterfaceCounterHandler(device_type)
+ nih = NetworkInstanceHandler(device_type)
+ niifh = NetworkInstanceInterfaceHandler(device_type)
+ niph = NetworkInstanceProtocolHandler(device_type)
+ nisrh = NetworkInstanceStaticRouteHandler(device_type)
+ aclh = AclHandler(device_type)
+
+ RESOURCE_KEY_MAPPER = {
+ RESOURCE_ENDPOINTS : comph.get_resource_key(),
+ RESOURCE_INTERFACES : ifaceh.get_resource_key(),
+ RESOURCE_NETWORK_INSTANCES : nih.get_resource_key(),
+ RESOURCE_ACL : aclh.get_resource_key(),
+ }
-PATH_MAPPER = {
- '/components' : comph.get_path(),
- '/components/component' : comph.get_path(),
- '/interfaces' : ifaceh.get_path(),
- '/network-instances' : nih.get_path(),
- '/acl' : aclh.get_path(),
-}
+ PATH_MAPPER = {
+ '/components' : comph.get_path(),
+ '/components/component' : comph.get_path(),
+ '/interfaces' : ifaceh.get_path(),
+ '/network-instances' : nih.get_path(),
+ '/acl' : aclh.get_path(),
+ }
-RESOURCE_KEY_TO_HANDLER = {
- comph.get_resource_key() : comph,
- ifaceh.get_resource_key() : ifaceh,
- ifctrh.get_resource_key() : ifctrh,
- nih.get_resource_key() : nih,
- niifh.get_resource_key() : niifh,
- niph.get_resource_key() : niph,
- nisrh.get_resource_key() : nisrh,
- aclh.get_resource_key() : aclh,
-}
+ RESOURCE_KEY_TO_HANDLER = {
+ comph.get_resource_key() : comph,
+ ifaceh.get_resource_key() : ifaceh,
+ ifctrh.get_resource_key() : ifctrh,
+ nih.get_resource_key() : nih,
+ niifh.get_resource_key() : niifh,
+ niph.get_resource_key() : niph,
+ nisrh.get_resource_key() : nisrh,
+ aclh.get_resource_key() : aclh,
+ }
-PATH_TO_HANDLER = {
- comph.get_path() : comph,
- ifaceh.get_path() : ifaceh,
- ifctrh.get_path() : ifctrh,
- nih.get_path() : nih,
- niifh.get_path() : niifh,
- niph.get_path() : niph,
- nisrh.get_path() : nisrh,
- aclh.get_path() : aclh,
-}
+ PATH_TO_HANDLER = {
+ comph.get_path() : comph,
+ ifaceh.get_path() : ifaceh,
+ ifctrh.get_path() : ifctrh,
+ nih.get_path() : nih,
+ niifh.get_path() : niifh,
+ niph.get_path() : niph,
+ nisrh.get_path() : nisrh,
+ aclh.get_path() : aclh,
+ }
def get_handler(
resource_key : Optional[str] = None, path : Optional[str] = None,
- raise_if_not_found=True
+ raise_if_not_found=True, device_type: str = None
) -> Optional[_Handler]:
+ _load_device_specific_mappings(device_type)
if (resource_key is None) == (path is None):
MSG = 'Exactly one of resource_key({:s}) or path({:s}) must be specified'
raise Exception(MSG.format(str(resource_key), str(path))) # pylint: disable=broad-exception-raised
@@ -107,19 +116,19 @@ def get_handler(
raise Exception(MSG.format(str(path), str(path_schema)))
return handler
-def get_path(resource_key : str) -> str:
- handler = get_handler(resource_key=resource_key)
+def get_path(resource_key : str, device_type: str = None) -> str:
+ handler = get_handler(resource_key=resource_key, device_type=device_type)
return handler.get_path()
def parse(
- str_path : str, value : Union[Dict, List], yang_handler : YangHandler
+ str_path : str, value : Union[Dict, List], yang_handler : YangHandler, device_type: str = None
) -> List[Tuple[str, Dict[str, Any]]]:
- handler = get_handler(path=str_path)
+ handler = get_handler(path=str_path, device_type=device_type)
return handler.parse(value, yang_handler)
def compose(
resource_key : str, resource_value : Union[Dict, List],
- yang_handler : YangHandler, delete : bool = False
+ yang_handler : YangHandler, delete : bool = False, device_type: str = None
) -> Tuple[str, str]:
- handler = get_handler(resource_key=resource_key)
+ handler = get_handler(resource_key=resource_key, device_type=device_type)
return handler.compose(resource_key, resource_value, yang_handler, delete=delete)
diff --git a/src/device/service/drivers/openconfig/OpenConfigDriver.py b/src/device/service/drivers/openconfig/OpenConfigDriver.py
index 4bf7be22c1d474a4ddf91d23f96f412d631057b2..0d079302f823b8374facfb9f0ca943be0820ea95 100644
--- a/src/device/service/drivers/openconfig/OpenConfigDriver.py
+++ b/src/device/service/drivers/openconfig/OpenConfigDriver.py
@@ -110,7 +110,7 @@ class NetconfSessionHandler:
@RETRY_DECORATOR
def get(self, filter=None, with_defaults=None): # pylint: disable=redefined-builtin
with self.__lock:
- if self.__vendor == 'JUNIPER'and not 'component' in str(filter):
+ if self.__vendor == 'JUNIPER' and not 'component' in str(filter):
return self.__manager.get_config(source="running", filter=filter, with_defaults=with_defaults)
else:
return self.__manager.get(filter=filter, with_defaults=with_defaults)
@@ -167,9 +167,9 @@ class SamplesCache:
try:
now = datetime.timestamp(datetime.utcnow())
if self.__timestamp is not None and (now - self.__timestamp) < SAMPLE_EVICTION_SECONDS: return
- str_filter = get_filter(SAMPLE_RESOURCE_KEY)
+ str_filter = get_filter(SAMPLE_RESOURCE_KEY, device_type=self.__netconf_handler.vendor)
xml_data = self.__netconf_handler.get(filter=str_filter).data_ele
- interface_samples = parse(SAMPLE_RESOURCE_KEY, xml_data)
+ interface_samples = parse(SAMPLE_RESOURCE_KEY, xml_data, device_type=self.__netconf_handler.vendor)
for interface,samples in interface_samples:
match = RE_GET_ENDPOINT_FROM_INTERFACE_KEY.match(interface)
if match is None: continue
@@ -228,7 +228,7 @@ def edit_config(
resource_key,resource_value = resource
chk_string(str_resource_name + '.key', resource_key, allow_empty=False)
str_config_messages = compose_config( # get template for configuration
- resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor, message_renderer=netconf_handler.message_renderer)
+ resource_key, resource_value, delete=delete, vendor=netconf_handler.vendor, message_renderer=netconf_handler.message_renderer, device_type=netconf_handler.vendor)
for str_config_message in str_config_messages: # configuration of the received templates
if str_config_message is None: raise UnsupportedResourceKeyException(resource_key)
logger.debug('[{:s}] str_config_message[{:d}] = {:s}'.format(
@@ -318,12 +318,12 @@ class OpenConfigDriver(_Driver):
str_resource_name = 'resource_key[#{:d}]'.format(i)
try:
chk_string(str_resource_name, resource_key, allow_empty=False)
- str_filter = get_filter(resource_key)
+ str_filter = get_filter(resource_key, device_type=self.__netconf_handler.vendor)
#self.__logger.debug('[GetConfig] str_filter = {:s}'.format(str(str_filter)))
if str_filter is None: str_filter = resource_key
xml_data = self.__netconf_handler.get(filter=str_filter).data_ele
if isinstance(xml_data, Exception): raise xml_data
- results.extend(parse(resource_key, xml_data))
+ results.extend(parse(resource_key, xml_data, device_type=self.__netconf_handler.vendor))
except Exception as e: # pylint: disable=broad-except
MSG = 'Exception retrieving {:s}: {:s}'
self.__logger.exception(MSG.format(str_resource_name, str(resource_key)))
diff --git a/src/device/service/drivers/openconfig/templates/Acl.py b/src/device/service/drivers/openconfig/templates/Acl.py
index 7845e8fcffcc7dd1a34369ea9675041295371a52..9ba37c1c6487c7af54074ce7421ae821ff528c97 100644
--- a/src/device/service/drivers/openconfig/templates/Acl.py
+++ b/src/device/service/drivers/openconfig/templates/Acl.py
@@ -16,110 +16,112 @@ import logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES
from .Tools import add_value_from_tag
+from inter_device_translation import get_dict_helper
+from . import find_element, get_resource_key
LOGGER = logging.getLogger(__name__)
-XPATH_ACL_SET = "//ocacl:acl/ocacl:acl-sets/ocacl:acl-set"
-XPATH_A_ACL_ENTRY = ".//ocacl:acl-entries/ocacl:acl-entry"
-XPATH_A_IPv4 = ".//ocacl:ipv4/ocacl:config"
-XPATH_A_TRANSPORT = ".//ocacl:transport/ocacl:config"
-XPATH_A_ACTIONS = ".//ocacl:actions/ocacl:config"
-
-XPATH_INTERFACE = "//ocacl:acl/ocacl:interfaces/ocacl:interface"
-XPATH_I_INGRESS = ".//ocacl:ingress-acl-sets/ocacl:ingress-acl-set"
-XPATH_I_EGRESS = ".//ocacl:egress-acl-sets/ocacl:egress-acl-set"
-
-def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
+def parse(xml_data : ET.Element, device_type : str = None) -> List[Tuple[str, Dict[str, Any]]]:
+ # Get device-specific paths
+ dict_helper = get_dict_helper(device_type)
+ xpath_acl_set = "//" + dict_helper.get_path('acl_set')
+ xpath_acl_entry = ".//" + dict_helper.get_path('acl_entry')
+ xpath_acl_ipv4 = ".//" + dict_helper.get_path('acl_ipv4')
+ xpath_acl_transport = ".//" + dict_helper.get_path('acl_transport')
+ xpath_acl_actions = ".//" + dict_helper.get_path('acl_actions')
+ xpath_acl_interface = "//" + dict_helper.get_path('acl_interface')
+ xpath_acl_ingress = ".//" + dict_helper.get_path('acl_ingress')
+ xpath_acl_egress = ".//" + dict_helper.get_path('acl_egress')
#LOGGER.info('[ACL] xml_data = {:s}'.format(str(ET.tostring(xml_data))))
response = []
acl = {}
name = {}
- for xml_acl in xml_data.xpath(XPATH_ACL_SET, namespaces=NAMESPACES):
+ for xml_acl in xml_data.xpath(xpath_acl_set, namespaces=NAMESPACES):
#LOGGER.info('xml_acl = {:s}'.format(str(ET.tostring(xml_acl))))
- acl_name = xml_acl.find('ocacl:name', namespaces=NAMESPACES)
+ acl_name = find_element(xml_acl, 'acl_name', device_type, NAMESPACES)
if acl_name is None or acl_name.text is None: continue
add_value_from_tag(name, 'name', acl_name)
- acl_type = xml_acl.find('ocacl:type', namespaces=NAMESPACES)
+ acl_type = find_element(xml_acl, 'acl_type', device_type, NAMESPACES)
add_value_from_tag(acl, 'type', acl_type)
- for xml_acl_entries in xml_acl.xpath(XPATH_A_ACL_ENTRY, namespaces=NAMESPACES):
+ for xml_acl_entries in xml_acl.xpath(xpath_acl_entry, namespaces=NAMESPACES):
- acl_id = xml_acl_entries.find('ocacl:sequence-id', namespaces=NAMESPACES)
+ acl_id = find_element(xml_acl_entries, 'acl_sequence_id', device_type, NAMESPACES)
add_value_from_tag(acl, 'sequence-id', acl_id)
LOGGER.info('xml_acl_id = {:s}'.format(str(ET.tostring(acl_id))))
- for xml_ipv4 in xml_acl_entries.xpath(XPATH_A_IPv4, namespaces=NAMESPACES):
+ for xml_ipv4 in xml_acl_entries.xpath(xpath_acl_ipv4, namespaces=NAMESPACES):
- ipv4_source = xml_ipv4.find('ocacl:source-address', namespaces=NAMESPACES)
+ ipv4_source = find_element(xml_ipv4, 'acl_source_address', device_type, NAMESPACES)
add_value_from_tag(acl, 'source-address' , ipv4_source)
- ipv4_destination = xml_ipv4.find('ocacl:destination-address', namespaces=NAMESPACES)
+ ipv4_destination = find_element(xml_ipv4, 'acl_destination_address', device_type, NAMESPACES)
add_value_from_tag(acl, 'destination-address' , ipv4_destination)
- ipv4_protocol = xml_ipv4.find('ocacl:protocol', namespaces=NAMESPACES)
+ ipv4_protocol = find_element(xml_ipv4, 'acl_protocol', device_type, NAMESPACES)
add_value_from_tag(acl, 'protocol' , ipv4_protocol)
- ipv4_dscp = xml_ipv4.find('ocacl:dscp', namespaces=NAMESPACES)
+ ipv4_dscp = find_element(xml_ipv4, 'acl_dscp', device_type, NAMESPACES)
add_value_from_tag(acl, 'dscp' , ipv4_dscp)
- ipv4_hop_limit = xml_ipv4.find('ocacl:hop-limit', namespaces=NAMESPACES)
+ ipv4_hop_limit = find_element(xml_ipv4, 'acl_hop_limit', device_type, NAMESPACES)
add_value_from_tag(acl, 'hop-limit' , ipv4_hop_limit)
- for xml_transport in xml_acl_entries.xpath(XPATH_A_TRANSPORT, namespaces=NAMESPACES):
+ for xml_transport in xml_acl_entries.xpath(xpath_acl_transport, namespaces=NAMESPACES):
- transport_source = xml_transport.find('ocacl:source-port', namespaces=NAMESPACES)
+ transport_source = find_element(xml_transport, 'acl_source_port', device_type, NAMESPACES)
add_value_from_tag(acl, 'source-port' ,transport_source)
- transport_destination = xml_transport.find('ocacl:destination-port', namespaces=NAMESPACES)
+ transport_destination = find_element(xml_transport, 'acl_destination_port', device_type, NAMESPACES)
add_value_from_tag(acl, 'destination-port' ,transport_destination)
- transport_tcp_flags = xml_transport.find('ocacl:tcp-flags', namespaces=NAMESPACES)
+ transport_tcp_flags = find_element(xml_transport, 'acl_tcp_flags', device_type, NAMESPACES)
add_value_from_tag(acl, 'tcp-flags' ,transport_tcp_flags)
- for xml_action in xml_acl_entries.xpath(XPATH_A_ACTIONS, namespaces=NAMESPACES):
+ for xml_action in xml_acl_entries.xpath(xpath_acl_actions, namespaces=NAMESPACES):
- action = xml_action.find('ocacl:forwarding-action', namespaces=NAMESPACES)
+ action = find_element(xml_action, 'acl_forwarding_action', device_type, NAMESPACES)
add_value_from_tag(acl, 'forwarding-action' ,action)
- log_action = xml_action.find('ocacl:log-action', namespaces=NAMESPACES)
+ log_action = find_element(xml_action, 'acl_log_action', device_type, NAMESPACES)
add_value_from_tag(acl, 'log-action' ,log_action)
- resource_key = '/acl/acl-set[{:s}][{:s}]/acl-entry[{:s}]'.format(
- name['name'], acl['type'], acl['sequence-id'])
+ resource_key = get_resource_key('acl_set_entry', device_type,
+ name=name['name'], type=acl['type'], sequence_id=acl['sequence-id'])
response.append((resource_key,acl))
- for xml_interface in xml_data.xpath(XPATH_INTERFACE, namespaces=NAMESPACES):
+ for xml_interface in xml_data.xpath(xpath_acl_interface, namespaces=NAMESPACES):
interface = {}
- interface_id = xml_interface.find('ocacl:id', namespaces=NAMESPACES)
+ interface_id = find_element(xml_interface, 'acl_interface_id', device_type, NAMESPACES)
add_value_from_tag(interface, 'id' , interface_id)
- for xml_ingress in xml_interface.xpath(XPATH_I_INGRESS, namespaces=NAMESPACES):
+ for xml_ingress in xml_interface.xpath(xpath_acl_ingress, namespaces=NAMESPACES):
- i_name = xml_ingress.find('ocacl:set-name-ingress', namespaces=NAMESPACES)
+ i_name = find_element(xml_ingress, 'acl_set_name_ingress', device_type, NAMESPACES)
add_value_from_tag(interface, 'ingress-set-name' , i_name)
- i_type = xml_ingress.find('ocacl:type-ingress', namespaces=NAMESPACES)
+ i_type = find_element(xml_ingress, 'acl_type_ingress', device_type, NAMESPACES)
add_value_from_tag(interface, 'ingress-type' , i_type)
- resource_key = '/acl/interfaces/ingress[{:s}][{:s}]'.format(
- name['name'], acl['type'])
+ resource_key = get_resource_key('acl_interfaces_ingress', device_type,
+ name=name['name'], type=acl['type'])
response.append((resource_key,interface))
- for xml_egress in xml_interface.xpath(XPATH_I_EGRESS, namespaces=NAMESPACES):
+ for xml_egress in xml_interface.xpath(xpath_acl_egress, namespaces=NAMESPACES):
- e_name = xml_egress.find('ocacl:set-name-egress', namespaces=NAMESPACES)
+ e_name = find_element(xml_egress, 'acl_set_name_egress', device_type, NAMESPACES)
add_value_from_tag(interface, 'egress-set-name' , e_name)
- e_type = xml_egress.find('ocacl:type-egress', namespaces=NAMESPACES)
+ e_type = find_element(xml_egress, 'acl_type_egress', device_type, NAMESPACES)
add_value_from_tag(interface, 'egress-type' , e_type)
- resource_key = '/acl/interfaces/egress[{:s}][{:s}]'.format(
- name['name'], acl['type'])
+ resource_key = get_resource_key('acl_interfaces_egress', device_type,
+ name=name['name'], type=acl['type'])
response.append((resource_key,interface))
return response
diff --git a/src/device/service/drivers/openconfig/templates/EndPoints.py b/src/device/service/drivers/openconfig/templates/EndPoints.py
index dc607cb6763d38153cada21d9e2794d4ea128f07..c628b37884afacd17d60b72ec3e48a5c4d7f65ce 100644
--- a/src/device/service/drivers/openconfig/templates/EndPoints.py
+++ b/src/device/service/drivers/openconfig/templates/EndPoints.py
@@ -17,18 +17,22 @@ from typing import Any, Dict, List, Tuple
from common.proto.kpi_sample_types_pb2 import KpiSampleType
from .Namespace import NAMESPACES
from .Tools import add_value_from_collection, add_value_from_tag
+from inter_device_translation import get_dict_helper, DictHelper
+from . import find_element, get_resource_key
LOGGER = logging.getLogger(__name__)
-XPATH_PORTS = "//ocp:components/ocp:component"
-XPATH_IFACE_COUNTER = "//oci:interfaces/oci:interface[oci:name='{:s}']/state/counters/{:s}"
-
-def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
+def parse(xml_data : ET.Element, device_type : str = None) -> List[Tuple[str, Dict[str, Any]]]:
+ # Get device-specific paths
+ dict_helper = get_dict_helper(device_type)
+ xpath_ports = "//" + dict_helper.get_path('ports')
+ xpath_iface_counter = "//" + dict_helper.get_path('interface_counters')
+
response = []
- for xml_component in xml_data.xpath(XPATH_PORTS, namespaces=NAMESPACES):
+ for xml_component in xml_data.xpath(xpath_ports, namespaces=NAMESPACES):
#LOGGER.info('xml_component = {:s}'.format(str(ET.tostring(xml_component))))
- component_type = xml_component.find('ocp:state/ocp:type', namespaces=NAMESPACES)
+ component_type = find_element(xml_component, 'ep_component_type', device_type, NAMESPACES)
if component_type is None or component_type.text is None: continue
component_type = component_type.text
if component_type not in {'PORT', 'oc-platform-types:PORT', 'idx:PORT'}: continue
@@ -37,23 +41,22 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
endpoint = {}
- component_name = xml_component.find('ocp:name', namespaces=NAMESPACES)
+ component_name = find_element(xml_component, 'ep_component_name', device_type, NAMESPACES)
if component_name is None or component_name.text is None: continue
add_value_from_tag(endpoint, 'uuid', component_name)
- component_type = xml_component.find(
- 'ocpp:port/ocpp:breakout-mode/ocpp:state/ocpp:channel-speed', namespaces=NAMESPACES)
+ component_type = find_element(xml_component, 'ep_port_channel_speed', device_type, NAMESPACES)
add_value_from_tag(endpoint, 'type', component_type)
if 'type' not in endpoint: endpoint['type'] = '-'
sample_types = {
- KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED : XPATH_IFACE_COUNTER.format(endpoint['uuid'], 'in-octets' ),
- KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED : XPATH_IFACE_COUNTER.format(endpoint['uuid'], 'out-octets'),
- KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED : XPATH_IFACE_COUNTER.format(endpoint['uuid'], 'in-pkts' ),
- KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED: XPATH_IFACE_COUNTER.format(endpoint['uuid'], 'out-pkts' ),
+ KpiSampleType.KPISAMPLETYPE_BYTES_RECEIVED : "//" + dict_helper.get_path('interface_counters', interface_name=endpoint['uuid'], counter_name='in-octets'),
+ KpiSampleType.KPISAMPLETYPE_BYTES_TRANSMITTED : "//" + dict_helper.get_path('interface_counters', interface_name=endpoint['uuid'], counter_name='out-octets'),
+ KpiSampleType.KPISAMPLETYPE_PACKETS_RECEIVED : "//" + dict_helper.get_path('interface_counters', interface_name=endpoint['uuid'], counter_name='in-pkts'),
+ KpiSampleType.KPISAMPLETYPE_PACKETS_TRANSMITTED: "//" + dict_helper.get_path('interface_counters', interface_name=endpoint['uuid'], counter_name='out-pkts'),
}
add_value_from_collection(endpoint, 'sample_types', sample_types)
if len(endpoint) == 0: continue
- response.append(('/endpoints/endpoint[{:s}]'.format(endpoint['uuid']), endpoint))
+ response.append((get_resource_key('endpoints_endpoint', device_type, uuid=endpoint['uuid']), endpoint))
return response
diff --git a/src/device/service/drivers/openconfig/templates/Interfaces.py b/src/device/service/drivers/openconfig/templates/Interfaces.py
index aea737100bcd980a097d2d2254750e44d59809a0..6f0b0474e83987e0dac9627b557b884408980c27 100644
--- a/src/device/service/drivers/openconfig/templates/Interfaces.py
+++ b/src/device/service/drivers/openconfig/templates/Interfaces.py
@@ -16,31 +16,31 @@ import logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES
from .Tools import add_value_from_tag
+from inter_device_translation import get_dict_helper, DictHelper
+from . import find_element, get_resource_key
LOGGER = logging.getLogger(__name__)
-XPATH_INTERFACES = "//oci:interfaces/oci:interface"
-XPATH_SUBINTERFACES = ".//oci:subinterfaces/oci:subinterface"
-XPATH_IPV4ADDRESSES = ".//ociip:ipv4/ociip:addresses/ociip:address"
-XPATH_IPV6ADDRESSES = ".//ociip:ipv6/ociip:addresses/ociip:address"
-
-def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
+def parse(xml_data : ET.Element, device_type : str = None) -> List[Tuple[str, Dict[str, Any]]]:
+ # Get device-specific paths
+ dict_helper = get_dict_helper(device_type)
+ xpath_interfaces = "//" + dict_helper.get_path('interfaces')
+ xpath_subinterfaces = ".//" + dict_helper.get_path('subinterfaces')
+ xpath_ipv4_addresses = ".//" + dict_helper.get_path('ipv4_addresses')
+ xpath_ipv6_addresses = ".//" + dict_helper.get_path('ipv6_addresses')
response = []
- for xml_interface in xml_data.xpath(XPATH_INTERFACES, namespaces=NAMESPACES):
+ for xml_interface in xml_data.xpath(xpath_interfaces, namespaces=NAMESPACES):
#LOGGER.info('xml_interface = {:s}'.format(str(ET.tostring(xml_interface))))
interface = {}
- #interface_type = xml_interface.find('oci:config/oci:type', namespaces=NAMESPACES)
- #add_value_from_tag(interface, 'type', interface_type)
-
- if xml_interface.find('oci:config/oci:type', namespaces=NAMESPACES) is not None:
- interface_type = xml_interface.find('oci:config/oci:type', namespaces=NAMESPACES)
- elif xml_interface.find('oci:state/oci:type', namespaces=NAMESPACES) is not None:
- interface_type = xml_interface.find('oci:state/oci:type', namespaces=NAMESPACES)
- else: continue
+ # Try to find interface type in config first, then state
+ interface_type = find_element(xml_interface, 'interface_type', device_type, NAMESPACES)
+ if interface_type is None:
+ interface_type = find_element(xml_interface, 'interface_state_type', device_type, NAMESPACES)
+ if interface_type is None: continue
- interface_name = xml_interface.find('oci:name', namespaces=NAMESPACES)
+ interface_name = find_element(xml_interface, 'interface_name', device_type, NAMESPACES)
if interface_name is None or interface_name.text is None: continue
add_value_from_tag(interface, 'name', interface_name)
@@ -51,13 +51,13 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
interface_type.text = interface_type.text.replace('idx:', '') #CISCO
add_value_from_tag(interface, 'type', interface_type)
- interface_mtu = xml_interface.find('oci:config/oci:mtu', namespaces=NAMESPACES)
+ interface_mtu = find_element(xml_interface, 'interface_mtu', device_type, NAMESPACES)
add_value_from_tag(interface, 'mtu', interface_mtu, cast=int)
- interface_description = xml_interface.find('oci:config/oci:description', namespaces=NAMESPACES)
+ interface_description = find_element(xml_interface, 'interface_description', device_type, NAMESPACES)
add_value_from_tag(interface, 'description', interface_description)
- for xml_subinterface in xml_interface.xpath(XPATH_SUBINTERFACES, namespaces=NAMESPACES):
+ for xml_subinterface in xml_interface.xpath(xpath_subinterfaces, namespaces=NAMESPACES):
#LOGGER.info('xml_subinterface = {:s}'.format(str(ET.tostring(xml_subinterface))))
subinterface = {}
@@ -67,16 +67,16 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
add_value_from_tag(subinterface, 'type', interface_type)
- subinterface_index = xml_subinterface.find('oci:index', namespaces=NAMESPACES)
+ subinterface_index = find_element(xml_subinterface, 'subinterface_index', device_type, NAMESPACES)
if subinterface_index is None or subinterface_index.text is None: continue
add_value_from_tag(subinterface, 'index', subinterface_index, cast=int)
- vlan_id = xml_subinterface.find('ocv:vlan/ocv:match/ocv:single-tagged/ocv:config/ocv:vlan-id', namespaces=NAMESPACES)
+ vlan_id = find_element(xml_subinterface, 'subinterface_vlan', device_type, NAMESPACES)
add_value_from_tag(subinterface, 'vlan_id', vlan_id, cast=int)
# TODO: implement support for multiple IP addresses per subinterface
#ipv4_addresses = []
- for xml_ipv4_address in xml_subinterface.xpath(XPATH_IPV4ADDRESSES, namespaces=NAMESPACES):
+ for xml_ipv4_address in xml_subinterface.xpath(xpath_ipv4_addresses, namespaces=NAMESPACES):
#LOGGER.info('xml_ipv4_address = {:s}'.format(str(ET.tostring(xml_ipv4_address))))
#ipv4_address = {}
@@ -84,11 +84,11 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
#origin = xml_ipv4_address.find('ociip:state/ociip:origin', namespaces=NAMESPACES)
#add_value_from_tag(ipv4_address, 'origin', origin)
- address = xml_ipv4_address.find('ociip:state/ociip:ip', namespaces=NAMESPACES)
+ address = find_element(xml_ipv4_address, 'ipv4_address', device_type, NAMESPACES)
#add_value_from_tag(ipv4_address, 'ip', address)
add_value_from_tag(subinterface, 'address_ip', address)
- prefix = xml_ipv4_address.find('ociip:state/ociip:prefix-length', namespaces=NAMESPACES)
+ prefix = find_element(xml_ipv4_address, 'ipv4_prefix', device_type, NAMESPACES)
#add_value_from_tag(ipv4_address, 'prefix_length', prefix)
add_value_from_tag(subinterface, 'address_prefix', prefix, cast=int)
@@ -97,17 +97,18 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
#add_value_from_collection(subinterface, 'ipv4_addresses', ipv4_addresses)
- for xml_ipv6_address in xml_subinterface.xpath(XPATH_IPV6ADDRESSES, namespaces=NAMESPACES):
+ for xml_ipv6_address in xml_subinterface.xpath(xpath_ipv6_addresses, namespaces=NAMESPACES):
#LOGGER.info('xml_ipv6_address = {:s}'.format(str(ET.tostring(xml_ipv6_address))))
- address = xml_ipv6_address.find('ociip:state/ociip:ip', namespaces=NAMESPACES)
+ address = find_element(xml_ipv6_address, 'ipv6_address', device_type, NAMESPACES)
add_value_from_tag(subinterface, 'address_ipv6', address)
- prefix = xml_ipv6_address.find('ociip:state/ociip:prefix-length', namespaces=NAMESPACES)
+ prefix = find_element(xml_ipv6_address, 'ipv6_prefix', device_type, NAMESPACES)
add_value_from_tag(subinterface, 'address_prefix_v6', prefix, cast=int)
if len(subinterface) == 0: continue
- resource_key = '/interface[{:s}]/subinterface[{:s}]'.format(interface['name'], str(subinterface['index']))
+ resource_key = get_resource_key('interface_subinterface', device_type,
+ name=interface['name'], index=str(subinterface['index']))
response.append((resource_key, subinterface))
if len(interface) == 0: continue
@@ -115,36 +116,40 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
return response
-def parse_counters(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
+def parse_counters(xml_data : ET.Element, device_type : str = None) -> List[Tuple[str, Dict[str, Any]]]:
+ # Get device-specific paths
+ dict_helper = get_dict_helper(device_type)
+ xpath_interfaces = "//" + dict_helper.get_path('interfaces')
+
response = []
- for xml_interface in xml_data.xpath(XPATH_INTERFACES, namespaces=NAMESPACES):
+ for xml_interface in xml_data.xpath(xpath_interfaces, namespaces=NAMESPACES):
#LOGGER.info('[parse_counters] xml_interface = {:s}'.format(str(ET.tostring(xml_interface))))
interface = {}
- interface_name = xml_interface.find('oci:name', namespaces=NAMESPACES)
+ interface_name = find_element(xml_interface, 'interface_name', device_type, NAMESPACES)
if interface_name is None or interface_name.text is None: continue
add_value_from_tag(interface, 'name', interface_name)
- interface_in_pkts = xml_interface.find('oci:state/oci:counters/oci:in-pkts', namespaces=NAMESPACES)
+ interface_in_pkts = find_element(xml_interface, 'interface_counters_in_pkts', device_type, NAMESPACES)
add_value_from_tag(interface, 'in-pkts', interface_in_pkts, cast=int)
- interface_in_octets = xml_interface.find('oci:state/oci:counters/oci:in-octets', namespaces=NAMESPACES)
+ interface_in_octets = find_element(xml_interface, 'interface_counters_in_octets', device_type, NAMESPACES)
add_value_from_tag(interface, 'in-octets', interface_in_octets, cast=int)
- interface_in_errors = xml_interface.find('oci:state/oci:counters/oci:in-errors', namespaces=NAMESPACES)
+ interface_in_errors = find_element(xml_interface, 'interface_counters_in_errors', device_type, NAMESPACES)
add_value_from_tag(interface, 'in-errors', interface_in_errors, cast=int)
- interface_out_octets = xml_interface.find('oci:state/oci:counters/oci:out-octets', namespaces=NAMESPACES)
+ interface_out_octets = find_element(xml_interface, 'interface_counters_out_octets', device_type, NAMESPACES)
add_value_from_tag(interface, 'out-octets', interface_out_octets, cast=int)
- interface_out_pkts = xml_interface.find('oci:state/oci:counters/oci:out-pkts', namespaces=NAMESPACES)
+ interface_out_pkts = find_element(xml_interface, 'interface_counters_out_pkts', device_type, NAMESPACES)
add_value_from_tag(interface, 'out-pkts', interface_out_pkts, cast=int)
- interface_out_errors = xml_interface.find('oci:state/oci:counters/oci:out-errors', namespaces=NAMESPACES)
+ interface_out_errors = find_element(xml_interface, 'interface_counters_out_errors', device_type, NAMESPACES)
add_value_from_tag(interface, 'out-errors', interface_out_errors, cast=int)
- interface_out_discards = xml_interface.find('oci:state/oci:counters/oci:out-discards', namespaces=NAMESPACES)
+ interface_out_discards = find_element(xml_interface, 'interface_counters_out_discards', device_type, NAMESPACES)
add_value_from_tag(interface, 'out-discards', interface_out_discards, cast=int)
#LOGGER.info('[parse_counters] interface = {:s}'.format(str(interface)))
diff --git a/src/device/service/drivers/openconfig/templates/Inventory.py b/src/device/service/drivers/openconfig/templates/Inventory.py
index d54d21d47aa1ed7e821e2c8572cc19f481a406f7..751f4a428f13a4989e97910877a90a9e6dddb7e4 100644
--- a/src/device/service/drivers/openconfig/templates/Inventory.py
+++ b/src/device/service/drivers/openconfig/templates/Inventory.py
@@ -16,11 +16,11 @@ import logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES
from .Tools import add_value_from_tag
+from inter_device_translation import get_dict_helper
+from . import find_element, get_resource_key
LOGGER = logging.getLogger(__name__)
-XPATH_PORTS = "//ocp:components/ocp:component"
-
"""
#Method Name: parse
@@ -52,10 +52,14 @@ XPATH_PORTS = "//ocp:components/ocp:component"
with the information extracted from the XML document components is returned.
"""
-def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
+def parse(xml_data : ET.Element, device_type : str = None) -> List[Tuple[str, Dict[str, Any]]]:
+ # Get device-specific paths
+ dict_helper = get_dict_helper(device_type)
+ xpath_ports = "//" + dict_helper.get_path('ports')
+
response = []
parent_types = {}
- for xml_component in xml_data.xpath(XPATH_PORTS, namespaces=NAMESPACES):
+ for xml_component in xml_data.xpath(xpath_ports, namespaces=NAMESPACES):
LOGGER.info('xml_component inventario = {:s}'.format(str(ET.tostring(xml_component))))
inventory = {}
inventory['parent-component-references'] = ''
@@ -64,82 +68,82 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
inventory['attributes'] = {}
component_reference = []
- component_name = xml_component.find('ocp:name', namespaces=NAMESPACES)
+ component_name = find_element(xml_component, 'inv_component_name', device_type, NAMESPACES)
if component_name is None or component_name.text is None: continue
add_value_from_tag(inventory, 'name', component_name)
- component_description = xml_component.find('ocp:state/ocp:description', namespaces=NAMESPACES)
+ component_description = find_element(xml_component, 'inv_component_description', device_type, NAMESPACES)
if not component_description is None:
add_value_from_tag(inventory['attributes'], 'description', component_description)
- component_location = xml_component.find('ocp:state/ocp:location', namespaces=NAMESPACES)
+ component_location = find_element(xml_component, 'inv_component_location', device_type, NAMESPACES)
if not component_location is None:
add_value_from_tag(inventory['attributes'], 'location', component_location)
- component_id = xml_component.find('ocp:state/ocp:id', namespaces=NAMESPACES)
+ component_id = find_element(xml_component, 'inv_component_id', device_type, NAMESPACES)
if not component_id is None:
add_value_from_tag(inventory['attributes'], 'id', component_id)
- component_type = xml_component.find('ocp:state/ocp:type', namespaces=NAMESPACES)
+ component_type = find_element(xml_component, 'inv_component_type', device_type, NAMESPACES)
if component_type is not None:
component_type.text = component_type.text.replace('oc-platform-types:','')
add_value_from_tag(inventory, 'class', component_type)
if inventory['class'] == 'CPU' or inventory['class'] == 'STORAGE': continue
- component_empty = xml_component.find('ocp:state/ocp:empty', namespaces=NAMESPACES)
+ component_empty = find_element(xml_component, 'inv_component_empty', device_type, NAMESPACES)
if not component_empty is None:
add_value_from_tag(inventory['attributes'], 'empty', component_empty)
- component_parent = xml_component.find('ocp:state/ocp:parent', namespaces=NAMESPACES)
+ component_parent = find_element(xml_component, 'inv_component_parent', device_type, NAMESPACES)
if not component_parent is None:
add_value_from_tag(inventory, 'parent-component-references', component_parent)
- component_HW = xml_component.find('ocp:state/ocp:hardware-version', namespaces=NAMESPACES)
+ component_HW = find_element(xml_component, 'inv_component_hardware_version', device_type, NAMESPACES)
if not component_HW is None:
add_value_from_tag(inventory['attributes'], 'hardware-rev', component_HW)
- component_firmware_version = xml_component.find('ocp:state/ocp:firmware-version', namespaces=NAMESPACES)
+ component_firmware_version = find_element(xml_component, 'inv_component_firmware_version', device_type, NAMESPACES)
if not component_firmware_version is None:
add_value_from_tag(inventory['attributes'], 'firmware-rev', component_firmware_version)
- component_SW = xml_component.find('ocp:state/ocp:software-version', namespaces=NAMESPACES)
+ component_SW = find_element(xml_component, 'inv_component_software_version', device_type, NAMESPACES)
if not component_SW is None:
add_value_from_tag(inventory['attributes'], 'software-rev', component_SW)
- component_serial = xml_component.find('ocp:state/ocp:serial-no', namespaces=NAMESPACES)
+ component_serial = find_element(xml_component, 'inv_component_serial', device_type, NAMESPACES)
if not component_serial is None:
add_value_from_tag(inventory['attributes'], 'serial-num', component_serial)
- component_mfg_name = xml_component.find('ocp:state/ocp:mfg-name', namespaces=NAMESPACES)
+ component_mfg_name = find_element(xml_component, 'inv_component_mfg_name', device_type, NAMESPACES)
if not component_mfg_name is None:
add_value_from_tag(inventory['attributes'], 'mfg-name', component_mfg_name)
- component_removable = xml_component.find('ocp:state/ocp:removable', namespaces=NAMESPACES)
+ component_removable = find_element(xml_component, 'inv_component_removable', device_type, NAMESPACES)
if not component_removable is None:
add_value_from_tag(inventory['attributes'], 'removable', component_removable)
- component_mfg_date = xml_component.find('ocp:state/ocp:mfg-date', namespaces=NAMESPACES)
+ component_mfg_date = find_element(xml_component, 'inv_component_mfg_date', device_type, NAMESPACES)
if not component_mfg_date is None:
add_value_from_tag(inventory['attributes'], 'mfg-date', component_mfg_date)
#Transceiver Information
- component_serial_t = xml_component.find('ocptr:transceiver/ocptr:state/ocptr:serial-no', namespaces=NAMESPACES)
+ component_serial_t = find_element(xml_component, 'inv_transceiver_serial', device_type, NAMESPACES)
if not component_serial_t is None:
add_value_from_tag(inventory['attributes'], 'serial-num', component_serial_t)
- component_present = xml_component.find('ocptr:transceiver/ocptr:state/ocptr:present', namespaces=NAMESPACES)
+ component_present = find_element(xml_component, 'inv_transceiver_present', device_type, NAMESPACES)
if component_present is not None and 'NOT_PRESENT' in component_present.text: continue
- component_vendor = xml_component.find('ocptr:transceiver/ocptr:state/ocptr:vendor', namespaces=NAMESPACES)
+ component_vendor = find_element(xml_component, 'inv_transceiver_vendor', device_type, NAMESPACES)
if not component_vendor is None:
add_value_from_tag(inventory['attributes'], 'vendor', component_vendor)
- component_connector = xml_component.find('ocptr:transceiver/ocptr:state/ocptr:connector-type', namespaces=NAMESPACES)
+ component_connector = find_element(xml_component, 'inv_transceiver_connector', device_type, NAMESPACES)
if not component_connector is None:
component_connector.text = component_connector.text.replace('oc-opt-types:','')
add_value_from_tag(inventory['attributes'], 'connector-type', component_connector)
- component_form = xml_component.find('ocptr:transceiver/ocptr:state/ocptr:form-factor', namespaces=NAMESPACES)
+ component_form = find_element(xml_component, 'inv_transceiver_form', device_type, NAMESPACES)
if not component_form is None:
component_form.text = component_form.text.replace('oc-opt-types:','')
add_value_from_tag(inventory['attributes'], 'form-factor', component_form)
@@ -149,7 +153,7 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
component_reference.extend([parent_types[inventory['parent-component-references']]])
- response.append(('/inventory/{:s}'.format(inventory['name']), inventory))
+ response.append((get_resource_key('inventory_component', device_type, name=inventory['name']), inventory))
for tupla in response:
if inventory['parent-component-references'] in tupla[0]:
diff --git a/src/device/service/drivers/openconfig/templates/Namespace.py b/src/device/service/drivers/openconfig/templates/Namespace.py
index 4604481bb666365752e33e9a8ef3bcf8523e6d1c..fd9af8cbda5355e1a2bedd7f7fdfa21586b54343 100644
--- a/src/device/service/drivers/openconfig/templates/Namespace.py
+++ b/src/device/service/drivers/openconfig/templates/Namespace.py
@@ -30,6 +30,18 @@ NAMESPACE_ROUTING_POLICY = 'http://openconfig.net/yang/routing-policy'
NAMESPACE_VLAN = 'http://openconfig.net/yang/vlan'
NAMESPACE_PLATFORM_TRANSCEIVER = 'http://openconfig.net/yang/platform/transceiver'
+
+NAMESPACE_IPI_INTERFACE = 'http://www.ipinfusion.com/yang/ocnos/ipi-interface'
+NAMESPACE_IPI_INTERFACE_EXTENDED = 'http://www.ipinfusion.com/yang/ocnos/ipi-if-extended'
+NAMESPACE_IPI_INTERFACE_IP = 'http://www.ipinfusion.com/yang/ocnos/ipi-if-ip'
+NAMESPACE_IPI_NETWORK_INSTANCE = 'http://www.ipinfusion.com/yang/ocnos/ipi-network-instance'
+NAMESPACE_IPI_VLAN = 'http://www.ipinfusion.com/yang/ocnos/ipi-vlan'
+NAMESPACE_IPI_ACL = 'http://www.ipinfusion.com/yang/ocnos/ipi-acl'
+NAMESPACE_IPI_ROUTING_POLICY = 'http://www.ipinfusion.com/yang/ocnos/ipi-routing-policy'
+NAMESPACE_IPI_BGP_POLICY = 'http://www.ipinfusion.com/yang/ocnos/ipi-bgp-policy'
+NAMESPACE_IPI_PLATFORM_PORT = 'http://www.ipinfusion.com/yang/ocnos/ipi-platform/port'
+NAMESPACE_IPI_PLATFORM_TRANSCEIVER = 'http://www.ipinfusion.com/yang/ocnos/ipi-platform/transceiver'
+
NAMESPACES = {
'nc' : NAMESPACE_NETCONF,
'ocacl': NAMESPACE_ACL,
@@ -46,4 +58,19 @@ NAMESPACES = {
'ocrp' : NAMESPACE_ROUTING_POLICY,
'ocv' : NAMESPACE_VLAN,
'ocptr': NAMESPACE_PLATFORM_TRANSCEIVER,
+
+ 'ipii': NAMESPACE_IPI_INTERFACE,
+ 'ipiie': NAMESPACE_IPI_INTERFACE_EXTENDED,
+ 'ipiiip': NAMESPACE_IPI_INTERFACE_IP,
+ 'ipini': NAMESPACE_IPI_NETWORK_INSTANCE,
+ 'ipiv' : NAMESPACE_IPI_VLAN,
+ 'ipiacl': NAMESPACE_IPI_ACL,
+ 'ipirp': NAMESPACE_IPI_ROUTING_POLICY,
+ 'ipibp': NAMESPACE_IPI_BGP_POLICY,
+ 'ipipp': NAMESPACE_IPI_PLATFORM_PORT,
+ 'ipitr': NAMESPACE_IPI_PLATFORM_TRANSCEIVER,
+
+ 'ipinfusion-interfaces': NAMESPACE_IPI_INTERFACE,
+ 'ipinfusion-network-instance': NAMESPACE_IPI_NETWORK_INSTANCE,
+ 'ipinfusion-network-instances': NAMESPACE_IPI_NETWORK_INSTANCE,
}
diff --git a/src/device/service/drivers/openconfig/templates/NetworkInstances.py b/src/device/service/drivers/openconfig/templates/NetworkInstances.py
index 7fee1b76137e9d0d55451d2326c2a38c2d51d79e..ba542aa804a5b4ae00e8493e795a95aafa3f3beb 100644
--- a/src/device/service/drivers/openconfig/templates/NetworkInstances.py
+++ b/src/device/service/drivers/openconfig/templates/NetworkInstances.py
@@ -16,44 +16,37 @@ import logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES
from .Tools import add_value_from_collection, add_value_from_tag
+from inter_device_translation import get_dict_helper
+from . import find_element, get_resource_key
LOGGER = logging.getLogger(__name__)
-XPATH_NETWORK_INSTANCES = "//ocni:network-instances/ocni:network-instance"
-XPATH_NI_PROTOCOLS = ".//ocni:protocols/ocni:protocol"
-XPATH_NI_TABLE_CONNECTS = ".//ocni:table-connections/ocni:table-connection"
-
-XPATH_NI_INTERFACE = ".//ocni:interfaces/ocni:interface"
-
-XPATH_NI_IIP_AP = ".//ocni:inter-instance-policies/ocni:apply-policy"
-XPATH_NI_IIP_AP_IMPORT = ".//ocni:config/ocni:import-policy"
-XPATH_NI_IIP_AP_EXPORT = ".//ocni:config/ocni:export-policy"
-
-XPATH_NI_CPOINTS = ".//ocni:connection-points/ocni:connection-point"
-XPATH_NI_CPOINTS_ENDPOINT = ".//ocni:endpoints/ocni:endpoint/ocni:remote/ocni:config"
-
-def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
+def parse(xml_data : ET.Element, device_type : str = None) -> List[Tuple[str, Dict[str, Any]]]:
+ # Get device-specific paths
+ dict_helper = get_dict_helper(device_type)
+ xpath_network_instances = "//" + dict_helper.get_path('network_instances')
+ xpath_ni_protocols = ".//" + dict_helper.get_path('ni_protocols')
+ xpath_ni_table_connections = ".//" + dict_helper.get_path('ni_table_connections')
+ xpath_ni_interface = ".//" + dict_helper.get_path('ni_interface')
+ xpath_ni_apply_policy = ".//" + dict_helper.get_path('ni_apply_policy')
+ xpath_ni_import_policy = ".//" + dict_helper.get_path('ni_import_policy')
+ xpath_ni_export_policy = ".//" + dict_helper.get_path('ni_export_policy')
+ xpath_ni_connection_points = ".//" + dict_helper.get_path('ni_connection_points')
+ xpath_ni_endpoints = ".//" + dict_helper.get_path('ni_endpoints')
response = []
- for xml_network_instance in xml_data.xpath(XPATH_NETWORK_INSTANCES, namespaces=NAMESPACES):
+ for xml_network_instance in xml_data.xpath(xpath_network_instances, namespaces=NAMESPACES):
#LOGGER.info('xml_network_instance = {:s}'.format(str(ET.tostring(xml_network_instance))))
network_instance = {}
- ni_name = xml_network_instance.find('ocni:name', namespaces=NAMESPACES)
+ ni_name = find_element(xml_network_instance, 'ni_name', device_type, NAMESPACES)
if ni_name is None or ni_name.text is None: continue
add_value_from_tag(network_instance, 'name', ni_name)
- '''
- ni_type = xml_network_instance.find('ocni:config/ocni:type', namespaces=NAMESPACES)
- ni_type.text = ni_type.text.replace('oc-ni-types:','')
- add_value_from_tag(network_instance, 'type', ni_type)
- '''
+
- if xml_network_instance.find('ocni:config/ocni:type', namespaces=NAMESPACES) is not None:
- ni_type = xml_network_instance.find('ocni:config/ocni:type', namespaces=NAMESPACES)
- elif xml_network_instance.find('oci:state/oci:type', namespaces=NAMESPACES) is not None:
- ni_type = xml_network_instance.find('oci:state/oci:type', namespaces=NAMESPACES)
- else:
+ ni_type = find_element(xml_network_instance, 'ni_type', device_type, NAMESPACES)
+ if ni_type is None:
continue
if 'oc-ni-types:' in ni_type.text:
ni_type.text = ni_type.text.replace('oc-ni-types:', '') #ADVA
@@ -61,119 +54,119 @@ def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
ni_type.text = ni_type.text.replace('idx:', '') #CISCO
add_value_from_tag(network_instance, 'type', ni_type)
- ni_router_id = xml_network_instance.find('ocni:config/ocni:router-id', namespaces=NAMESPACES)
+ ni_router_id = find_element(xml_network_instance, 'ni_router_id', device_type, NAMESPACES)
add_value_from_tag(network_instance, 'router_id', ni_router_id)
- ni_route_dist = xml_network_instance.find('ocni:config/ocni:route-distinguisher', namespaces=NAMESPACES)
+ ni_route_dist = find_element(xml_network_instance, 'ni_route_distinguisher', device_type, NAMESPACES)
add_value_from_tag(network_instance, 'route_distinguisher', ni_route_dist)
#ni_address_families = []
#add_value_from_collection(network_instance, 'address_families', ni_address_families)
if len(network_instance) == 0: continue
- response.append(('/network_instance[{:s}]'.format(network_instance['name']), network_instance))
+ response.append((get_resource_key('network_instance', device_type, name=network_instance['name']), network_instance))
- for xml_cpoints in xml_network_instance.xpath(XPATH_NI_PROTOCOLS, namespaces=NAMESPACES):
+ for xml_cpoints in xml_network_instance.xpath(xpath_ni_protocols, namespaces=NAMESPACES):
cpoint = {}
add_value_from_tag(cpoint, 'name', ni_name)
- connection_point = xml_cpoints.find('ocni:connection-point-id', namespaces=NAMESPACES)
+ connection_point = find_element(xml_cpoints, 'ni_connection_point_id', device_type, NAMESPACES)
add_value_from_tag(cpoint, 'connection_point', connection_point)
- for xml_endpoint in xml_cpoints.xpath(XPATH_NI_CPOINTS_ENDPOINT, namespaces=NAMESPACES):
- remote_system = xml_endpoint.find('ocni:remote-system', namespaces=NAMESPACES)
+ for xml_endpoint in xml_cpoints.xpath(xpath_ni_endpoints, namespaces=NAMESPACES):
+ remote_system = find_element(xml_endpoint, 'ni_remote_system', device_type, NAMESPACES)
add_value_from_tag(cpoint, 'remote_system', remote_system)
- VC_ID = xml_endpoint.find('ocni:virtual-circuit-identifier', namespaces=NAMESPACES)
+ VC_ID = find_element(xml_endpoint, 'ni_virtual_circuit_identifier', device_type, NAMESPACES)
add_value_from_tag(cpoint, 'VC_ID', VC_ID)
- for xml_protocol in xml_network_instance.xpath(XPATH_NI_PROTOCOLS, namespaces=NAMESPACES):
+ for xml_protocol in xml_network_instance.xpath(xpath_ni_protocols, namespaces=NAMESPACES):
#LOGGER.info('xml_protocol = {:s}'.format(str(ET.tostring(xml_protocol))))
protocol = {}
add_value_from_tag(protocol, 'name', ni_name)
- identifier = xml_protocol.find('ocni:identifier', namespaces=NAMESPACES)
- if identifier is None: identifier = xml_protocol.find('ocpt:identifier', namespaces=NAMESPACES)
- if identifier is None: identifier = xml_protocol.find('ocpt2:identifier', namespaces=NAMESPACES)
+ identifier = find_element(xml_protocol, 'ni_protocol_identifier', device_type, NAMESPACES)
if identifier is None or identifier.text is None: continue
add_value_from_tag(protocol, 'identifier', identifier, cast=lambda s: s.replace('oc-pol-types:', ''))
- name = xml_protocol.find('ocni:name', namespaces=NAMESPACES)
+ name = find_element(xml_protocol, 'ni_protocol_name', device_type, NAMESPACES)
add_value_from_tag(protocol, 'protocol_name', name)
if protocol['identifier'] == 'BGP':
- bgp_as = xml_protocol.find('ocni:bgp/ocni:global/ocni:config/ocni:as', namespaces=NAMESPACES)
+ bgp_as = find_element(xml_protocol, 'ni_bgp_as', device_type, NAMESPACES)
add_value_from_tag(protocol, 'as', bgp_as, cast=int)
- bgp_id = xml_protocol.find('ocni:bgp/ocni:global/ocni:config/ocni:router-id', namespaces=NAMESPACES)
+ bgp_id = find_element(xml_protocol, 'ni_bgp_router_id', device_type, NAMESPACES)
add_value_from_tag(protocol, 'router_id', bgp_id)
- resource_key = '/network_instance[{:s}]/protocols[{:s}]'.format(
- network_instance['name'], protocol['identifier'])
+ resource_key = get_resource_key('network_instance_protocols', device_type,
+ name=network_instance['name'], identifier=protocol['identifier'])
response.append((resource_key, protocol))
- for xml_table_connection in xml_network_instance.xpath(XPATH_NI_TABLE_CONNECTS, namespaces=NAMESPACES):
+ for xml_table_connection in xml_network_instance.xpath(xpath_ni_table_connections, namespaces=NAMESPACES):
#LOGGER.info('xml_table_connection = {:s}'.format(str(ET.tostring(xml_table_connection))))
table_connection = {}
add_value_from_tag(table_connection, 'name', ni_name)
- src_protocol = xml_table_connection.find('ocni:src-protocol', namespaces=NAMESPACES)
+ src_protocol = find_element(xml_table_connection, 'ni_src_protocol', device_type, NAMESPACES)
add_value_from_tag(table_connection, 'src_protocol', src_protocol,
cast=lambda s: s.replace('oc-pol-types:', ''))
- dst_protocol = xml_table_connection.find('ocni:dst-protocol', namespaces=NAMESPACES)
+ dst_protocol = find_element(xml_table_connection, 'ni_dst_protocol', device_type, NAMESPACES)
add_value_from_tag(table_connection, 'dst_protocol', dst_protocol,
cast=lambda s: s.replace('oc-pol-types:', ''))
- address_family = xml_table_connection.find('ocni:address-family', namespaces=NAMESPACES)
+ address_family = find_element(xml_table_connection, 'ni_address_family', device_type, NAMESPACES)
add_value_from_tag(table_connection, 'address_family', address_family,
cast=lambda s: s.replace('oc-types:', ''))
- default_import_policy = xml_table_connection.find('ocni:config/ocni:default-import-policy', namespaces=NAMESPACES)
+ default_import_policy = find_element(xml_table_connection, 'ni_default_import_policy', device_type, NAMESPACES)
add_value_from_tag(table_connection, 'default_import_policy', default_import_policy)
- resource_key = '/network_instance[{:s}]/table_connections[{:s}][{:s}][{:s}]'.format(
- network_instance['name'], table_connection['src_protocol'], table_connection['dst_protocol'],
- table_connection['address_family'])
+ resource_key = get_resource_key('network_instance_table_connections', device_type,
+ name=network_instance['name'],
+ src_protocol=table_connection['src_protocol'],
+ dst_protocol=table_connection['dst_protocol'],
+ address_family=table_connection['address_family'])
response.append((resource_key, table_connection))
- for xml_interface in xml_network_instance.xpath(XPATH_NI_INTERFACE, namespaces=NAMESPACES):
+ for xml_interface in xml_network_instance.xpath(xpath_ni_interface, namespaces=NAMESPACES):
LOGGER.info('xml_interfaces = {:s}'.format(str(ET.tostring(xml_interface))))
interface = {}
- name_iface = xml_interface.find('ocni:config/ocni:interface', namespaces=NAMESPACES)
+ name_iface = find_element(xml_interface, 'ni_interface_name', device_type, NAMESPACES)
if name_iface is None or name_iface.text is None: continue
add_value_from_tag(interface, 'name_iface', name_iface)
- name_subiface = xml_interface.find('ocni:config/ocni:subinterface', namespaces=NAMESPACES)
+ name_subiface = find_element(xml_interface, 'ni_subinterface_name', device_type, NAMESPACES)
add_value_from_tag(interface, 'name_subiface', name_subiface)
- resource_key = '/network_instance[{:s}]/interface[{:s}]'.format(
- network_instance['name'], interface['name_iface'])
+ resource_key = get_resource_key('network_instance_interface', device_type,
+ name=network_instance['name'], interface_name=interface['name_iface'])
response.append((resource_key, interface))
- for xml_iip_ap in xml_network_instance.xpath(XPATH_NI_IIP_AP, namespaces=NAMESPACES):
+ for xml_iip_ap in xml_network_instance.xpath(xpath_ni_apply_policy, namespaces=NAMESPACES):
#LOGGER.info('xml_iip_ap = {:s}'.format(str(ET.tostring(xml_iip_ap))))
- for xml_import_policy in xml_iip_ap.xpath(XPATH_NI_IIP_AP_IMPORT, namespaces=NAMESPACES):
+ for xml_import_policy in xml_iip_ap.xpath(xpath_ni_import_policy, namespaces=NAMESPACES):
#LOGGER.info('xml_import_policy = {:s}'.format(str(ET.tostring(xml_import_policy))))
if xml_import_policy.text is None: continue
iip_ap = {}
add_value_from_tag(iip_ap, 'name', ni_name)
add_value_from_tag(iip_ap, 'import_policy', xml_import_policy)
- resource_key = '/network_instance[{:s}]/inter_instance_policies[{:s}]'.format(
- iip_ap['name'], iip_ap['import_policy'])
+ resource_key = get_resource_key('network_instance_inter_instance_policies', device_type,
+ name=iip_ap['name'], policy_name=iip_ap['import_policy'])
response.append((resource_key, iip_ap))
- for xml_export_policy in xml_iip_ap.xpath(XPATH_NI_IIP_AP_EXPORT, namespaces=NAMESPACES):
+ for xml_export_policy in xml_iip_ap.xpath(xpath_ni_export_policy, namespaces=NAMESPACES):
#LOGGER.info('xml_export_policy = {:s}'.format(str(ET.tostring(xml_export_policy))))
if xml_export_policy.text is None: continue
iip_ap = {}
add_value_from_tag(iip_ap, 'name', ni_name)
add_value_from_tag(iip_ap, 'export_policy', xml_export_policy)
- resource_key = '/network_instance[{:s}]/inter_instance_policies[{:s}]'.format(
- iip_ap['name'], iip_ap['export_policy'])
+ resource_key = get_resource_key('network_instance_inter_instance_policies', device_type,
+ name=iip_ap['name'], policy_name=iip_ap['export_policy'])
response.append((resource_key, iip_ap))
diff --git a/src/device/service/drivers/openconfig/templates/RoutingPolicy.py b/src/device/service/drivers/openconfig/templates/RoutingPolicy.py
index eac90ed5121309a154fe9c59e434aa461b96f670..e0f8c34447829b52046bc51c31083e76b7e90e80 100644
--- a/src/device/service/drivers/openconfig/templates/RoutingPolicy.py
+++ b/src/device/service/drivers/openconfig/templates/RoutingPolicy.py
@@ -16,72 +16,77 @@ import copy, logging, lxml.etree as ET
from typing import Any, Dict, List, Tuple
from .Namespace import NAMESPACES
from .Tools import add_value_from_tag
+from inter_device_translation import get_dict_helper
+from . import find_element, get_resource_key
LOGGER = logging.getLogger(__name__)
-XPATH_POLICY_DEFINITIONS = "//ocrp:routing-policy/ocrp:policy-definitions/ocrp:policy-definition"
-XPATH_PD_STATEMENTS = ".//ocrp:statements/ocrp:statement"
-XPATH_PD_ST_CONDITIONS = ".//ocrp:conditions/ocbp:bgp-conditions/ocbp:match-ext-community-set"
-XPATH_PD_ST_ACTIONS = ".//ocrp:actions"
-
-XPATH_BGP_EXT_COMMUN_SET = "//ocrp:routing-policy/ocrp:defined-sets/ocbp:bgp-defined-sets/" + \
- "ocbp:ext-community-sets/ocbp:ext-community-set"
-
-def parse(xml_data : ET.Element) -> List[Tuple[str, Dict[str, Any]]]:
+def parse(xml_data : ET.Element, device_type : str = None) -> List[Tuple[str, Dict[str, Any]]]:
+ # Get device-specific paths
+ dict_helper = get_dict_helper(device_type)
+ xpath_policy_definitions = "//" + dict_helper.get_path('routing_policy_definitions')
+ xpath_pd_statements = ".//" + dict_helper.get_path('pd_statements')
+ xpath_pd_conditions = ".//" + dict_helper.get_path('pd_conditions')
+ xpath_pd_actions = ".//" + dict_helper.get_path('pd_actions')
+ xpath_bgp_ext_community_set = "//" + dict_helper.get_path('bgp_ext_community_set')
#LOGGER.info('[RoutePolicy] xml_data = {:s}'.format(str(ET.tostring(xml_data))))
response = []
- for xml_policy_definition in xml_data.xpath(XPATH_POLICY_DEFINITIONS, namespaces=NAMESPACES):
+ for xml_policy_definition in xml_data.xpath(xpath_policy_definitions, namespaces=NAMESPACES):
#LOGGER.info('xml_policy_definition = {:s}'.format(str(ET.tostring(xml_policy_definition))))
policy_definition = {}
statement_name = ''
- policy_name = xml_policy_definition.find('ocrp:name', namespaces=NAMESPACES)
+ policy_name = find_element(xml_policy_definition, 'rp_policy_name', device_type, NAMESPACES)
if policy_name is None or policy_name.text is None: continue
add_value_from_tag(policy_definition, 'policy_name', policy_name)
- resource_key = '/routing_policy/policy_definition[{:s}]'.format(policy_definition['policy_name'])
+ resource_key = get_resource_key('routing_policy_definition', device_type,
+ name=policy_definition['policy_name'])
response.append((resource_key, copy.deepcopy(policy_definition)))
- for xml_statement in xml_policy_definition.xpath(XPATH_PD_STATEMENTS, namespaces=NAMESPACES):
- statement_name = xml_statement.find('ocrp:name', namespaces=NAMESPACES)
- if len(statement_name) != 0: #FIX: In case there is a route policy defined without a statement name
+ for xml_statement in xml_policy_definition.xpath(xpath_pd_statements, namespaces=NAMESPACES):
+ statement_name = find_element(xml_statement, 'rp_statement_name', device_type, NAMESPACES)
+ if statement_name is not None and len(statement_name) != 0: #FIX: In case there is a route policy defined without a statement name
add_value_from_tag(policy_definition, 'statement_name', statement_name)
- for xml_condition in xml_statement.xpath(XPATH_PD_ST_CONDITIONS, namespaces=NAMESPACES):
- ext_community_set_name = xml_condition.find('ocbp:config/ocbp:ext-community-set', namespaces=NAMESPACES)
+ for xml_condition in xml_statement.xpath(xpath_pd_conditions, namespaces=NAMESPACES):
+ ext_community_set_name = find_element(xml_condition, 'rp_ext_community_set', device_type, NAMESPACES)
add_value_from_tag(policy_definition, 'ext_community_set_name', ext_community_set_name)
- match_set_options = xml_condition.find('ocbp:config/ocbp:match-set-options', namespaces=NAMESPACES)
+ match_set_options = find_element(xml_condition, 'rp_match_set_options', device_type, NAMESPACES)
add_value_from_tag(policy_definition, 'match_set_options', match_set_options)
- for xml_action in xml_statement.xpath(XPATH_PD_ST_ACTIONS, namespaces=NAMESPACES):
- policy_result = xml_action.find('ocbp:config/ocbp:policy-result', namespaces=NAMESPACES)
+ for xml_action in xml_statement.xpath(xpath_pd_actions, namespaces=NAMESPACES):
+ policy_result = find_element(xml_action, 'rp_policy_result', device_type, NAMESPACES)
add_value_from_tag(policy_definition, 'policy_result', policy_result)
if len(statement_name) != 0: #FIX: In case there is a route policy defined without a statement name
- resource_key = '/routing_policy/policy_definition[{:s}]/statement[{:s}]'.format(
- policy_definition['policy_name'], policy_definition['statement_name'])
+ resource_key = get_resource_key('routing_policy_statement', device_type,
+ name=policy_definition['policy_name'],
+ statement_name=policy_definition['statement_name'])
response.append((resource_key, copy.deepcopy(policy_definition)))
- for xml_bgp_ext_community_set in xml_data.xpath(XPATH_BGP_EXT_COMMUN_SET, namespaces=NAMESPACES):
+ for xml_bgp_ext_community_set in xml_data.xpath(xpath_bgp_ext_community_set, namespaces=NAMESPACES):
#LOGGER.info('xml_bgp_ext_community_set = {:s}'.format(str(ET.tostring(xml_bgp_ext_community_set))))
bgp_ext_community_set = {}
- ext_community_set_name = xml_bgp_ext_community_set.find('ocbp:ext-community-set-name', namespaces=NAMESPACES)
+ ext_community_set_name = find_element(xml_bgp_ext_community_set, 'rp_ext_community_set_name', device_type, NAMESPACES)
if ext_community_set_name is None or ext_community_set_name.text is None: continue
add_value_from_tag(bgp_ext_community_set, 'ext_community_set_name', ext_community_set_name)
- resource_key = '/routing_policy/bgp_defined_set[{:s}]'.format(bgp_ext_community_set['ext_community_set_name'])
+ resource_key = get_resource_key('routing_policy_bgp_defined_set', device_type,
+ name=bgp_ext_community_set['ext_community_set_name'])
response.append((resource_key, copy.deepcopy(bgp_ext_community_set)))
- ext_community_member = xml_bgp_ext_community_set.find('ocbp:config/ocbp:ext-community-member', namespaces=NAMESPACES)
+ ext_community_member = find_element(xml_bgp_ext_community_set, 'rp_ext_community_member', device_type, NAMESPACES)
if ext_community_member is not None and ext_community_member.text is not None:
add_value_from_tag(bgp_ext_community_set, 'ext_community_member', ext_community_member)
- resource_key = '/routing_policy/bgp_defined_set[{:s}][{:s}]'.format(
- bgp_ext_community_set['ext_community_set_name'], bgp_ext_community_set['ext_community_member'])
+ resource_key = get_resource_key('routing_policy_bgp_defined_set_member', device_type,
+ name=bgp_ext_community_set['ext_community_set_name'],
+ member=bgp_ext_community_set['ext_community_member'])
response.append((resource_key, copy.deepcopy(bgp_ext_community_set)))
return response
diff --git a/src/device/service/drivers/openconfig/templates/__init__.py b/src/device/service/drivers/openconfig/templates/__init__.py
index 47559efda07a08e9e56a980436d7dd1470556ecf..0f03f795cf6d36f3366ba814af9289063f6c9fe6 100644
--- a/src/device/service/drivers/openconfig/templates/__init__.py
+++ b/src/device/service/drivers/openconfig/templates/__init__.py
@@ -21,14 +21,7 @@ import paramiko
from .Tools import generate_templates
from device.service.driver_api._Driver import (
RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES, RESOURCE_ROUTING_POLICIES, RESOURCE_ACL, RESOURCE_INVENTORY)
-from .EndPoints import parse as parse_endpoints
-from .Interfaces import parse as parse_interfaces, parse_counters
-from .NetworkInstances import parse as parse_network_instances
-from .RoutingPolicy import parse as parse_routing_policy
-from .Acl import parse as parse_acl
-from .Inventory import parse as parse_inventory
-from .acl.acl_adapter import acl_cr_to_dict
-from .acl.acl_adapter_ipinfusion_proprietary import acl_cr_to_dict_ipinfusion_proprietary
+from inter_device_translation import get_dict_helper
LOGGER = logging.getLogger(__name__)
@@ -50,6 +43,46 @@ RESOURCE_KEY_MAPPINGS = {
RESOURCE_ACL : 'acl',
}
+RESOURCE_PARSERS = None # will be initialized after dependent imports
+
+LOGGER = logging.getLogger(__name__)
+RE_REMOVE_FILTERS = re.compile(r'\[[^\]]+\]')
+RE_REMOVE_FILTERS_2 = re.compile(r'\/[a-z]+:')
+EMPTY_CONFIG = ''
+EMPTY_FILTER = ''
+
+def get_dict_object(object_name: str, device_type: str, plural: bool = False) -> str:
+ dict_helper = get_dict_helper('oc' if device_type is None else device_type)
+ return dict_helper.get_object(object_name, plural=plural)
+
+def find_element(xml_element, element_name: str, device_type: str = None, namespaces: dict = None):
+ dict_helper = get_dict_helper(device_type)
+ namespace, path = dict_helper.get_element(element_name)
+
+ if namespaces is None:
+ namespaces = {}
+
+ return xml_element.find(f'{namespace}:{path}', namespaces=namespaces)
+
+def get_resource_key(resource_key_name: str, device_type: str = None, **kwargs) -> str:
+ dict_helper = get_dict_helper(device_type)
+ return dict_helper.get_resource_key(resource_key_name, **kwargs)
+
+# Create Jinja2 environment with custom filter
+JINJA_ENV = Environment(loader=PackageLoader('device.service.drivers.openconfig'), autoescape=select_autoescape())
+JINJA_ENV.filters['dict_object'] = get_dict_object
+
+
+
+from .EndPoints import parse as parse_endpoints
+from .Interfaces import parse as parse_interfaces, parse_counters
+from .NetworkInstances import parse as parse_network_instances
+from .RoutingPolicy import parse as parse_routing_policy
+from .Acl import parse as parse_acl
+from .Inventory import parse as parse_inventory
+from .acl.acl_adapter import acl_cr_to_dict
+from .acl.acl_adapter_ipinfusion_proprietary import acl_cr_to_dict_ipinfusion_proprietary
+
RESOURCE_PARSERS = {
'inventory' : parse_inventory,
'component' : parse_endpoints,
@@ -59,31 +92,23 @@ RESOURCE_PARSERS = {
'interfaces/interface/state/counters': parse_counters,
'acl' : parse_acl,
}
-
-LOGGER = logging.getLogger(__name__)
-RE_REMOVE_FILTERS = re.compile(r'\[[^\]]+\]')
-RE_REMOVE_FILTERS_2 = re.compile(r'\/[a-z]+:')
-EMPTY_CONFIG = ''
-EMPTY_FILTER = ''
-JINJA_ENV = Environment(loader=PackageLoader('device.service.drivers.openconfig'), autoescape=select_autoescape())
-
-def get_filter(resource_key : str):
+def get_filter(resource_key : str, device_type: str = None):
resource_key = RESOURCE_KEY_MAPPINGS.get(resource_key, resource_key)
resource_key = RE_REMOVE_FILTERS.sub('', resource_key)
resource_key = RE_REMOVE_FILTERS_2.sub('/', resource_key)
resource_key = resource_key.replace('//', '')
template_name = '{:s}/get.xml'.format(resource_key)
template = JINJA_ENV.get_template(template_name)
- return '{:s}'.format(template.render().strip())
+ return '{:s}'.format(template.render(device_type=device_type).strip())
-def parse(resource_key : str, xml_data : ET.Element):
+def parse(resource_key : str, xml_data : ET.Element, device_type : str = None):
resource_key = RESOURCE_KEY_MAPPINGS.get(resource_key, resource_key)
resource_key = RE_REMOVE_FILTERS.sub('', resource_key)
resource_key = RE_REMOVE_FILTERS_2.sub('/', resource_key)
resource_key = resource_key.replace('//', '')
parser = RESOURCE_PARSERS.get(resource_key)
if parser is None: return [(resource_key, xml_data)]
- return parser(xml_data)
+ return parser(xml_data, device_type)
"""
# Method Name: compose_config
@@ -104,7 +129,7 @@ def parse(resource_key : str, xml_data : ET.Element):
"""
def compose_config( # template generation
- resource_key : str, resource_value : str, delete : bool = False, vendor : Optional[str] = None, message_renderer = str
+ resource_key : str, resource_value : str, delete : bool = False, vendor : Optional[str] = None, message_renderer = str, device_type : Optional[str] = None
) -> str:
if (message_renderer == "pyangbind"):
@@ -146,7 +171,7 @@ def compose_config( # template generation
return [
'{:s}'.format(
- template.render(**data, operation=operation, vendor=vendor).strip())
+ template.render(**data, device_type=device_type, operation=operation, vendor=vendor).strip())
for template in templates
]
diff --git a/src/device/service/drivers/openconfig/templates/acl/interfaces/egress/edit_config.xml b/src/device/service/drivers/openconfig/templates/acl/interfaces/egress/edit_config.xml
index b070b305a505890c51f3751d2b83eb415ae4aa43..2679d5e9c0562bfa4ebd32862474674410832b7f 100644
--- a/src/device/service/drivers/openconfig/templates/acl/interfaces/egress/edit_config.xml
+++ b/src/device/service/drivers/openconfig/templates/acl/interfaces/egress/edit_config.xml
@@ -1,6 +1,6 @@
-
-
+ <{{ 'interfaces' | dict_object(device_type, plural=True) }}>
+ <{{ 'interfaces' | dict_object(device_type) {% if operation is defined %}{% if all is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %} {% endif %}>
{{id}}
{{id}}
@@ -8,7 +8,7 @@
{% if interface is defined %}
- {{interface}}
+ <{{ 'interfaces' | dict_object(device_type) }}>{{interface}}{{ 'interfaces' | dict_object(device_type) }}>
{% if subinterface is defined %}{{subinterface}}{% endif%}
@@ -25,6 +25,6 @@
{% endif%}
-
-
+ {{ 'interfaces' | dict_object(device_type) }}>
+ {{ 'interfaces' | dict_object(device_type, plural=True) }}>
diff --git a/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config.xml b/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config.xml
index d1f18efb26bc1316354c2bb26623cb36f7dc0be6..950f98b1c1b579bc6f44508a80331c44cc10f240 100644
--- a/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config.xml
+++ b/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config.xml
@@ -1,6 +1,6 @@
-
-
+ <{{ 'interfaces' | dict_object(device_type, plural=True) }}>
+ <{{ 'interfaces' | dict_object(device_type) {% if operation is defined %}{% if all is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %} {% endif %}>
{{id}}
{{id}}
@@ -8,7 +8,7 @@
{% if interface is defined %}
- {{interface}}
+ <{{ 'interfaces' | dict_object(device_type) }}>{{interface}}{{ 'interfaces' | dict_object(device_type) }}>
{% if subinterface is defined %}{{subinterface}}{% endif%}
@@ -25,6 +25,6 @@
{% endif%}
-
-
+ {{ 'interfaces' | dict_object(device_type) }}>
+ {{ 'interfaces' | dict_object(device_type, plural=True) }}>
diff --git a/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml b/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml
index 6e502154f16a7a9d4ce0afc0c49ab96b3a2bd979..a8efd9e33b5310673b51d141a063490b2fcae0e4 100644
--- a/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml
+++ b/src/device/service/drivers/openconfig/templates/acl/interfaces/ingress/edit_config_ipinfusion_proprietary.xml
@@ -1,6 +1,6 @@
-
-
+ <{{ 'interfaces' | dict_object(device_type, plural=True) }}>
+ <{{ 'interfaces' | dict_object(device_type) }}>
{{interface}}
{{interface}}
@@ -21,6 +21,6 @@
-
-
+ {{ 'interfaces' | dict_object(device_type) }}>
+ {{ 'interfaces' | dict_object(device_type, plural=True) }}>
\ No newline at end of file
diff --git a/src/device/service/drivers/openconfig/templates/component/get.xml b/src/device/service/drivers/openconfig/templates/component/get.xml
index aa25ed1e3b11e0c324b361eb52d064dac87a64c5..dd7cff27aea3f5da8bb19f35e26f221ea9d2aa45 100644
--- a/src/device/service/drivers/openconfig/templates/component/get.xml
+++ b/src/device/service/drivers/openconfig/templates/component/get.xml
@@ -1,3 +1,3 @@
-
-
-
+<{{ 'components' | dict_object(device_type, plural=True) }}>
+ <{{ 'components' | dict_object(device_type) }}/>
+{{ 'components' | dict_object(device_type, plural=True) }}>
\ No newline at end of file
diff --git a/src/device/service/drivers/openconfig/templates/interface/get.xml b/src/device/service/drivers/openconfig/templates/interface/get.xml
index c0867655bd325ee9c3cdd74077ac905e36808d5f..ab90a905dcdd16d9ec5a7b317069f6aa881f2c12 100644
--- a/src/device/service/drivers/openconfig/templates/interface/get.xml
+++ b/src/device/service/drivers/openconfig/templates/interface/get.xml
@@ -1,3 +1,3 @@
-
-
-
+<{{ 'interfaces' | dict_object(device_type, plural=True) }}>
+ <{{ 'interfaces' | dict_object(device_type) }}/>
+{{ 'interfaces' | dict_object(device_type, plural=True) }}>
\ No newline at end of file
diff --git a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml
index e926796d039d54e30f6ba13eb5eb66bcec079c08..cf6fae7e6f62e3e2a80fb2b09df4c1edd2efcec7 100644
--- a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml
+++ b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml
@@ -5,15 +5,15 @@
{{name}}
oc-ni-types:{{type}}
-
-
+ <{{ 'interfaces' | dict_object(device_type, plural=True) }}>
+ <{{ 'interfaces' | dict_object(device_type){% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
{{id}}
{{id}}
- {{interface}}
+ <{{ 'interfaces' | dict_object(device_type) }}>{{interface}}{{ 'interfaces' | dict_object(device_type) }}>
{{subinterface}}
-
-
+ {{ 'interfaces' | dict_object(device_type) }}>
+ {{ 'interfaces' | dict_object(device_type, plural=True) }}>
diff --git a/src/inter_device_translation/__init__.py b/src/inter_device_translation/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1a77c75bffc837668e4e5bce238712923ebf99c
--- /dev/null
+++ b/src/inter_device_translation/__init__.py
@@ -0,0 +1,121 @@
+import yaml
+import os
+
+
+# Get the directory where this module is located
+module_dir = os.path.dirname(os.path.abspath(__file__))
+config_path = os.path.join(module_dir, 'config', 'config.yml')
+
+with open(config_path) as cfg:
+ config : dict = yaml.safe_load(cfg)
+
+dict_name = config.get('name')
+dict_default = config.get('default')
+
+
+class DictHelper:
+ def __init__(self, file):
+ self.file = file
+
+ def _read(self) -> dict:
+ with open(self.file) as cfg:
+ return yaml.safe_load(cfg)
+
+ def get_object(self, name, plural=False) -> str:
+ config_data = self._read()
+ if name not in config_data.get('objects', {}):
+ raise KeyError(f"Object '{name}' not found in configuration")
+ return config_data['objects'][name].get('plural' if plural else 'singular')
+
+ def get_namespaces(self, name) -> str:
+ return self._read().get('namespaces', {}).get(name)
+
+ def get_path(self, key, **kwargs) -> str:
+ path_details = self._read().get('paths', {}).get(key)
+ if not path_details:
+ raise KeyError(f"Path '{key}' not found in configuration")
+
+ path : str = path_details.get('path')
+ namespace = path_details.get('namespace')
+
+ # Format the path with provided parameters
+ if kwargs:
+ path = path.format(**kwargs)
+
+ if namespace is None:
+ return path
+
+ path_segments = path.split('/')
+ # Only segments without explicit namespace prefixes require one
+ segments_requiring_ns = [s for s in path_segments if len(s) > 1 and ':' not in s]
+
+ if isinstance(namespace, list):
+ if len(namespace) != len(segments_requiring_ns):
+ raise Exception(f'Number of namespaces do not match the specified path : {path}')
+ namespace_list = namespace
+ elif isinstance(namespace, str):
+ namespace_list = [namespace for _ in range(len(segments_requiring_ns))]
+ else:
+ namespace_list = []
+
+ ns_i = 0
+ processed_segments = []
+ for s in path_segments:
+ if len(s) > 1:
+ if ':' in s:
+ # Segment already includes a namespace prefix; leave as is
+ processed_segments.append(s)
+ else:
+ ns = namespace_list[ns_i] if ns_i < len(namespace_list) else None
+ processed_segments.append(f'{ns}:{s}' if ns else s)
+ ns_i += 1
+ else:
+ processed_segments.append(s)
+
+ return '/'.join(processed_segments)
+
+ def get_element(self, name):
+ """
+ Get element namespace and path for XML element lookups.
+
+ Args:
+ name: The name of the element to look up
+
+ Returns:
+ Tuple of (namespace, path) for the element
+ """
+ element_details = self._read().get('elements', {}).get(name)
+ if not element_details:
+ raise KeyError(f"Element '{name}' not found in configuration")
+
+ namespace = element_details.get('namespace')
+ path = element_details.get('path')
+
+ return namespace, path
+
+ def get_resource_key(self, key, **kwargs) -> str:
+ """
+ Get device-specific resource key path.
+
+ Args:
+ name: The resource key name to look up
+ **kwargs: Parameters to format into the resource key path
+
+ Returns:
+ Formatted resource key path
+ """
+ resource_key_details = self._read().get('resource_keys', {}).get(key)
+ if not resource_key_details:
+ raise KeyError(f"Resource key '{key}' not found in configuration")
+
+ path = resource_key_details.get('path')
+ if kwargs:
+ path = path.format(**kwargs)
+
+ return path
+
+
+def get_dict_helper(dict_type = None) -> DictHelper:
+ if dict_type is None: dict_type = dict_default
+ config_file = os.path.join(module_dir, 'config', f'{dict_name}.{dict_type}.yml')
+ return DictHelper(config_file)
\ No newline at end of file
diff --git a/src/inter_device_translation/config/config.yml b/src/inter_device_translation/config/config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..37f7fb1fe36346ab0986897b017a30f65bcde803
--- /dev/null
+++ b/src/inter_device_translation/config/config.yml
@@ -0,0 +1,2 @@
+name: dict
+default: oc
\ No newline at end of file
diff --git a/src/inter_device_translation/config/dict.ipi.yml b/src/inter_device_translation/config/dict.ipi.yml
new file mode 100644
index 0000000000000000000000000000000000000000..654e78294875f1830dc8feb9295023953cc15765
--- /dev/null
+++ b/src/inter_device_translation/config/dict.ipi.yml
@@ -0,0 +1,460 @@
+namespaces:
+ interfaces: ipii
+ interfaces_ip: ipiiip
+
+objects:
+ components:
+ singular: interface
+ plural: interfaces
+ interfaces:
+ singular: interface
+ plural: interfaces
+
+paths:
+ component_type:
+ namespace: ipiie
+ path: extended/state/hardware-type
+ ports:
+ namespace: ipii
+ path: interfaces/interface
+ components:
+ namespace: ipii
+ path: interfaces/interface
+ interface_counters:
+ namespace: ipii
+ path: interfaces/interface[name='{interface_name}']/state/counters/{counter_name}
+ interfaces:
+ namespace: ipii
+ path: interfaces/interface
+ subinterfaces:
+ namespace: ipii
+ path: subinterfaces/subinterface
+ ipv4_addresses:
+ namespace: ipiiip
+ path: ipv4/addresses/address
+ ipv6_addresses:
+ namespace: ipiiip
+ path: ipv6/addresses/address
+ acl_set:
+ namespace: ipiacl
+ path: acl/acl-sets/acl-set
+ acl_entry:
+ namespace: ipiacl
+ path: acl-entries/acl-entry
+ acl_ipv4:
+ namespace: ipiacl
+ path: ipv4/config
+ acl_transport:
+ namespace: ipiacl
+ path: transport/config
+ acl_actions:
+ namespace: ipiacl
+ path: actions/config
+ acl_interface:
+ namespace: ipiacl
+ path: acl/interfaces/interface
+ acl_ingress:
+ namespace: ipiacl
+ path: ingress-acl-sets/ingress-acl-set
+ acl_egress:
+ namespace: ipiacl
+ path: egress-acl-sets/egress-acl-set
+ network_instances:
+ namespace: ipini
+ path: network-instances/network-instance
+ ni_protocols:
+ namespace: ipini
+ path: protocols/protocol
+ ni_table_connections:
+ namespace: ipini
+ path: table-connections/table-connection
+ ni_interface:
+ namespace: ipini
+ path: interfaces/interface
+ ni_apply_policy:
+ namespace: ipini
+ path: inter-instance-policies/apply-policy
+ ni_import_policy:
+ namespace: ipini
+ path: config/import-policy
+ ni_export_policy:
+ namespace: ipini
+ path: config/export-policy
+ ni_connection_points:
+ namespace: ipini
+ path: connection-points/connection-point
+ ni_endpoints:
+ namespace: ipini
+ path: endpoints/endpoint/remote/config
+ routing_policy_definitions:
+ namespace: ipirp
+ path: routing-policy/policy-definitions/policy-definition
+ pd_statements:
+ namespace: ipirp
+ path: statements/statement
+ pd_conditions:
+ namespace: ipirp
+ path: conditions/ipibp:bgp-conditions/ipibp:match-ext-community-set
+ pd_actions:
+ namespace: ipirp
+ path: actions
+ bgp_ext_community_set:
+ namespace: ipirp
+ path: routing-policy/defined-sets/ipibp:bgp-defined-sets/ipibp:ext-community-sets/ipibp:ext-community-set
+ interface_counters_path:
+ namespace: ipii
+ path: /ipinfusion-interfaces:interfaces/interface/state/counters
+ network_instance_interfaces:
+ namespace: ipini
+ path: /ipinfusion-network-instance:network-instances/network-instance[name={name}]/interfaces
+ network_instance_protocols:
+ namespace: ipini
+ path: /ipinfusion-network-instance:network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]
+ network_instance_static_routes:
+ namespace: ipini
+ path: /ipinfusion-network-instance:network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]/static-routes/static[prefix={prefix}]
+ network_instance_interface:
+ namespace: ipini
+ path: /ipinfusion-network-instances/network-instance[name={name}]/interfaces/interface[id={interface_id}]
+ network_instance_protocol:
+ namespace: ipini
+ path: /ipinfusion-network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]
+ network_instance_static_route:
+ namespace: ipini
+ path: /ipinfusion-network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]/static-routes/static[prefix={prefix}]
+ interface_subinterface:
+ namespace: ipii
+ path: /ipinfusion-interfaces/interface[name={name}]/subinterfaces/subinterface[index={index}]
+
+elements:
+ interface_name:
+ namespace: ipii
+ path: name
+ interface_type:
+ namespace: ipii
+ path: config/type
+ interface_state_type:
+ namespace: ipii
+ path: state/type
+ interface_mtu:
+ namespace: ipii
+ path: config/mtu
+ interface_description:
+ namespace: ipii
+ path: config/description
+ interface_counters_in_pkts:
+ namespace: ipii
+ path: state/counters/in-pkts
+ interface_counters_in_octets:
+ namespace: ipii
+ path: state/counters/in-octets
+ interface_counters_in_errors:
+ namespace: ipii
+ path: state/counters/in-errors
+ interface_counters_out_octets:
+ namespace: ipii
+ path: state/counters/out-octets
+ interface_counters_out_pkts:
+ namespace: ipii
+ path: state/counters/out-pkts
+ interface_counters_out_errors:
+ namespace: ipii
+ path: state/counters/out-errors
+ interface_counters_out_discards:
+ namespace: ipii
+ path: state/counters/out-discards
+ subinterface_index:
+ namespace: ipii
+ path: index
+ subinterface_vlan:
+ namespace: ipiv
+ path: vlan/match/single-tagged/config/vlan-id
+ ipv4_address:
+ namespace: ipiiip
+ path: state/ip
+ ipv4_prefix:
+ namespace: ipiiip
+ path: state/prefix-length
+ ipv6_address:
+ namespace: ipiiip
+ path: state/ip
+ ipv6_prefix:
+ namespace: ipiiip
+ path: state/prefix-length
+ component_name:
+ namespace: ipii
+ path: name
+ component_type:
+ namespace: ipii
+ path: state/type
+ component_description:
+ namespace: ipii
+ path: state/description
+ component_location:
+ namespace: ipii
+ path: state/location
+ component_id:
+ namespace: ipii
+ path: state/id
+ component_empty:
+ namespace: ipii
+ path: state/empty
+ component_parent:
+ namespace: ipii
+ path: state/parent
+ component_hardware_version:
+ namespace: ipii
+ path: state/hardware-version
+ component_firmware_version:
+ namespace: ipii
+ path: state/firmware-version
+ component_software_version:
+ namespace: ipii
+ path: state/software-version
+ component_serial:
+ namespace: ipii
+ path: state/serial-no
+ component_mfg_name:
+ namespace: ipii
+ path: state/mfg-name
+ component_model_name:
+ namespace: ipii
+ path: state/model-name
+ component_part_no:
+ namespace: ipii
+ path: state/part-no
+ component_removable:
+ namespace: ipii
+ path: state/removable
+ component_replaceable:
+ namespace: ipii
+ path: state/replaceable
+ component_oper_status:
+ namespace: ipii
+ path: state/oper-status
+ acl_name:
+ namespace: ipiacl
+ path: name
+ acl_type:
+ namespace: ipiacl
+ path: type
+ acl_sequence_id:
+ namespace: ipiacl
+ path: sequence-id
+ acl_source_address:
+ namespace: ipiacl
+ path: source-address
+ acl_destination_address:
+ namespace: ipiacl
+ path: destination-address
+ acl_protocol:
+ namespace: ipiacl
+ path: protocol
+ acl_dscp:
+ namespace: ipiacl
+ path: dscp
+ acl_hop_limit:
+ namespace: ipiacl
+ path: hop-limit
+ acl_source_port:
+ namespace: ipiacl
+ path: source-port
+ acl_destination_port:
+ namespace: ipiacl
+ path: destination-port
+ acl_tcp_flags:
+ namespace: ipiacl
+ path: tcp-flags
+ acl_forwarding_action:
+ namespace: ipiacl
+ path: forwarding-action
+ acl_log_action:
+ namespace: ipiacl
+ path: log-action
+ acl_interface_id:
+ namespace: ipiacl
+ path: id
+ acl_set_name_ingress:
+ namespace: ipiacl
+ path: set-name-ingress
+ acl_type_ingress:
+ namespace: ipiacl
+ path: type-ingress
+ acl_set_name_egress:
+ namespace: ipiacl
+ path: set-name-egress
+ acl_type_egress:
+ namespace: ipiacl
+ path: type-egress
+ ni_name:
+ namespace: ipini
+ path: name
+ ni_type:
+ namespace: ipini
+ path: config/type
+ ni_router_id:
+ namespace: ipini
+ path: config/router-id
+ ni_route_distinguisher:
+ namespace: ipini
+ path: config/route-distinguisher
+ ni_connection_point_id:
+ namespace: ipini
+ path: connection-point-id
+ ni_remote_system:
+ namespace: ipini
+ path: remote-system
+ ni_virtual_circuit_identifier:
+ namespace: ipini
+ path: virtual-circuit-identifier
+ ni_protocol_identifier:
+ namespace: ipini
+ path: identifier
+ ni_protocol_name:
+ namespace: ipini
+ path: name
+ ni_bgp_as:
+ namespace: ipini
+ path: bgp/global/config/as
+ ni_bgp_router_id:
+ namespace: ipini
+ path: bgp/global/config/router-id
+ ni_src_protocol:
+ namespace: ipini
+ path: src-protocol
+ ni_dst_protocol:
+ namespace: ipini
+ path: dst-protocol
+ ni_address_family:
+ namespace: ipini
+ path: address-family
+ ni_default_import_policy:
+ namespace: ipini
+ path: config/default-import-policy
+ ni_interface_name:
+ namespace: ipini
+ path: config/interface
+ ni_subinterface_name:
+ namespace: ipini
+ path: config/subinterface
+ rp_policy_name:
+ namespace: ipirp
+ path: name
+ rp_statement_name:
+ namespace: ipirp
+ path: name
+ rp_ext_community_set:
+ namespace: ipibp
+ path: config/ext-community-set
+ rp_match_set_options:
+ namespace: ipibp
+ path: config/match-set-options
+ rp_policy_result:
+ namespace: ipibp
+ path: config/policy-result
+ rp_ext_community_set_name:
+ namespace: ipibp
+ path: ext-community-set-name
+ rp_ext_community_member:
+ namespace: ipibp
+ path: config/ext-community-member
+ inv_component_name:
+ namespace: ipii
+ path: name
+ inv_component_description:
+ namespace: ipii
+ path: state/description
+ inv_component_location:
+ namespace: ipii
+ path: state/location
+ inv_component_id:
+ namespace: ipii
+ path: state/id
+ inv_component_type:
+ namespace: ipii
+ path: state/type
+ inv_component_empty:
+ namespace: ipii
+ path: state/empty
+ inv_component_parent:
+ namespace: ipii
+ path: state/parent
+ inv_component_hardware_version:
+ namespace: ipii
+ path: state/hardware-version
+ inv_component_firmware_version:
+ namespace: ipii
+ path: state/firmware-version
+ inv_component_software_version:
+ namespace: ipii
+ path: state/software-version
+ inv_component_serial:
+ namespace: ipii
+ path: state/serial-no
+ inv_component_mfg_name:
+ namespace: ipii
+ path: state/mfg-name
+ inv_component_removable:
+ namespace: ipii
+ path: state/removable
+ inv_component_mfg_date:
+ namespace: ipii
+ path: state/mfg-date
+ inv_transceiver_serial:
+ namespace: ipitr
+ path: transceiver/state/serial-no
+ inv_transceiver_present:
+ namespace: ipitr
+ path: transceiver/state/present
+ inv_transceiver_vendor:
+ namespace: ipitr
+ path: transceiver/state/vendor
+ inv_transceiver_connector:
+ namespace: ipitr
+ path: transceiver/state/connector-type
+ inv_transceiver_form:
+ namespace: ipitr
+ path: transceiver/state/form-factor
+ ep_component_type:
+ namespace: ipii
+ path: state/type
+ ep_component_name:
+ namespace: ipii
+ path: name
+ ep_port_channel_speed:
+ namespace: ipipp
+ path: port/breakout-mode/state/channel-speed
+
+resource_keys:
+ network_instance:
+ path: /network_instance[{name}]
+ network_instance_protocols:
+ path: /network_instance[{name}]/protocols[{identifier}]
+ network_instance_table_connections:
+ path: /network_instance[{name}]/table_connections[{src_protocol}][{dst_protocol}][{address_family}]
+ network_instance_interface:
+ path: /network_instance[{name}]/interface[{interface_name}]
+ network_instance_inter_instance_policies:
+ path: /network_instance[{name}]/inter_instance_policies[{policy_name}]
+ acl_set_entry:
+ path: /acl/acl-set[{name}][{type}]/acl-entry[{sequence_id}]
+ acl_interfaces_ingress:
+ path: /acl/interfaces/ingress[{name}][{type}]
+ acl_interfaces_egress:
+ path: /acl/interfaces/egress[{name}][{type}]
+ interface_subinterface:
+ path: /interface[{name}]/subinterface[{index}]
+ routing_policy_definition:
+ path: /routing_policy/policy_definition[{name}]
+ routing_policy_statement:
+ path: /routing_policy/policy_definition[{name}]/statement[{statement_name}]
+ routing_policy_bgp_defined_set:
+ path: /routing_policy/bgp_defined_set[{name}]
+ routing_policy_bgp_defined_set_member:
+ path: /routing_policy/bgp_defined_set[{name}][{member}]
+ inventory_component:
+ path: /inventory[{name}]
+ endpoints_endpoint:
+ path: /endpoints/endpoint[{uuid}]
+ interface:
+ path: /interface[{name}]
\ No newline at end of file
diff --git a/src/inter_device_translation/config/dict.oc.yml b/src/inter_device_translation/config/dict.oc.yml
new file mode 100644
index 0000000000000000000000000000000000000000..48e2fc250f634f91cf26b567751fab1755d86639
--- /dev/null
+++ b/src/inter_device_translation/config/dict.oc.yml
@@ -0,0 +1,460 @@
+namespaces:
+ interfaces: oci
+ interfaces_ip: ociip
+
+objects:
+ components:
+ singular: component
+ plural: components
+ interfaces:
+ singular: interface
+ plural: interfaces
+
+paths:
+ component_type:
+ namespace: ocpp
+ path: port/breakout-mode/state/channel-speed
+ ports:
+ namespace: ocp
+ path: components/component
+ components:
+ namespace: ocp
+ path: components/component
+ interface_counters:
+ namespace: oci
+ path: interfaces/interface[name='{interface_name}']/state/counters/{counter_name}
+ interfaces:
+ namespace: oci
+ path: interfaces/interface
+ subinterfaces:
+ namespace: oci
+ path: subinterfaces/subinterface
+ ipv4_addresses:
+ namespace: ociip
+ path: ipv4/addresses/address
+ ipv6_addresses:
+ namespace: ociip
+ path: ipv6/addresses/address
+ acl_set:
+ namespace: ocacl
+ path: acl/acl-sets/acl-set
+ acl_entry:
+ namespace: ocacl
+ path: acl-entries/acl-entry
+ acl_ipv4:
+ namespace: ocacl
+ path: ipv4/config
+ acl_transport:
+ namespace: ocacl
+ path: transport/config
+ acl_actions:
+ namespace: ocacl
+ path: actions/config
+ acl_interface:
+ namespace: ocacl
+ path: acl/interfaces/interface
+ acl_ingress:
+ namespace: ocacl
+ path: ingress-acl-sets/ingress-acl-set
+ acl_egress:
+ namespace: ocacl
+ path: egress-acl-sets/egress-acl-set
+ network_instances:
+ namespace: ocni
+ path: network-instances/network-instance
+ ni_protocols:
+ namespace: ocni
+ path: protocols/protocol
+ ni_table_connections:
+ namespace: ocni
+ path: table-connections/table-connection
+ ni_interface:
+ namespace: ocni
+ path: interfaces/interface
+ ni_apply_policy:
+ namespace: ocni
+ path: inter-instance-policies/apply-policy
+ ni_import_policy:
+ namespace: ocni
+ path: config/import-policy
+ ni_export_policy:
+ namespace: ocni
+ path: config/export-policy
+ ni_connection_points:
+ namespace: ocni
+ path: connection-points/connection-point
+ ni_endpoints:
+ namespace: ocni
+ path: endpoints/endpoint/remote/config
+ routing_policy_definitions:
+ namespace: ocrp
+ path: routing-policy/policy-definitions/policy-definition
+ pd_statements:
+ namespace: ocrp
+ path: statements/statement
+ pd_conditions:
+ namespace: ocrp
+ path: conditions/ocbp:bgp-conditions/ocbp:match-ext-community-set
+ pd_actions:
+ namespace: ocrp
+ path: actions
+ bgp_ext_community_set:
+ namespace: ocrp
+ path: routing-policy/defined-sets/ocbp:bgp-defined-sets/ocbp:ext-community-sets/ocbp:ext-community-set
+ interface_counters_path:
+ namespace: oci
+ path: /openconfig-interfaces:interfaces/interface/state/counters
+ network_instance_interfaces:
+ namespace: ocni
+ path: /openconfig-network-instance:network-instances/network-instance[name={name}]/interfaces
+ network_instance_protocols:
+ namespace: ocni
+ path: /openconfig-network-instance:network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]
+ network_instance_static_routes:
+ namespace: ocni
+ path: /openconfig-network-instance:network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]/static-routes/static[prefix={prefix}]
+ network_instance_interface:
+ namespace: ocni
+ path: /network-instances/network-instance[name={name}]/interfaces/interface[id={interface_id}]
+ network_instance_protocol:
+ namespace: ocni
+ path: /network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]
+ network_instance_static_route:
+ namespace: ocni
+ path: /network-instances/network-instance[name={name}]/protocols/protocol[identifier={identifier}][name={protocol_name}]/static-routes/static[prefix={prefix}]
+ interface_subinterface:
+ namespace: oci
+ path: /interfaces/interface[name={name}]/subinterfaces/subinterface[index={index}]
+
+elements:
+ interface_name:
+ namespace: oci
+ path: name
+ interface_type:
+ namespace: oci
+ path: config/type
+ interface_state_type:
+ namespace: oci
+ path: state/type
+ interface_mtu:
+ namespace: oci
+ path: config/mtu
+ interface_description:
+ namespace: oci
+ path: config/description
+ interface_counters_in_pkts:
+ namespace: oci
+ path: state/counters/in-pkts
+ interface_counters_in_octets:
+ namespace: oci
+ path: state/counters/in-octets
+ interface_counters_in_errors:
+ namespace: oci
+ path: state/counters/in-errors
+ interface_counters_out_octets:
+ namespace: oci
+ path: state/counters/out-octets
+ interface_counters_out_pkts:
+ namespace: oci
+ path: state/counters/out-pkts
+ interface_counters_out_errors:
+ namespace: oci
+ path: state/counters/out-errors
+ interface_counters_out_discards:
+ namespace: oci
+ path: state/counters/out-discards
+ subinterface_index:
+ namespace: oci
+ path: index
+ subinterface_vlan:
+ namespace: ocv
+ path: vlan/match/single-tagged/config/vlan-id
+ ipv4_address:
+ namespace: ociip
+ path: state/ip
+ ipv4_prefix:
+ namespace: ociip
+ path: state/prefix-length
+ ipv6_address:
+ namespace: ociip
+ path: state/ip
+ ipv6_prefix:
+ namespace: ociip
+ path: state/prefix-length
+ component_name:
+ namespace: ocp
+ path: name
+ component_type:
+ namespace: ocp
+ path: state/type
+ component_description:
+ namespace: ocp
+ path: state/description
+ component_location:
+ namespace: ocp
+ path: state/location
+ component_id:
+ namespace: ocp
+ path: state/id
+ component_empty:
+ namespace: ocp
+ path: state/empty
+ component_parent:
+ namespace: ocp
+ path: state/parent
+ component_hardware_version:
+ namespace: ocp
+ path: state/hardware-version
+ component_firmware_version:
+ namespace: ocp
+ path: state/firmware-version
+ component_software_version:
+ namespace: ocp
+ path: state/software-version
+ component_serial:
+ namespace: ocp
+ path: state/serial-no
+ component_mfg_name:
+ namespace: ocp
+ path: state/mfg-name
+ component_model_name:
+ namespace: ocp
+ path: state/model-name
+ component_part_no:
+ namespace: ocp
+ path: state/part-no
+ component_removable:
+ namespace: ocp
+ path: state/removable
+ component_replaceable:
+ namespace: ocp
+ path: state/replaceable
+ component_oper_status:
+ namespace: ocp
+ path: state/oper-status
+ acl_name:
+ namespace: ocacl
+ path: name
+ acl_type:
+ namespace: ocacl
+ path: type
+ acl_sequence_id:
+ namespace: ocacl
+ path: sequence-id
+ acl_source_address:
+ namespace: ocacl
+ path: source-address
+ acl_destination_address:
+ namespace: ocacl
+ path: destination-address
+ acl_protocol:
+ namespace: ocacl
+ path: protocol
+ acl_dscp:
+ namespace: ocacl
+ path: dscp
+ acl_hop_limit:
+ namespace: ocacl
+ path: hop-limit
+ acl_source_port:
+ namespace: ocacl
+ path: source-port
+ acl_destination_port:
+ namespace: ocacl
+ path: destination-port
+ acl_tcp_flags:
+ namespace: ocacl
+ path: tcp-flags
+ acl_forwarding_action:
+ namespace: ocacl
+ path: forwarding-action
+ acl_log_action:
+ namespace: ocacl
+ path: log-action
+ acl_interface_id:
+ namespace: ocacl
+ path: id
+ acl_set_name_ingress:
+ namespace: ocacl
+ path: set-name-ingress
+ acl_type_ingress:
+ namespace: ocacl
+ path: type-ingress
+ acl_set_name_egress:
+ namespace: ocacl
+ path: set-name-egress
+ acl_type_egress:
+ namespace: ocacl
+ path: type-egress
+ ni_name:
+ namespace: ocni
+ path: name
+ ni_type:
+ namespace: ocni
+ path: config/type
+ ni_router_id:
+ namespace: ocni
+ path: config/router-id
+ ni_route_distinguisher:
+ namespace: ocni
+ path: config/route-distinguisher
+ ni_connection_point_id:
+ namespace: ocni
+ path: connection-point-id
+ ni_remote_system:
+ namespace: ocni
+ path: remote-system
+ ni_virtual_circuit_identifier:
+ namespace: ocni
+ path: virtual-circuit-identifier
+ ni_protocol_identifier:
+ namespace: ocni
+ path: identifier
+ ni_protocol_name:
+ namespace: ocni
+ path: name
+ ni_bgp_as:
+ namespace: ocni
+ path: bgp/global/config/as
+ ni_bgp_router_id:
+ namespace: ocni
+ path: bgp/global/config/router-id
+ ni_src_protocol:
+ namespace: ocni
+ path: src-protocol
+ ni_dst_protocol:
+ namespace: ocni
+ path: dst-protocol
+ ni_address_family:
+ namespace: ocni
+ path: address-family
+ ni_default_import_policy:
+ namespace: ocni
+ path: config/default-import-policy
+ ni_interface_name:
+ namespace: ocni
+ path: config/interface
+ ni_subinterface_name:
+ namespace: ocni
+ path: config/subinterface
+ rp_policy_name:
+ namespace: ocrp
+ path: name
+ rp_statement_name:
+ namespace: ocrp
+ path: name
+ rp_ext_community_set:
+ namespace: ocbp
+ path: config/ext-community-set
+ rp_match_set_options:
+ namespace: ocbp
+ path: config/match-set-options
+ rp_policy_result:
+ namespace: ocbp
+ path: config/policy-result
+ rp_ext_community_set_name:
+ namespace: ocbp
+ path: ext-community-set-name
+ rp_ext_community_member:
+ namespace: ocbp
+ path: config/ext-community-member
+ inv_component_name:
+ namespace: ocp
+ path: name
+ inv_component_description:
+ namespace: ocp
+ path: state/description
+ inv_component_location:
+ namespace: ocp
+ path: state/location
+ inv_component_id:
+ namespace: ocp
+ path: state/id
+ inv_component_type:
+ namespace: ocp
+ path: state/type
+ inv_component_empty:
+ namespace: ocp
+ path: state/empty
+ inv_component_parent:
+ namespace: ocp
+ path: state/parent
+ inv_component_hardware_version:
+ namespace: ocp
+ path: state/hardware-version
+ inv_component_firmware_version:
+ namespace: ocp
+ path: state/firmware-version
+ inv_component_software_version:
+ namespace: ocp
+ path: state/software-version
+ inv_component_serial:
+ namespace: ocp
+ path: state/serial-no
+ inv_component_mfg_name:
+ namespace: ocp
+ path: state/mfg-name
+ inv_component_removable:
+ namespace: ocp
+ path: state/removable
+ inv_component_mfg_date:
+ namespace: ocp
+ path: state/mfg-date
+ inv_transceiver_serial:
+ namespace: ocptr
+ path: transceiver/state/serial-no
+ inv_transceiver_present:
+ namespace: ocptr
+ path: transceiver/state/present
+ inv_transceiver_vendor:
+ namespace: ocptr
+ path: transceiver/state/vendor
+ inv_transceiver_connector:
+ namespace: ocptr
+ path: transceiver/state/connector-type
+ inv_transceiver_form:
+ namespace: ocptr
+ path: transceiver/state/form-factor
+ ep_component_type:
+ namespace: ocp
+ path: state/type
+ ep_component_name:
+ namespace: ocp
+ path: name
+ ep_port_channel_speed:
+ namespace: ocpp
+ path: port/breakout-mode/state/channel-speed
+
+resource_keys:
+ network_instance:
+ path: /network_instance[{name}]
+ network_instance_protocols:
+ path: /network_instance[{name}]/protocols[{identifier}]
+ network_instance_table_connections:
+ path: /network_instance[{name}]/table_connections[{src_protocol}][{dst_protocol}][{address_family}]
+ network_instance_interface:
+ path: /network_instance[{name}]/interface[{interface_name}]
+ network_instance_inter_instance_policies:
+ path: /network_instance[{name}]/inter_instance_policies[{policy_name}]
+ acl_set_entry:
+ path: /acl/acl-set[{name}][{type}]/acl-entry[{sequence_id}]
+ acl_interfaces_ingress:
+ path: /acl/interfaces/ingress[{name}][{type}]
+ acl_interfaces_egress:
+ path: /acl/interfaces/egress[{name}][{type}]
+ interface_subinterface:
+ path: /interface[{name}]/subinterface[{index}]
+ routing_policy_definition:
+ path: /routing_policy/policy_definition[{name}]
+ routing_policy_statement:
+ path: /routing_policy/policy_definition[{name}]/statement[{statement_name}]
+ routing_policy_bgp_defined_set:
+ path: /routing_policy/bgp_defined_set[{name}]
+ routing_policy_bgp_defined_set_member:
+ path: /routing_policy/bgp_defined_set[{name}][{member}]
+ inventory_component:
+ path: /inventory[{name}]
+ endpoints_endpoint:
+ path: /endpoints/endpoint[{uuid}]
+ interface:
+ path: /interface[{name}]
\ No newline at end of file
diff --git a/src/load_generator/requirements.in b/src/load_generator/requirements.in
index a2ee41d8317c5146977ef173654b823f476d2237..72a3d081a866a54fa48f175a8c91994bcea4e7f8 100644
--- a/src/load_generator/requirements.in
+++ b/src/load_generator/requirements.in
@@ -13,3 +13,4 @@
# limitations under the License.
APScheduler>=3.10.4
+pytz