Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# Copyright 2022-2024 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 json, logging, requests
from os import name
from requests.auth import HTTPBasicAuth
from typing import Dict, List, Optional
GET_DEVICES_URL = '{:s}://{:s}:{:d}/v1.0/topology/switches'
GET_LINKS_URL = '{:s}://{:s}:{:d}/v1.0/topology/links'
TIMEOUT = 30
HTTP_OK_CODES = {
200, # OK
201, # Created
202, # Accepted
204, # No Content
}
MAPPING_STATUS = {
'DEVICEOPERATIONALSTATUS_UNDEFINED': 0,
'DEVICEOPERATIONALSTATUS_DISABLED' : 1,
'DEVICEOPERATIONALSTATUS_ENABLED' : 2,
}
MAPPING_DRIVER = {
'DEVICEDRIVER_UNDEFINED' : 0,
'DEVICEDRIVER_OPENCONFIG' : 1,
'DEVICEDRIVER_TRANSPORT_API' : 2,
'DEVICEDRIVER_P4' : 3,
'DEVICEDRIVER_IETF_NETWORK_TOPOLOGY': 4,
'DEVICEDRIVER_ONF_TR_532' : 5,
'DEVICEDRIVER_XR' : 6,
'DEVICEDRIVER_IETF_L2VPN' : 7,
'DEVICEDRIVER_GNMI_OPENCONFIG' : 8,
'DEVICEDRIVER_OPTICAL_TFS' : 9,
'DEVICEDRIVER_IETF_ACTN' : 10,
'DEVICEDRIVER_OC' : 11,
'DEVICEDRIVER_QKD' : 12,
'DEVICEDRIVER_RYU' : 13,
}
MSG_ERROR = 'Could not retrieve devices in remote TeraFlowSDN instance({:s}). status_code={:s} reply={:s}'
LOGGER = logging.getLogger(__name__)
class TfsApiClient:
def __init__(
self, address : str, port : int, scheme : str = 'http',
username : Optional[str] = None, password : Optional[str] = None
) -> None:
self._devices_url = GET_DEVICES_URL.format(scheme, address, port)
LOGGER.info(f'self_devices_url{self._devices_url}')
self._links_url = GET_LINKS_URL.format(scheme, address, port)
self._auth = HTTPBasicAuth(username, password) if username is not None and password is not None else None
def get_devices_endpoints(self) -> List[Dict]:
LOGGER.debug('[get_devices_endpoints] begin')
reply_switches = requests.get(self._devices_url, timeout=TIMEOUT, verify=False, auth=self._auth)
if reply_switches.status_code not in HTTP_OK_CODES:
msg = MSG_ERROR.format(str(self._devices_url), str(reply_switches.status_code), str(reply_switches))
LOGGER.error(msg)
raise Exception(msg)
json_reply_switches = reply_switches.json()
LOGGER.info('[get_devices_endpoints] json_reply_switches={:s}'.format(json.dumps(json_reply_switches)))
result = list()
for json_switch in json_reply_switches:
device_uuid: str = json_switch['dpid']
device_ports = json_switch.get('ports', [])
for port in device_ports:
port_name = port.get('name', '')
device_name = port_name.split('-')[0]
port_no = port.get('port_no', '')
hw_address = port.get('hw_addr', '')
device_url = '/devices/device[{:s}]'.format(device_uuid)
device_data = {
'uuid': device_uuid,
'drivers': 'DEVICEDRIVER_RYU',
}
result.append((device_url, device_data))
for json_switch in json_reply_switches:
device_uuid: str = json_switch['dpid']
device_ports = json_switch.get('ports', [])
for port in device_ports:
port_name = port.get('name', '')
port_no = port.get('port_no','')
endpoint_uuid = port_name
endpoint_url = '/endpoints/endpoint[{:s}]'.format(endpoint_uuid)
endpoint_data = {
'device_uuid': device_uuid,
'name': port_name,
'type': 'copper',
}
result.append((endpoint_url, endpoint_data))
#
reply = requests.get(self._links_url, timeout=TIMEOUT, verify=False, auth=self._auth)
if reply.status_code not in HTTP_OK_CODES:
msg = MSG_ERROR.format(str(self._links_url), str(reply.status_code), str(reply))
LOGGER.error(msg)
raise Exception(msg)
for json_link in reply.json():
dpid_src = json_link.get('src', {}).get('dpid', '')
dpid_dst = json_link.get('dst', {}).get('dpid', '')
port_src_name = json_link.get('src', {}).get('name', '')
port_name_secondpart = port_src_name.split('-')[1]
port_dst_name = json_link.get('dst', {}).get('name', '')
port_name_second = port_dst_name.split('-')[1]
switch_name_src = port_src_name.split('-')[0]
switch_name_dest = port_dst_name.split('-')[0]
link_name = f"{dpid_src}-{port_src_name}==={dpid_dst}-{port_dst_name}"
link_uuid = f"{port_src_name}=={port_dst_name}"
(dpid_src,port_src_name),
(dpid_dst,port_dst_name) ]
LOGGER.info(f'link_endpoint_ids are {link_endpoint_ids}')
link_url = '/links/link[{:s}]'.format(link_uuid)
link_data = {
'uuid': link_uuid,
'name': link_name,
'endpoints': link_endpoint_ids,
}
result.append((link_url, link_data))
LOGGER.debug('[get_devices_endpoints] topology; returning')
return result