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

Device component - OpticalTfs driver:

- Corrected setup/teardown of optical connectivity services
parent a10687b7
No related branches found
No related tags found
3 merge requests!359Release TeraFlowSDN 5.0,!328Resolve "(CTTC) Update recommendations to use SocketIO on NBI and E2E Orch components",!286Resolve "(CTTC) Implement integration test between E2E-IP-Optical SDN Controllers"
......@@ -20,7 +20,7 @@ from common.type_checkers.Checkers import chk_string, chk_type
from device.service.driver_api._Driver import _Driver, RESOURCE_ENDPOINTS, RESOURCE_SERVICES
from device.service.driver_api.ImportTopologyEnum import ImportTopologyEnum, get_import_topology
from .TfsApiClient import TfsApiClient
from .TfsOpticalClient import TfsOpticalClient
#from .TfsOpticalClient import TfsOpticalClient
LOGGER = logging.getLogger(__name__)
......@@ -46,10 +46,10 @@ class OpticalTfsDriver(_Driver):
self.address, self.port, scheme=scheme, username=username,
password=password, timeout=timeout
)
self.toc = TfsOpticalClient(
self.address, int(self.port), scheme=scheme, username=username,
password=password, timeout=timeout
)
#self.toc = TfsOpticalClient(
# self.address, int(self.port), scheme=scheme, username=username,
# password=password, timeout=timeout
#)
# Options are:
# disabled --> just import endpoints as usual
......@@ -99,8 +99,7 @@ class OpticalTfsDriver(_Driver):
results.extend(self.tac.get_devices_endpoints(self.__import_topology))
elif resource_key == RESOURCE_SERVICES:
# return all services through
#results.extend(self.toc.get_lightpaths())
pass
results.extend(self.tac.get_services())
else:
MSG = 'ResourceKey({:s}) not implemented'
LOGGER.warning(MSG.format(str(resource_key)))
......@@ -123,13 +122,11 @@ class OpticalTfsDriver(_Driver):
resource_key, resource_value = resource
try:
resource_value = json.loads(resource_value)
src_node = resource_value['src_node']
dst_node = resource_value['dst_node']
bitrate = resource_value['bitrate' ]
results.extend(self.toc.add_lightpath(src_node, dst_node, bitrate))
self.tac.setup_service(resource_value)
results.append((resource_key, True))
except Exception as e:
LOGGER.exception('Unhandled error processing resource_key({:s})'.format(str(resource_key)))
MSG = 'Unhandled error processing resource_key({:s})'
LOGGER.exception(MSG.format(str(resource_key)))
results.append((resource_key, e))
return results
......@@ -146,14 +143,11 @@ class OpticalTfsDriver(_Driver):
resource_key,resource_value = resource
try:
resource_value = json.loads(resource_value)
flow_id = resource_value['flow_id' ]
src_node = resource_value['src_node']
dst_node = resource_value['dst_node']
bitrate = resource_value['bitrate' ]
self.toc.del_lightpath(flow_id, src_node, dst_node, bitrate)
self.tac.teardown_service(resource_value)
results.append((resource_key, True))
except Exception as e:
LOGGER.exception('Unhandled error processing resource_key({:s})'.format(str(resource_key)))
MSG = 'Unhandled error processing resource_key({:s})'
LOGGER.exception(MSG.format(str(resource_key)))
results.append((resource_key, e))
return results
......
......@@ -12,14 +12,22 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import logging, requests
from typing import Dict, List, Optional
import logging
from typing import Dict, List, Optional, Tuple
from common.Constants import DEFAULT_CONTEXT_NAME, DEFAULT_TOPOLOGY_NAME
from common.proto.context_pb2 import ServiceStatusEnum, ServiceTypeEnum
from common.tools.client.RestClient import RestClient
from common.tools.object_factory.Constraint import json_constraint_custom
from common.tools.object_factory.Context import json_context_id
from common.tools.object_factory.Device import json_device_id
from common.tools.object_factory.EndPoint import json_endpoint_id
from common.tools.object_factory.Service import json_service
from device.service.driver_api.ImportTopologyEnum import ImportTopologyEnum
GET_CONTEXT_IDS_URL = '/tfs-api/context_ids'
GET_DEVICES_URL = '/tfs-api/devices'
GET_LINKS_URL = '/tfs-api/links'
CONTEXT_IDS_URL = '/tfs-api/context_ids'
TOPOLOGY_URL = '/tfs-api/context/{context_uuid:s}/topology_details/{topology_uuid:s}'
SERVICES_URL = '/tfs-api/context/{context_uuid:s}/services'
SERVICE_URL = '/tfs-api/context/{context_uuid:s}/service/{service_uuid:s}'
MAPPING_STATUS = {
'DEVICEOPERATIONALSTATUS_UNDEFINED': 0,
......@@ -60,7 +68,7 @@ class TfsApiClient(RestClient):
)
def check_credentials(self) -> None:
self.get(GET_CONTEXT_IDS_URL, expected_status_codes={requests.codes['OK']})
self.get(CONTEXT_IDS_URL)
LOGGER.info('Credentials checked')
def get_devices_endpoints(
......@@ -74,10 +82,12 @@ class TfsApiClient(RestClient):
MSG = 'Unsupported import_topology mode: {:s}'
raise Exception(MSG.format(str(import_topology)))
devices = self.get(GET_DEVICES_URL, expected_status_codes={requests.codes['OK']})
topology = self.get(TOPOLOGY_URL.format(
context_uuid=DEFAULT_CONTEXT_NAME, topology_uuid=DEFAULT_TOPOLOGY_NAME
))
result = list()
for json_device in devices['devices']:
for json_device in topology['devices']:
device_uuid : str = json_device['device_id']['device_uuid']['uuid']
device_type : str = json_device['device_type']
#if not device_type.startswith('emu-'): device_type = 'emu-' + device_type
......@@ -110,9 +120,24 @@ class TfsApiClient(RestClient):
LOGGER.debug('[get_devices_endpoints] devices only; returning')
return result
links = self.get(GET_LINKS_URL, expected_status_codes={requests.codes['OK']})
for json_link in topology['links']:
link_uuid : str = json_link['link_id']['link_uuid']['uuid']
link_url = '/links/link[{:s}]'.format(link_uuid)
link_endpoint_ids = [
(
json_endpoint_id['device_id']['device_uuid']['uuid'],
json_endpoint_id['endpoint_uuid']['uuid'],
)
for json_endpoint_id in json_link['link_endpoint_ids']
]
link_data = {
'uuid': json_link['link_id']['link_uuid']['uuid'],
'name': json_link['name'],
'endpoints': link_endpoint_ids,
}
result.append((link_url, link_data))
for json_link in links['links']:
for json_link in topology['optical_links']:
link_uuid : str = json_link['link_id']['link_uuid']['uuid']
link_url = '/links/link[{:s}]'.format(link_uuid)
link_endpoint_ids = [
......@@ -131,3 +156,103 @@ class TfsApiClient(RestClient):
LOGGER.debug('[get_devices_endpoints] topology; returning')
return result
def setup_service(self, resource_value : Dict) -> None:
service_uuid = resource_value['service_uuid' ]
service_name = resource_value['service_name' ]
src_device_uuid = resource_value['src_device_uuid' ]
src_endpoint_uuid = resource_value['src_endpoint_uuid']
dst_device_uuid = resource_value['dst_device_uuid' ]
dst_endpoint_uuid = resource_value['dst_endpoint_uuid']
bitrate = resource_value['bitrate' ]
bidir = resource_value['bidir' ]
ob_width = resource_value['ob_width' ]
endpoint_ids = [
json_endpoint_id(json_device_id(src_device_uuid), src_endpoint_uuid),
json_endpoint_id(json_device_id(dst_device_uuid), dst_endpoint_uuid),
]
constraints = [
json_constraint_custom('bandwidth[gbps]', str(bitrate)),
json_constraint_custom('bidirectionality', '1' if bidir else '0'),
]
if service_name == 'IP1/PORT-xe1==IP2/PORT-xe1':
constraints.append(json_constraint_custom('optical-band-width[GHz]', str(ob_width)))
service_add = json_service(
service_uuid,
ServiceTypeEnum.Name(ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY),
context_id = json_context_id(DEFAULT_CONTEXT_NAME),
name = service_name,
status = ServiceStatusEnum.Name(ServiceStatusEnum.SERVICESTATUS_PLANNED),
)
services_url = SERVICES_URL.format(context_uuid=DEFAULT_CONTEXT_NAME)
service_ids = self.post(services_url, body=service_add)
assert len(service_ids) == 1
service_id = service_ids[0]
service_uuid = service_id['service_uuid']['uuid']
service_upd = json_service(
service_uuid,
ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY,
context_id = json_context_id(DEFAULT_CONTEXT_NAME),
name = service_name, endpoint_ids = endpoint_ids, constraints = constraints,
status = ServiceStatusEnum.Name(ServiceStatusEnum.SERVICESTATUS_PLANNED),
)
service_url = SERVICE_URL.format(context_uuid=DEFAULT_CONTEXT_NAME, service_uuid=service_uuid)
self.put(service_url, body=service_upd)
def teardown_service(self, resource_value : Dict) -> None:
service_uuid = resource_value['service_uuid']
service_name = resource_value['service_name']
service_url = SERVICE_URL.format(context_uuid=DEFAULT_CONTEXT_NAME, service_uuid=service_uuid)
self.delete(service_url)
if service_name == 'IP1/PORT-xe1==IP2/PORT-xe1':
self.delete(service_url)
@staticmethod
def parse_service(service : Dict) -> Tuple[str, Dict]:
service_uuid = service['service_id']['service_uuid']['uuid']
src_endpoint_id = service['service_endpoint_ids'][ 0]
dst_endpoint_id = service['service_endpoint_ids'][-1]
parsed_service = {
'service_uuid' : service_uuid,
'service_name' : service['name'],
'src_device_uuid' : src_endpoint_id['device_id']['device_uuid']['uuid'],
'src_endpoint_uuid': src_endpoint_id['endpoint_uuid']['uuid'],
'dst_device_uuid' : dst_endpoint_id['device_id']['device_uuid']['uuid'],
'dst_endpoint_uuid': dst_endpoint_id['endpoint_uuid']['uuid'],
}
for constraint in service.get('service_constraints', list()):
if 'custom' not in constraint: continue
constraint_type = constraint['custom']['constraint_type']
constraint_value = constraint['custom']['constraint_value']
if constraint_type == 'bandwidth[gbps]':
parsed_service['bitrate'] = int(float(constraint_value))
if constraint_type == 'bidirectionality':
parsed_service['bidir'] = int(constraint_value) == 1
if constraint_type == 'optical-band-width[GHz]':
parsed_service['ob_width'] = int(constraint_value)
resource_key = '/services/service[{:s}]'.format(service_uuid)
return resource_key, parsed_service
def get_services(self) -> List[Tuple[str, Dict]]:
services_url = SERVICES_URL.format(context_uuid=DEFAULT_CONTEXT_NAME)
_services = self.get(services_url)
OPTICAL_CONNECTIVITY_SERVICE_TYPES = {
'SERVICETYPE_OPTICAL_CONNECTIVITY',
ServiceTypeEnum.SERVICETYPE_OPTICAL_CONNECTIVITY
}
return [
TfsApiClient.parse_service(service)
for service in _services['services']
if service['service_type'] in OPTICAL_CONNECTIVITY_SERVICE_TYPES
]
def get_service(self, service_uuid : str) -> Tuple[str, Dict]:
service_url = SERVICE_URL.format(context_uuid=DEFAULT_CONTEXT_NAME, service_uuid=service_uuid)
service = self.get(service_url)
return TfsApiClient.parse_service(service)
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