Loading src/device/service/drivers/ietf_actn/IetfActnDriver.py +12 −16 Original line number Diff line number Diff line Loading @@ -21,19 +21,22 @@ from device.service.driver_api._Driver import _Driver, RESOURCE_ENDPOINTS, RESOU from .handlers.EthtServiceHandler import EthtServiceHandler from .handlers.OsuTunnelHandler import OsuTunnelHandler from .handlers.NetworkTopologyHandler import NetworkTopologyHandler from .handlers.RestApiClient import RestApiClient from .Tools import get_etht_services, get_osu_tunnels, parse_resource_key LOGGER = logging.getLogger(__name__) ALL_RESOURCE_KEYS = [ RESOURCE_ENDPOINTS, RESOURCE_SERVICES, ] DRIVER_NAME = 'ietf_actn' METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': DRIVER_NAME}) class IetfActnDriver(_Driver): def __init__(self, address: str, port: int, **settings) -> None: super().__init__(DRIVER_NAME, address, port, **settings) Loading @@ -41,23 +44,20 @@ class IetfActnDriver(_Driver): self.__started = threading.Event() self.__terminate = threading.Event() self._rest_api_client = RestApiClient(address, port, settings=settings) restconf_settings = copy.deepcopy(settings) restconf_settings.pop('base_url', None) restconf_settings.pop('import_topology', None) restconf_settings['logger'] = logging.getLogger(__name__ + '.RestConfClient') self._rest_conf_client = RestConfClient(address, port=port, **restconf_settings) self._handler_etht_service = EthtServiceHandler(self._rest_api_client) self._handler_etht_service = EthtServiceHandler(self._rest_conf_client) self._handler_net_topology = NetworkTopologyHandler(self._rest_conf_client, **settings) self._handler_osu_tunnel = OsuTunnelHandler(self._rest_api_client) self._handler_osu_tunnel = OsuTunnelHandler(self._rest_conf_client) def Connect(self) -> bool: with self.__lock: if self.__started.is_set(): return True try: self._rest_api_client.get('Check Credentials', '') self._rest_conf_client._discover_base_url() except requests.exceptions.Timeout: LOGGER.exception('Timeout exception checking connectivity') return False Loading @@ -81,15 +81,13 @@ class IetfActnDriver(_Driver): @metered_subclass_method(METRICS_POOL) def GetConfig(self, resource_keys : List[str] = []) -> List[Tuple[str, Union[Any, None, Exception]]]: chk_type('resources', resource_keys, list) results = [] results = list() with self.__lock: if len(resource_keys) == 0: resource_keys = ALL_RESOURCE_KEYS for i, resource_key in enumerate(resource_keys): chk_string('resource_key[#{:d}]'.format(i), resource_key, allow_empty=False) try: _results = list() if resource_key == RESOURCE_ENDPOINTS: # Add mgmt endpoint by default #resource_key = '/endpoints/endpoint[mgmt]' Loading @@ -97,17 +95,15 @@ class IetfActnDriver(_Driver): #results.append((resource_key, resource_value)) results.extend(self._handler_net_topology.get()) elif resource_key == RESOURCE_SERVICES: get_osu_tunnels(self._handler_osu_tunnel, _results) get_etht_services(self._handler_etht_service, _results) get_osu_tunnels(self._handler_osu_tunnel, results) get_etht_services(self._handler_etht_service, results) else: # check if resource key is for a specific OSU tunnel or ETHT service, and get them accordingly osu_tunnel_name, etht_service_name = parse_resource_key(resource_key) if osu_tunnel_name is not None: get_osu_tunnels(self._handler_osu_tunnel, _results, osu_tunnel_name=osu_tunnel_name) get_osu_tunnels(self._handler_osu_tunnel, results, osu_tunnel_name=osu_tunnel_name) if etht_service_name is not None: get_etht_services(self._handler_etht_service, _results, etht_service_name=etht_service_name) results.extend(_results) get_etht_services(self._handler_etht_service, results, etht_service_name=etht_service_name) except Exception as e: MSG = 'Error processing resource_key: {:s}' LOGGER.exception(MSG.format(str(resource_key))) Loading src/device/service/drivers/ietf_actn/handlers/EthtServiceHandler.py +16 −27 Original line number Diff line number Diff line Loading @@ -14,10 +14,12 @@ import enum, logging from typing import Dict, List, Optional, Tuple, Union from .RestApiClient import HTTP_STATUS_CREATED, HTTP_STATUS_NO_CONTENT, HTTP_STATUS_OK, RestApiClient from common.tools.client.RestConfClient import RestConfClient LOGGER = logging.getLogger(__name__) class BandwidthProfileTypeEnum(enum.Enum): MEF_10_BWP = 'ietf-eth-tran-types:mef-10-bwp' Loading Loading @@ -106,36 +108,20 @@ def compose_etht_service( 'optimizations': compose_optimizations(), }]}} class EthtServiceHandler: def __init__(self, rest_api_client : RestApiClient) -> None: self._rest_api_client = rest_api_client self._object_name = 'EthtService' def __init__(self, rest_conf_client : RestConfClient) -> None: self._rest_conf_client = rest_conf_client self._subpath_root = '/ietf-eth-tran-service:etht-svc' self._subpath_item = self._subpath_root + '/etht-svc-instances="{etht_service_name:s}"' self._subpath_item = self._subpath_root + '/etht-svc-instances={etht_service_name:s}' def _rest_api_get(self, etht_service_name : Optional[str] = None) -> Union[Dict, List]: def get(self, etht_service_name : Optional[str] = None) -> Union[Dict, List]: if etht_service_name is None: subpath_url = self._subpath_root else: subpath_url = self._subpath_item.format(etht_service_name=etht_service_name) return self._rest_api_client.get( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_OK} ) def _rest_api_update(self, data : Dict) -> bool: return self._rest_api_client.update( self._object_name, self._subpath_root, data, expected_http_status={HTTP_STATUS_CREATED} ) def _rest_api_delete(self, etht_service_name : str) -> bool: if etht_service_name is None: raise Exception('etht_service_name is None') subpath_url = self._subpath_item.format(etht_service_name=etht_service_name) return self._rest_api_client.delete( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_NO_CONTENT} ) def get(self, etht_service_name : Optional[str] = None) -> Union[Dict, List]: data = self._rest_api_get(etht_service_name=etht_service_name) data = self._rest_conf_client.get(subpath_url) if not isinstance(data, dict): raise ValueError('data should be a dict') if 'ietf-eth-tran-service:etht-svc' not in data: Loading Loading @@ -192,6 +178,7 @@ class EthtServiceHandler: return etht_services def update(self, parameters : Dict) -> bool: name = parameters['name' ] service_type = parameters['service_type' ] Loading @@ -214,8 +201,10 @@ class EthtServiceHandler: src_node_id, src_tp_id, src_vlan_tag, dst_node_id, dst_tp_id, dst_vlan_tag, src_static_routes=src_static_routes, dst_static_routes=dst_static_routes ) return self._rest_conf_client.post(self._subpath_root, body=data) is not None return self._rest_api_update(data) def delete(self, etht_service_name : str) -> bool: return self._rest_api_delete(etht_service_name) def delete(self, etht_service_name : str) -> None: if etht_service_name is None: raise Exception('etht_service_name is None') subpath_url = self._subpath_item.format(etht_service_name=etht_service_name) return self._rest_conf_client.delete(subpath_url) src/device/service/drivers/ietf_actn/handlers/NetworkTopologyHandler.py +0 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ LOGGER = logging.getLogger(__name__) class NetworkTopologyHandler: def __init__(self, rest_conf_client : RestConfClient, **settings) -> None: self._rest_conf_client = rest_conf_client self._object_name = 'NetworkTopology' self._subpath_root = '/ietf-network:networks' self._subpath_item = self._subpath_root + '/network={network_id:s}' Loading src/device/service/drivers/ietf_actn/handlers/OsuTunnelHandler.py +15 −25 Original line number Diff line number Diff line Loading @@ -14,10 +14,12 @@ import enum, logging from typing import Dict, List, Optional, Union from .RestApiClient import HTTP_STATUS_CREATED, HTTP_STATUS_NO_CONTENT, HTTP_STATUS_OK, RestApiClient from common.tools.client.RestConfClient import RestConfClient LOGGER = logging.getLogger(__name__) class EndpointProtectionRoleEnum(enum.Enum): WORK = 'work' Loading Loading @@ -80,36 +82,21 @@ def compose_osu_tunnel( 'protection': compose_osu_tunnel_protection(), }]} class OsuTunnelHandler: def __init__(self, rest_api_client : RestApiClient) -> None: self._rest_api_client = rest_api_client self._object_name = 'OsuTunnel' def __init__(self, rest_conf_client : RestConfClient) -> None: self._rest_conf_client = rest_conf_client self._subpath_root = '/ietf-te:te/tunnels' self._subpath_item = self._subpath_root + '/tunnel="{osu_tunnel_name:s}"' self._subpath_item = self._subpath_root + '/tunnel={osu_tunnel_name:s}' def _rest_api_get(self, osu_tunnel_name : Optional[str] = None) -> Union[Dict, List]: def get(self, osu_tunnel_name : Optional[str] = None) -> Union[Dict, List]: if osu_tunnel_name is None: subpath_url = self._subpath_root else: subpath_url = self._subpath_item.format(osu_tunnel_name=osu_tunnel_name) return self._rest_api_client.get( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_OK} ) def _rest_api_update(self, data : Dict) -> bool: return self._rest_api_client.update( self._object_name, self._subpath_root, data, expected_http_status={HTTP_STATUS_CREATED} ) def _rest_api_delete(self, osu_tunnel_name : str) -> bool: if osu_tunnel_name is None: raise Exception('osu_tunnel_name is None') subpath_url = self._subpath_item.format(osu_tunnel_name=osu_tunnel_name) return self._rest_api_client.delete( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_NO_CONTENT} ) def get(self, osu_tunnel_name : Optional[str] = None) -> Union[Dict, List]: data = self._rest_api_get(osu_tunnel_name=osu_tunnel_name) data = self._rest_conf_client.get(subpath_url) if not isinstance(data, dict): raise ValueError('data should be a dict') if 'ietf-te:tunnel' not in data: raise ValueError('data does not contain key "ietf-te:tunnel"') Loading Loading @@ -147,6 +134,7 @@ class OsuTunnelHandler: return osu_tunnels def update(self, parameters : Dict) -> bool: name = parameters['name' ] Loading @@ -169,8 +157,10 @@ class OsuTunnelHandler: name, src_node_id, src_tp_id, src_ttp_channel_name, dst_node_id, dst_tp_id, dst_ttp_channel_name, odu_type, osuflex_number, delay, bidirectional=bidirectional ) return self._rest_conf_client.post(self._subpath_root, body=data) is not None return self._rest_api_update(data) def delete(self, osu_tunnel_name : str) -> bool: return self._rest_api_delete(osu_tunnel_name) if osu_tunnel_name is None: raise Exception('osu_tunnel_name is None') subpath_url = self._subpath_item.format(osu_tunnel_name=osu_tunnel_name) return self._rest_conf_client.delete(subpath_url) Loading
src/device/service/drivers/ietf_actn/IetfActnDriver.py +12 −16 Original line number Diff line number Diff line Loading @@ -21,19 +21,22 @@ from device.service.driver_api._Driver import _Driver, RESOURCE_ENDPOINTS, RESOU from .handlers.EthtServiceHandler import EthtServiceHandler from .handlers.OsuTunnelHandler import OsuTunnelHandler from .handlers.NetworkTopologyHandler import NetworkTopologyHandler from .handlers.RestApiClient import RestApiClient from .Tools import get_etht_services, get_osu_tunnels, parse_resource_key LOGGER = logging.getLogger(__name__) ALL_RESOURCE_KEYS = [ RESOURCE_ENDPOINTS, RESOURCE_SERVICES, ] DRIVER_NAME = 'ietf_actn' METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': DRIVER_NAME}) class IetfActnDriver(_Driver): def __init__(self, address: str, port: int, **settings) -> None: super().__init__(DRIVER_NAME, address, port, **settings) Loading @@ -41,23 +44,20 @@ class IetfActnDriver(_Driver): self.__started = threading.Event() self.__terminate = threading.Event() self._rest_api_client = RestApiClient(address, port, settings=settings) restconf_settings = copy.deepcopy(settings) restconf_settings.pop('base_url', None) restconf_settings.pop('import_topology', None) restconf_settings['logger'] = logging.getLogger(__name__ + '.RestConfClient') self._rest_conf_client = RestConfClient(address, port=port, **restconf_settings) self._handler_etht_service = EthtServiceHandler(self._rest_api_client) self._handler_etht_service = EthtServiceHandler(self._rest_conf_client) self._handler_net_topology = NetworkTopologyHandler(self._rest_conf_client, **settings) self._handler_osu_tunnel = OsuTunnelHandler(self._rest_api_client) self._handler_osu_tunnel = OsuTunnelHandler(self._rest_conf_client) def Connect(self) -> bool: with self.__lock: if self.__started.is_set(): return True try: self._rest_api_client.get('Check Credentials', '') self._rest_conf_client._discover_base_url() except requests.exceptions.Timeout: LOGGER.exception('Timeout exception checking connectivity') return False Loading @@ -81,15 +81,13 @@ class IetfActnDriver(_Driver): @metered_subclass_method(METRICS_POOL) def GetConfig(self, resource_keys : List[str] = []) -> List[Tuple[str, Union[Any, None, Exception]]]: chk_type('resources', resource_keys, list) results = [] results = list() with self.__lock: if len(resource_keys) == 0: resource_keys = ALL_RESOURCE_KEYS for i, resource_key in enumerate(resource_keys): chk_string('resource_key[#{:d}]'.format(i), resource_key, allow_empty=False) try: _results = list() if resource_key == RESOURCE_ENDPOINTS: # Add mgmt endpoint by default #resource_key = '/endpoints/endpoint[mgmt]' Loading @@ -97,17 +95,15 @@ class IetfActnDriver(_Driver): #results.append((resource_key, resource_value)) results.extend(self._handler_net_topology.get()) elif resource_key == RESOURCE_SERVICES: get_osu_tunnels(self._handler_osu_tunnel, _results) get_etht_services(self._handler_etht_service, _results) get_osu_tunnels(self._handler_osu_tunnel, results) get_etht_services(self._handler_etht_service, results) else: # check if resource key is for a specific OSU tunnel or ETHT service, and get them accordingly osu_tunnel_name, etht_service_name = parse_resource_key(resource_key) if osu_tunnel_name is not None: get_osu_tunnels(self._handler_osu_tunnel, _results, osu_tunnel_name=osu_tunnel_name) get_osu_tunnels(self._handler_osu_tunnel, results, osu_tunnel_name=osu_tunnel_name) if etht_service_name is not None: get_etht_services(self._handler_etht_service, _results, etht_service_name=etht_service_name) results.extend(_results) get_etht_services(self._handler_etht_service, results, etht_service_name=etht_service_name) except Exception as e: MSG = 'Error processing resource_key: {:s}' LOGGER.exception(MSG.format(str(resource_key))) Loading
src/device/service/drivers/ietf_actn/handlers/EthtServiceHandler.py +16 −27 Original line number Diff line number Diff line Loading @@ -14,10 +14,12 @@ import enum, logging from typing import Dict, List, Optional, Tuple, Union from .RestApiClient import HTTP_STATUS_CREATED, HTTP_STATUS_NO_CONTENT, HTTP_STATUS_OK, RestApiClient from common.tools.client.RestConfClient import RestConfClient LOGGER = logging.getLogger(__name__) class BandwidthProfileTypeEnum(enum.Enum): MEF_10_BWP = 'ietf-eth-tran-types:mef-10-bwp' Loading Loading @@ -106,36 +108,20 @@ def compose_etht_service( 'optimizations': compose_optimizations(), }]}} class EthtServiceHandler: def __init__(self, rest_api_client : RestApiClient) -> None: self._rest_api_client = rest_api_client self._object_name = 'EthtService' def __init__(self, rest_conf_client : RestConfClient) -> None: self._rest_conf_client = rest_conf_client self._subpath_root = '/ietf-eth-tran-service:etht-svc' self._subpath_item = self._subpath_root + '/etht-svc-instances="{etht_service_name:s}"' self._subpath_item = self._subpath_root + '/etht-svc-instances={etht_service_name:s}' def _rest_api_get(self, etht_service_name : Optional[str] = None) -> Union[Dict, List]: def get(self, etht_service_name : Optional[str] = None) -> Union[Dict, List]: if etht_service_name is None: subpath_url = self._subpath_root else: subpath_url = self._subpath_item.format(etht_service_name=etht_service_name) return self._rest_api_client.get( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_OK} ) def _rest_api_update(self, data : Dict) -> bool: return self._rest_api_client.update( self._object_name, self._subpath_root, data, expected_http_status={HTTP_STATUS_CREATED} ) def _rest_api_delete(self, etht_service_name : str) -> bool: if etht_service_name is None: raise Exception('etht_service_name is None') subpath_url = self._subpath_item.format(etht_service_name=etht_service_name) return self._rest_api_client.delete( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_NO_CONTENT} ) def get(self, etht_service_name : Optional[str] = None) -> Union[Dict, List]: data = self._rest_api_get(etht_service_name=etht_service_name) data = self._rest_conf_client.get(subpath_url) if not isinstance(data, dict): raise ValueError('data should be a dict') if 'ietf-eth-tran-service:etht-svc' not in data: Loading Loading @@ -192,6 +178,7 @@ class EthtServiceHandler: return etht_services def update(self, parameters : Dict) -> bool: name = parameters['name' ] service_type = parameters['service_type' ] Loading @@ -214,8 +201,10 @@ class EthtServiceHandler: src_node_id, src_tp_id, src_vlan_tag, dst_node_id, dst_tp_id, dst_vlan_tag, src_static_routes=src_static_routes, dst_static_routes=dst_static_routes ) return self._rest_conf_client.post(self._subpath_root, body=data) is not None return self._rest_api_update(data) def delete(self, etht_service_name : str) -> bool: return self._rest_api_delete(etht_service_name) def delete(self, etht_service_name : str) -> None: if etht_service_name is None: raise Exception('etht_service_name is None') subpath_url = self._subpath_item.format(etht_service_name=etht_service_name) return self._rest_conf_client.delete(subpath_url)
src/device/service/drivers/ietf_actn/handlers/NetworkTopologyHandler.py +0 −1 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ LOGGER = logging.getLogger(__name__) class NetworkTopologyHandler: def __init__(self, rest_conf_client : RestConfClient, **settings) -> None: self._rest_conf_client = rest_conf_client self._object_name = 'NetworkTopology' self._subpath_root = '/ietf-network:networks' self._subpath_item = self._subpath_root + '/network={network_id:s}' Loading
src/device/service/drivers/ietf_actn/handlers/OsuTunnelHandler.py +15 −25 Original line number Diff line number Diff line Loading @@ -14,10 +14,12 @@ import enum, logging from typing import Dict, List, Optional, Union from .RestApiClient import HTTP_STATUS_CREATED, HTTP_STATUS_NO_CONTENT, HTTP_STATUS_OK, RestApiClient from common.tools.client.RestConfClient import RestConfClient LOGGER = logging.getLogger(__name__) class EndpointProtectionRoleEnum(enum.Enum): WORK = 'work' Loading Loading @@ -80,36 +82,21 @@ def compose_osu_tunnel( 'protection': compose_osu_tunnel_protection(), }]} class OsuTunnelHandler: def __init__(self, rest_api_client : RestApiClient) -> None: self._rest_api_client = rest_api_client self._object_name = 'OsuTunnel' def __init__(self, rest_conf_client : RestConfClient) -> None: self._rest_conf_client = rest_conf_client self._subpath_root = '/ietf-te:te/tunnels' self._subpath_item = self._subpath_root + '/tunnel="{osu_tunnel_name:s}"' self._subpath_item = self._subpath_root + '/tunnel={osu_tunnel_name:s}' def _rest_api_get(self, osu_tunnel_name : Optional[str] = None) -> Union[Dict, List]: def get(self, osu_tunnel_name : Optional[str] = None) -> Union[Dict, List]: if osu_tunnel_name is None: subpath_url = self._subpath_root else: subpath_url = self._subpath_item.format(osu_tunnel_name=osu_tunnel_name) return self._rest_api_client.get( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_OK} ) def _rest_api_update(self, data : Dict) -> bool: return self._rest_api_client.update( self._object_name, self._subpath_root, data, expected_http_status={HTTP_STATUS_CREATED} ) def _rest_api_delete(self, osu_tunnel_name : str) -> bool: if osu_tunnel_name is None: raise Exception('osu_tunnel_name is None') subpath_url = self._subpath_item.format(osu_tunnel_name=osu_tunnel_name) return self._rest_api_client.delete( self._object_name, subpath_url, expected_http_status={HTTP_STATUS_NO_CONTENT} ) def get(self, osu_tunnel_name : Optional[str] = None) -> Union[Dict, List]: data = self._rest_api_get(osu_tunnel_name=osu_tunnel_name) data = self._rest_conf_client.get(subpath_url) if not isinstance(data, dict): raise ValueError('data should be a dict') if 'ietf-te:tunnel' not in data: raise ValueError('data does not contain key "ietf-te:tunnel"') Loading Loading @@ -147,6 +134,7 @@ class OsuTunnelHandler: return osu_tunnels def update(self, parameters : Dict) -> bool: name = parameters['name' ] Loading @@ -169,8 +157,10 @@ class OsuTunnelHandler: name, src_node_id, src_tp_id, src_ttp_channel_name, dst_node_id, dst_tp_id, dst_ttp_channel_name, odu_type, osuflex_number, delay, bidirectional=bidirectional ) return self._rest_conf_client.post(self._subpath_root, body=data) is not None return self._rest_api_update(data) def delete(self, osu_tunnel_name : str) -> bool: return self._rest_api_delete(osu_tunnel_name) if osu_tunnel_name is None: raise Exception('osu_tunnel_name is None') subpath_url = self._subpath_item.format(osu_tunnel_name=osu_tunnel_name) return self._rest_conf_client.delete(subpath_url)