diff --git a/src/device/service/drivers/ietf_actn/handlers/EthtServiceHandler.py b/src/device/service/drivers/ietf_actn/handlers/EthtServiceHandler.py index 66734199afa60149bf51990ab00fe815bbae3600..ff0dadbbcbcd0d58508ce4dacb1830f2ef170bad 100644 --- a/src/device/service/drivers/ietf_actn/handlers/EthtServiceHandler.py +++ b/src/device/service/drivers/ietf_actn/handlers/EthtServiceHandler.py @@ -14,7 +14,7 @@ import enum, logging from typing import Dict, List, Optional, Tuple, Union -from .RestApiClient import RestApiClient +from .RestApiClient import HTTP_STATUS_CREATED, HTTP_STATUS_NO_CONTENT, HTTP_STATUS_OK, RestApiClient LOGGER = logging.getLogger(__name__) @@ -110,11 +110,26 @@ class EthtServiceHandler: def __init__(self, rest_api_client : RestApiClient) -> None: self._rest_api_client = rest_api_client self._object_name = 'EthtService' - self._subpath_url = '/ietf-eth-tran-service:etht-svc/etht-svc-instances' + self._subpath_url = '/ietf-eth-tran-service:etht-svc' + + def _rest_api_get(self, filters : List[Tuple[str, str]]) -> Union[Dict, List]: + return self._rest_api_client.get( + self._object_name, self._subpath_url, filters, 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_url, data, expected_http_status={HTTP_STATUS_CREATED} + ) + + def _rest_api_delete(self, filters : List[Tuple[str, str]]) -> bool: + return self._rest_api_client.delete( + self._object_name, self._subpath_url, filters, expected_http_status={HTTP_STATUS_NO_CONTENT} + ) def get(self, etht_service_name : Optional[str] = None) -> Union[Dict, List]: filters = [] if etht_service_name is None else [('etht-svc-name', etht_service_name)] - data = self._rest_api_client.get(self._object_name, self._subpath_url, filters) + data = self._rest_api_get(filters) if not isinstance(data, dict): return ValueError('data should be a dict') if 'ietf-eth-tran-service:etht-svc' not in data: @@ -194,8 +209,8 @@ class EthtServiceHandler: src_static_routes=src_static_routes, dst_static_routes=dst_static_routes ) - return self._rest_api_client.update(self._object_name, self._subpath_url, data) + return self._rest_api_update(data) def delete(self, etht_service_name : str) -> bool: filters = [('etht-svc-name', etht_service_name)] - return self._rest_api_client.delete(self._object_name, self._subpath_url, filters) + return self._rest_api_delete(filters) diff --git a/src/device/service/drivers/ietf_actn/handlers/OsuTunnelHandler.py b/src/device/service/drivers/ietf_actn/handlers/OsuTunnelHandler.py index 57395de4f372757c0d147ffb939b5d781e6e85fe..2cb6f46f0b940cc03f8956904749f5bd3bf319b8 100644 --- a/src/device/service/drivers/ietf_actn/handlers/OsuTunnelHandler.py +++ b/src/device/service/drivers/ietf_actn/handlers/OsuTunnelHandler.py @@ -13,8 +13,8 @@ # limitations under the License. import enum, logging -from typing import Dict, List, Optional, Union -from .RestApiClient import RestApiClient +from typing import Dict, List, Optional, Tuple, Union +from .RestApiClient import HTTP_STATUS_CREATED, HTTP_STATUS_NO_CONTENT, HTTP_STATUS_OK, RestApiClient LOGGER = logging.getLogger(__name__) @@ -84,11 +84,26 @@ class OsuTunnelHandler: def __init__(self, rest_api_client : RestApiClient) -> None: self._rest_api_client = rest_api_client self._object_name = 'OsuTunnel' - self._subpath_url = '/ietf-te:tunnel' + self._subpath_url = '/ietf-te:te/tunnels' + + def _rest_api_get(self, filters : List[Tuple[str, str]]) -> Union[Dict, List]: + return self._rest_api_client.get( + self._object_name, self._subpath_url, filters, 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_url, data, expected_http_status={HTTP_STATUS_CREATED} + ) + + def _rest_api_delete(self, filters : List[Tuple[str, str]]) -> bool: + return self._rest_api_client.delete( + self._object_name, self._subpath_url, filters, expected_http_status={HTTP_STATUS_NO_CONTENT} + ) def get(self, osu_tunnel_name : Optional[str] = None) -> Union[Dict, List]: filters = [] if osu_tunnel_name is None else [('name', osu_tunnel_name)] - data = self._rest_api_client.get(self._object_name, self._subpath_url, filters) + data = self._rest_api_get(filters) if not isinstance(data, dict): return ValueError('data should be a dict') if 'ietf-te:tunnel' not in data: return ValueError('data does not contain key "ietf-te:tunnel"') @@ -149,8 +164,8 @@ class OsuTunnelHandler: odu_type, osuflex_number, delay, bidirectional=bidirectional ) - return self._rest_api_client.update(self._object_name, self._subpath_url, data) + return self._rest_api_update(data) def delete(self, osu_tunnel_name : str) -> bool: filters = [('name', osu_tunnel_name)] - return self._rest_api_client.delete(self._object_name, self._subpath_url, filters) + return self._rest_api_delete(filters) diff --git a/src/device/service/drivers/ietf_actn/handlers/RestApiClient.py b/src/device/service/drivers/ietf_actn/handlers/RestApiClient.py index 15321f7a060541465f85d87c358eed6608350512..7154dfc483a038c2cd20b7ac5c429ae759ce9a65 100644 --- a/src/device/service/drivers/ietf_actn/handlers/RestApiClient.py +++ b/src/device/service/drivers/ietf_actn/handlers/RestApiClient.py @@ -14,20 +14,25 @@ import copy, json, logging, requests from requests.auth import HTTPBasicAuth -from typing import Any, Dict, List, Tuple, Union +from typing import Any, Dict, List, Set, Tuple, Union LOGGER = logging.getLogger(__name__) -DEFAULT_BASE_URL = '/restconf/data' -DEFAULT_SCHEMA = 'http' +DEFAULT_BASE_URL = '/restconf/v2/data' +DEFAULT_SCHEMA = 'https' DEFAULT_TIMEOUT = 120 DEFAULT_VERIFY = False +HTTP_STATUS_OK = 200 +HTTP_STATUS_CREATED = 201 +HTTP_STATUS_ACCEPTED = 202 +HTTP_STATUS_NO_CONTENT = 204 + HTTP_OK_CODES = { - 200, # OK - 201, # Created - 202, # Accepted - 204, # No Content + HTTP_STATUS_OK, + HTTP_STATUS_CREATED, + HTTP_STATUS_ACCEPTED, + HTTP_STATUS_NO_CONTENT, } class RestApiClient: @@ -44,7 +49,8 @@ class RestApiClient: self._verify = int(settings.get('verify', DEFAULT_VERIFY )) def get( - self, object_name : str, url : str, filters : List[Tuple[str, str]] + self, object_name : str, url : str, filters : List[Tuple[str, str]], + expected_http_status : Set[int] = {HTTP_STATUS_OK} ) -> Union[Dict, List]: str_filters = ''.join([ '[{:s}={:s}]'.format(filter_field, filter_value) @@ -59,7 +65,7 @@ class RestApiClient: ) LOGGER.info(' Response: {:s}'.format(str(response))) - if response.status_code in HTTP_OK_CODES: return json.loads(response.content) + if response.status_code in expected_http_status: return json.loads(response.content) MSG = 'Could not get {:s}({:s}): status_code={:s} reply={:s}' msg = MSG.format(str(object_name), str(str_filters), str(response.status_code), str(response)) @@ -67,7 +73,8 @@ class RestApiClient: return Exception(msg) def update( - self, object_name : str, url : str, data : Dict, headers : Dict[str, Any] = dict() + self, object_name : str, url : str, data : Dict, headers : Dict[str, Any] = dict(), + expected_http_status : Set[int] = HTTP_OK_CODES ) -> bool: headers = copy.deepcopy(headers) if 'content-type' not in {header_name.lower() for header_name in headers.keys()}: @@ -81,14 +88,15 @@ class RestApiClient: ) LOGGER.info(' Response: {:s}'.format(str(response))) - if response.status_code in HTTP_OK_CODES: return True + if response.status_code in expected_http_status: return True MSG = 'Could not create/update {:s}({:s}): status_code={:s} reply={:s}' LOGGER.error(MSG.format(str(object_name), str(data), str(response.status_code), str(response))) return False def delete( - self, object_name : str, url : str, filters : List[Tuple[str, str]] + self, object_name : str, url : str, filters : List[Tuple[str, str]], + expected_http_status : Set[int] = HTTP_OK_CODES ) -> bool: str_filters = ''.join([ '[{:s}={:s}]'.format(filter_field, filter_value) @@ -103,7 +111,7 @@ class RestApiClient: ) LOGGER.info(' Response: {:s}'.format(str(response))) - if response.status_code in HTTP_OK_CODES: return True + if response.status_code in expected_http_status: return True MSG = 'Could not delete {:s}({:s}): status_code={:s} reply={:s}' LOGGER.error(MSG.format(str(object_name), str(str_filters), str(response.status_code), str(response)))