Skip to content
Snippets Groups Projects
Commit efabee0e authored by Lluis Gifre Renom's avatar Lluis Gifre Renom
Browse files

Device - IETF ACTN Driver:

- Intermediate backup
parent b03b81da
No related branches found
No related tags found
2 merge requests!235Release TeraFlowSDN 3.0,!188Resolve "(CTTC) Implement SBI Driver ACTN"
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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 enum
from typing import Dict
OSU_TUNNEL_URL = '/restconf/data/ietf-te:tunnel'
class EndpointProtectionRoleEnum(enum.Enum):
WORK = 'work'
class LspProtectionTypeEnum(enum.Enum):
UNPROTECTED = 'ietf-te-types:lsp-protection-unprotected'
class LspRestorationTypeEnum(enum.Enum):
NOT_APPLICABLE = 'ietf-te-types:lsp-restoration-not-applicable'
class TunnelAdminStateEnum(enum.Enum):
UP = 'ietf-te-types:tunnel-admin-state-up'
class OduTypeEnum(enum.Enum):
OSUFLEX = 'osuflex'
def compose_osu_tunnel_endpoint(
node_id : str, tp_id : str, ttp_channel_name : str,
protection_role : EndpointProtectionRoleEnum = EndpointProtectionRoleEnum.WORK
) -> Dict:
return {
'node-id': node_id, 'tp-id': tp_id, 'ttp-channel-name': ttp_channel_name,
'protection-role': protection_role.value
}
def compose_osu_tunnel_te_bandwidth_odu(odu_type : OduTypeEnum, number : int) -> Dict:
return {'layer': 'odu', 'odu-type': odu_type.value, 'number': number}
def compose_osu_tunnel_protection(
type_ : LspProtectionTypeEnum = LspProtectionTypeEnum.UNPROTECTED, reversion_disable : bool = True
) -> Dict:
return {'protection-type': type_.value, 'protection-reversion-disable': reversion_disable}
def compose_osu_tunnel_restoration(
type_ : LspRestorationTypeEnum = LspRestorationTypeEnum.NOT_APPLICABLE, restoration_lock : bool = False
) -> Dict:
return {'restoration-type': type_.value, 'restoration-lock': restoration_lock}
def compose_osu_tunnel(
name : str,
src_node_id : str, src_tp_id : str, src_ttp_channel_name : str,
dst_node_id : str, dst_tp_id : str, dst_ttp_channel_name : str,
odu_type : OduTypeEnum, osuflex_number : int,
delay : int, bidirectional : bool = True,
admin_state : TunnelAdminStateEnum = TunnelAdminStateEnum.UP
) -> Dict:
return {'ietf-te:tunnel': [{
'name': name.lower(),
'title': name.upper(),
'admin-state': admin_state.value,
'delay': delay,
'te-bandwidth': compose_osu_tunnel_te_bandwidth_odu(odu_type, osuflex_number),
'bidirectional': bidirectional,
'source-endpoints': {'source-endpoint': [
compose_osu_tunnel_endpoint(src_node_id, src_tp_id, src_ttp_channel_name),
]},
'destination-endpoints': {'destination-endpoint': [
compose_osu_tunnel_endpoint(dst_node_id, dst_tp_id, dst_ttp_channel_name),
]},
'restoration': compose_osu_tunnel_restoration(),
'protection': compose_osu_tunnel_protection(),
}]}
...@@ -12,12 +12,13 @@ ...@@ -12,12 +12,13 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import logging, requests, threading import json, logging, requests, threading
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
from typing import Any, Iterator, List, Optional, Tuple, Union from typing import Any, Iterator, List, Optional, Tuple, Union
from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
from common.type_checkers.Checkers import chk_string, chk_type from common.type_checkers.Checkers import chk_string, chk_type
from device.service.driver_api._Driver import _Driver from device.service.driver_api._Driver import _Driver
from device.service.drivers.ietf_actn.Tools import create_resource, delete_resource, get_resource
from . import ALL_RESOURCE_KEYS from . import ALL_RESOURCE_KEYS
#from .Tools import create_connectivity_service, find_key, config_getter, delete_connectivity_service #from .Tools import create_connectivity_service, find_key, config_getter, delete_connectivity_service
...@@ -26,33 +27,40 @@ LOGGER = logging.getLogger(__name__) ...@@ -26,33 +27,40 @@ LOGGER = logging.getLogger(__name__)
DRIVER_NAME = 'ietf_actn' DRIVER_NAME = 'ietf_actn'
METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': DRIVER_NAME}) METRICS_POOL = MetricsPool('Device', 'Driver', labels={'driver': DRIVER_NAME})
DEFAULT_BASE_URL = '/restconf/data'
DEFAULT_TIMEOUT = 120
class IetfActnDriver(_Driver): class IetfActnDriver(_Driver):
def __init__(self, address: str, port: int, **settings) -> None: def __init__(self, address: str, port: int, **settings) -> None:
super().__init__(DRIVER_NAME, address, port, **settings) super().__init__(DRIVER_NAME, address, port, **settings)
self.__lock = threading.Lock() self.__lock = threading.Lock()
self.__started = threading.Event() self.__started = threading.Event()
self.__terminate = threading.Event() self.__terminate = threading.Event()
username = self.settings.get('username') username = self.settings.get('username')
password = self.settings.get('password') password = self.settings.get('password')
self.__auth = HTTPBasicAuth(username, password) if username is not None and password is not None else None self.__auth = HTTPBasicAuth(username, password) if username is not None and password is not None else None
scheme = self.settings.get('scheme', 'http') scheme = self.settings.get('scheme', 'http')
self.__base_url = '{:s}://{:s}:{:d}'.format(scheme, self.address, int(self.port)) base_url = self.settings.get('base_url', DEFAULT_BASE_URL)
self.__timeout = int(self.settings.get('timeout', 120)) self.__base_url = '{:s}://{:s}:{:d}{:s}'.format(scheme, address, int(port), base_url)
self.__timeout = int(self.settings.get('timeout', DEFAULT_TIMEOUT))
def Connect(self) -> bool: def Connect(self) -> bool:
#url = self.__base_url + '/restconf/data/tapi-common:context' url = self.__base_url + '/tapi-common:context'
#with self.__lock: with self.__lock:
# if self.__started.is_set(): return True if self.__started.is_set(): return True
# try: try:
# requests.get(url, timeout=self.__timeout, verify=False, auth=self.__auth) requests.get(url, timeout=self.__timeout, verify=False, auth=self.__auth)
# except requests.exceptions.Timeout: except requests.exceptions.Timeout:
# LOGGER.exception('Timeout connecting {:s}'.format(str(self.__base_url))) LOGGER.exception('Timeout connecting {:s}'.format(str(self.__base_url)))
# return False return False
# except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
# LOGGER.exception('Exception connecting {:s}'.format(str(self.__base_url))) LOGGER.exception('Exception connecting {:s}'.format(str(self.__base_url)))
# return False return False
# else: else:
# self.__started.set() self.__started.set()
return True return True
def Disconnect(self) -> bool: def Disconnect(self) -> bool:
...@@ -69,13 +77,14 @@ class IetfActnDriver(_Driver): ...@@ -69,13 +77,14 @@ class IetfActnDriver(_Driver):
def GetConfig(self, resource_keys : List[str] = []) -> List[Tuple[str, Union[Any, None, Exception]]]: def GetConfig(self, resource_keys : List[str] = []) -> List[Tuple[str, Union[Any, None, Exception]]]:
chk_type('resources', resource_keys, list) chk_type('resources', resource_keys, list)
results = [] results = []
#with self.__lock: with self.__lock:
# if len(resource_keys) == 0: resource_keys = ALL_RESOURCE_KEYS if len(resource_keys) == 0: resource_keys = ALL_RESOURCE_KEYS
# for i, resource_key in enumerate(resource_keys): for i, resource_key in enumerate(resource_keys):
# str_resource_name = 'resource_key[#{:d}]'.format(i) chk_string('resource_key[#{:d}]'.format(i), resource_key, allow_empty=False)
# chk_string(str_resource_name, resource_key, allow_empty=False) results.extend(get_resource(
# results.extend(config_getter( self.__base_url, resource_key,
# self.__base_url, resource_key, timeout=self.__timeout, auth=self.__auth)) timeout=self.__timeout, auth=self.__auth
))
return results return results
@metered_subclass_method(METRICS_POOL) @metered_subclass_method(METRICS_POOL)
...@@ -83,35 +92,28 @@ class IetfActnDriver(_Driver): ...@@ -83,35 +92,28 @@ class IetfActnDriver(_Driver):
results = [] results = []
if len(resources) == 0: if len(resources) == 0:
return results return results
#with self.__lock: with self.__lock:
# for resource in resources: for resource_key, resource_value in resources:
# LOGGER.info('resource = {:s}'.format(str(resource))) LOGGER.info('resource: key({:s}) => value({:s})'.format(str(resource_key), str(resource_value)))
# if isinstance(value, str): value = json.loads(value)
# uuid = find_key(resource, 'uuid') results.extend(create_resource(
# input_sip = find_key(resource, 'input_sip_uuid') self.__base_url, resource_key, resource_value,
# output_sip = find_key(resource, 'output_sip_uuid') timeout=self.__timeout, auth=self.__auth
# capacity_value = find_key(resource, 'capacity_value') ))
# capacity_unit = find_key(resource, 'capacity_unit')
# layer_protocol_name = find_key(resource, 'layer_protocol_name')
# layer_protocol_qualifier = find_key(resource, 'layer_protocol_qualifier')
# direction = find_key(resource, 'direction')
#
# data = create_connectivity_service(
# self.__base_url, uuid, input_sip, output_sip, direction, capacity_value, capacity_unit,
# layer_protocol_name, layer_protocol_qualifier, timeout=self.__timeout, auth=self.__auth)
# results.extend(data)
return results return results
@metered_subclass_method(METRICS_POOL) @metered_subclass_method(METRICS_POOL)
def DeleteConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: def DeleteConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
results = [] results = []
if len(resources) == 0: return results if len(resources) == 0: return results
#with self.__lock: with self.__lock:
# for resource in resources: for resource_key, resource_value in resources:
# LOGGER.info('resource = {:s}'.format(str(resource))) LOGGER.info('resource: key({:s}) => value({:s})'.format(str(resource_key), str(resource_value)))
# uuid = find_key(resource, 'uuid') if isinstance(value, str): value = json.loads(value)
# results.extend(delete_connectivity_service( results.extend(delete_resource(
# self.__base_url, uuid, timeout=self.__timeout, auth=self.__auth)) self.__base_url, resource_key, resource_value,
timeout=self.__timeout, auth=self.__auth
))
return results return results
@metered_subclass_method(METRICS_POOL) @metered_subclass_method(METRICS_POOL)
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
import json, logging, operator, requests import json, logging, operator, requests
from requests.auth import HTTPBasicAuth from requests.auth import HTTPBasicAuth
from typing import Optional from typing import Dict, Optional
from device.service.driver_api._Driver import RESOURCE_ENDPOINTS, RESOURCE_SERVICES from device.service.driver_api._Driver import RESOURCE_ENDPOINTS, RESOURCE_SERVICES
LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__)
...@@ -29,11 +29,11 @@ HTTP_OK_CODES = { ...@@ -29,11 +29,11 @@ HTTP_OK_CODES = {
def find_key(resource, key): def find_key(resource, key):
return json.loads(resource[1])[key] return json.loads(resource[1])[key]
def get_resource(
def config_getter( base_url : str, resource_key : str,
root_url : str, resource_key : str, auth : Optional[HTTPBasicAuth] = None, timeout : Optional[int] = None auth : Optional[HTTPBasicAuth] = None, timeout : Optional[int] = None
): ):
url = '{:s}/restconf/data/tapi-common:context'.format(root_url) url = '{:s}/restconf/data/tapi-common:context'.format(base_url)
result = [] result = []
try: try:
response = requests.get(url, timeout=timeout, verify=False, auth=auth) response = requests.get(url, timeout=timeout, verify=False, auth=auth)
...@@ -123,13 +123,22 @@ def config_getter( ...@@ -123,13 +123,22 @@ def config_getter(
return result return result
def create_connectivity_service( def create_resource(
root_url, uuid, input_sip, output_sip, direction, capacity_value, capacity_unit, layer_protocol_name, base_url : str, resource_key : str, resource_value : Dict,
layer_protocol_qualifier,
auth : Optional[HTTPBasicAuth] = None, timeout : Optional[int] = None auth : Optional[HTTPBasicAuth] = None, timeout : Optional[int] = None
): ):
url = '{:s}/restconf/data/tapi-common:context/tapi-connectivity:connectivity-context'.format(root_url) uuid = find_key(resource, 'uuid')
input_sip = find_key(resource, 'input_sip_uuid')
output_sip = find_key(resource, 'output_sip_uuid')
capacity_value = find_key(resource, 'capacity_value')
capacity_unit = find_key(resource, 'capacity_unit')
layer_protocol_name = find_key(resource, 'layer_protocol_name')
layer_protocol_qualifier = find_key(resource, 'layer_protocol_qualifier')
direction = find_key(resource, 'direction')
url = '{:s}/restconf/data/tapi-common:context/tapi-connectivity:connectivity-context'.format(base_url)
headers = {'content-type': 'application/json'} headers = {'content-type': 'application/json'}
data = { data = {
'tapi-connectivity:connectivity-service': [ 'tapi-connectivity:connectivity-service': [
...@@ -181,9 +190,14 @@ def create_connectivity_service( ...@@ -181,9 +190,14 @@ def create_connectivity_service(
results.append(response.status_code in HTTP_OK_CODES) results.append(response.status_code in HTTP_OK_CODES)
return results return results
def delete_connectivity_service(root_url, uuid, auth : Optional[HTTPBasicAuth] = None, timeout : Optional[int] = None): def delete_resource(
base_url : str, resource_key : str, resource_value : Dict,
auth : Optional[HTTPBasicAuth] = None, timeout : Optional[int] = None
):
uuid = find_key(resource, 'uuid')
url = '{:s}/restconf/data/tapi-common:context/tapi-connectivity:connectivity-context/connectivity-service={:s}' url = '{:s}/restconf/data/tapi-common:context/tapi-connectivity:connectivity-context/connectivity-service={:s}'
url = url.format(root_url, uuid) url = url.format(base_url, uuid)
results = [] results = []
try: try:
response = requests.delete(url=url, timeout=timeout, verify=False, auth=auth) response = requests.delete(url=url, timeout=timeout, verify=False, auth=auth)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment