Commit 6a3609d9 authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Device component - ACTN Driver:

- Code polishing
parent c4d36d2d
Loading
Loading
Loading
Loading
+5 −9
Original line number Diff line number Diff line
@@ -85,14 +85,10 @@ class IetfActnDriver(_Driver):
        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)

                str_resource_name = 'resource_key[#{:d}]'.format(i)
                try:
                    chk_string(str_resource_name, resource_key, allow_empty=False)
                    if resource_key == RESOURCE_ENDPOINTS:
                        # Add mgmt endpoint by default
                        #resource_key = '/endpoints/endpoint[mgmt]'
                        #resource_value = {'uuid': 'mgmt', 'name': 'mgmt', 'type': 'mgmt'}
                        #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)
@@ -105,9 +101,9 @@ class IetfActnDriver(_Driver):
                        if etht_service_name is not None:
                            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)))
                    results.append((resource_key, e))
                    MSG = 'Error processing resource_key({:s}, {:s})'
                    LOGGER.exception(MSG.format(str_resource_name, str(resource_key)))
                    results.append((resource_key, e))  # if processing fails, store the exception

        return results

+0 −104
Original line number Diff line number Diff line
# Copyright 2022-2025 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import copy, json, logging, requests
from requests.auth import HTTPBasicAuth
from typing import Any, Dict, List, Set, Union

LOGGER = logging.getLogger(__name__)

DEFAULT_BASE_URL = '/restconf/v2/data'
DEFAULT_SCHEME   = '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 = {
    HTTP_STATUS_OK,
    HTTP_STATUS_CREATED,
    HTTP_STATUS_ACCEPTED,
    HTTP_STATUS_NO_CONTENT,
}

class RestApiClient:
    def __init__(self, address : str, port : int, settings : Dict[str, Any] = dict()) -> None:
        username = settings.get('username')
        password = settings.get('password')
        self._auth = HTTPBasicAuth(username, password) if username is not None and password is not None else None

        scheme   = settings.get('scheme',   DEFAULT_SCHEME  )
        base_url = settings.get('base_url', DEFAULT_BASE_URL)
        self._base_url = '{:s}://{:s}:{:d}{:s}'.format(scheme, address, int(port), base_url)

        self._timeout = int(settings.get('timeout', DEFAULT_TIMEOUT))
        self._verify  = bool(settings.get('verify', DEFAULT_VERIFY))

    def get(
        self, object_name : str, url : str,
        expected_http_status : Set[int] = {HTTP_STATUS_OK}
    ) -> Union[Dict, List]:
        MSG = 'Get {:s}({:s})'
        LOGGER.info(MSG.format(str(object_name), str(url)))
        response = requests.get(
            self._base_url + url,
            timeout=self._timeout, verify=self._verify, auth=self._auth
        )
        LOGGER.info('  Response[{:s}]: {:s}'.format(str(response.status_code), str(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}'
        raise Exception(MSG.format(str(object_name), str(url), str(response.status_code), str(response)))

    def update(
        self, object_name : str, url : str, data : Dict, headers : Dict[str, Any] = dict(),
        expected_http_status : Set[int] = HTTP_OK_CODES
    ) -> None:
        headers = copy.deepcopy(headers)
        if 'content-type' not in {header_name.lower() for header_name in headers.keys()}:
            headers.update({'content-type': 'application/json'})

        MSG = 'Create/Update {:s}({:s}, {:s})'
        LOGGER.info(MSG.format(str(object_name), str(url), str(data)))
        response = requests.post(
            self._base_url + url, data=json.dumps(data), headers=headers,
            timeout=self._timeout, verify=self._verify, auth=self._auth
        )
        LOGGER.info('  Response[{:s}]: {:s}'.format(str(response.status_code), str(response.content)))

        if response.status_code in expected_http_status: return

        MSG = 'Could not create/update {:s}({:s}, {:s}): status_code={:s} reply={:s}'
        raise Exception(MSG.format(str(object_name), str(url), str(data), str(response.status_code), str(response)))

    def delete(
        self, object_name : str, url : str,
        expected_http_status : Set[int] = HTTP_OK_CODES
    ) -> None:
        MSG = 'Delete {:s}({:s})'
        LOGGER.info(MSG.format(str(object_name), str(url)))
        response = requests.delete(
            self._base_url + url,
            timeout=self._timeout, verify=self._verify, auth=self._auth
        )
        LOGGER.info('  Response[{:s}]: {:s}'.format(str(response.status_code), str(response.content)))

        if response.status_code in expected_http_status: return

        MSG = 'Could not delete {:s}({:s}): status_code={:s} reply={:s}'
        raise Exception(MSG.format(str(object_name), str(url), str(response.status_code), str(response)))