Skip to content
Snippets Groups Projects
Commit 47d1404d authored by Ville Hallivuori's avatar Ville Hallivuori
Browse files

Pull request #5: vhallivu/xr_pytest_with_http_mock

Merge in XRCA/teraflow from vhallivu/xr_pytest_with_http_mock to xr_development

Squashed commit of the following:

commit d0688826c369c9320027cc6b3eef34d82674f1ec
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Tue Aug 30 07:29:30 2022 +0300

    XR Teraflow driver logging cleanup

commit 89922d37c7709b4fe5acb3b122f5d6aea023c956
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Tue Aug 30 07:04:15 2022 +0300

    Improved HTTP request logging

commit c50420a5358686dbafa1cf61acf35ac753a2dc5f
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Mon Aug 29 14:33:28 2022 +0300

    POST refactoring

commit a133ed135816fd252bdc026e25598e8c2e65e8ec
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Mon Aug 29 13:24:15 2022 +0300

    More refactoring

commit 202c9827f7373dabc98ac2e72464fca104d6ba64
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Mon Aug 29 08:16:07 2022 +0300

    Start of HTTP refactoring

commit 8595e63c2cc6fef51476315134c12f6f4e700a46
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Wed Aug 24 08:06:58 2022 +0300

    Add missing mutexes to XrDriver

commit d250437104322de12232320aa55e371f9777875a
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Tue Aug 23 17:54:48 2022 +0300

    Connection update unit test

commit 5240a96941b43e2cc2488443bb927475fc96ac81
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Mon Aug 22 14:34:56 2022 +0300

    Improved HTTP get error handling

commit 10fa5132aa47db2a69345c5f69a60dd9e2c25c74
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Mon Aug 22 11:51:12 2022 +0300

    Higher level unit test for XR

commit 242f44363b8bdb63e02ec92c034aa3208abd7219
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Sat Aug 20 16:59:18 2022 +0300

    Improved test data for constellation pytests

commit 3f834ba6f7e9448cab77869789ed0ded6d838e70
Author: Ville Hallivuori <VHallivuori@infinera.com>
Date:   Sat Aug 20 16:32:48 2022 +0300

    Initial prototyping of mock based testing for xr
parent c2aeea99
No related branches found
No related tags found
2 merge requests!54Release 2.0.0,!20XR Driver
......@@ -10,6 +10,7 @@ python-json-logger==2.0.2
pytz==2021.3
redis==4.1.2
requests==2.27.1
requests-mock==1.9.3
xmltodict==0.12.0
# pip's dependency resolver does not take into account installed packages.
......
......@@ -35,6 +35,7 @@ class XrDriver(_Driver):
self.__started = threading.Event()
self.__terminate = threading.Event()
self.__timeout = int(settings.get('timeout', 120))
self.__cm_address = address
# Mandatory key, an exception will get thrown if missing
self.__hub_module_name = settings["hub_module_name"]
......@@ -47,7 +48,11 @@ class XrDriver(_Driver):
LOGGER.info(f"XrDriver instantiated, cm {address}:{port}, {settings=}")
def __str__(self):
return f"{self.__hub_module_name}@{self.__cm_address}"
def Connect(self) -> bool:
LOGGER.info(f"Connect[{self}]")
with self.__lock:
if self.__started.is_set():
return True
......@@ -58,91 +63,98 @@ class XrDriver(_Driver):
return True
def Disconnect(self) -> bool:
LOGGER.info(f"Disconnect[{self}]")
with self.__lock:
self.__terminate.set()
return True
def GetInitialConfig(self) -> List[Tuple[str, Any]]:
LOGGER.info(f"GetInitialConfig[{self}]")
with self.__lock:
return []
#pylint: disable=dangerous-default-value
def GetConfig(self, resource_keys : List[str] = []) -> List[Tuple[str, Union[Any, None, Exception]]]:
LOGGER.info(f"GetConfig[{self}]: {resource_keys=}")
chk_type('resources', resource_keys, list)
constellation = self.__cm_connection.get_constellation_by_hub_name(self.__hub_module_name)
if constellation:
self.__constellation = constellation
return [(f"/endpoints/endpoint[{ifname}]", {'uuid': ifname, 'type': 'optical', 'sample_types': {}}) for ifname in constellation.ifnames()]
else:
return []
# Empty resource_keys means all resources. As we only have endpoints, we ignore parameter and always
# return everything.
with self.__lock:
constellation = self.__cm_connection.get_constellation_by_hub_name(self.__hub_module_name)
if constellation:
self.__constellation = constellation
return [(f"/endpoints/endpoint[{ifname}]", {'uuid': ifname, 'type': 'optical', 'sample_types': {}}) for ifname in constellation.ifnames()]
else:
return []
def SetConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
LOGGER.info(f"SetConfig {resources=}")
LOGGER.info(f"SetConfig[{self}]: {resources=}")
# Logged config seems like:
#[('/service[52ff5f0f-fda4-40bd-a0b1-066f4ff04079:optical]', '{"capacity_unit": "GHz", "capacity_value": 1, "direction": "UNIDIRECTIONAL", "input_sip": "XR HUB 1|XR-T4", "layer_protocol_name": "PHOTONIC_MEDIA", "layer_protocol_qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC", "output_sip": "XR LEAF 1|XR-T1", "uuid": "52ff5f0f-fda4-40bd-a0b1-066f4ff04079:optical"}')]
#[('/service[52ff5f0f-fda4-40bd-a0b1-066f4ff04079:optical]', '{"capacity_unit": "GHz", "capacity_value": 1, "direction": "UNIDIRECTIONAL", "input_sip": "XR HUB 1|XR-T4", "layer_protocol_name": "PHOTONIC_MEDIA", "layer_protocol_qualifier": "tapi-photonic-media:PHOTONIC_LAYER_QUALIFIER_NMC", "output_sip": "XR LEAF 1|XR-T1", "uuid": "52ff5f0f-fda4-40bd-a0b1-066f4ff04079:optical"}')]
if self.__constellation is None:
self.__constellation = self.__cm_connection.get_constellation_by_hub_name(self.__hub_module_name)
if self.__constellation is None:
LOGGER.error("SetConfig: no valid constellation")
return [False] * len(resources)
with self.__lock:
if self.__constellation is None:
self.__constellation = self.__cm_connection.get_constellation_by_hub_name(self.__hub_module_name)
if self.__constellation is None:
LOGGER.error("SetConfig: no valid constellation")
return [False] * len(resources)
results = []
if len(resources) == 0:
return results
for key, config in resources:
service_uuid = self.__cm_connection.service_uuid(key)
if service_uuid:
config = json.loads(config)
results.append(tf.set_config_for_service(self.__cm_connection, self.__constellation, service_uuid, config))
else:
results.append(False)
results = []
if len(resources) == 0:
return results
for key, config in resources:
service_uuid = self.__cm_connection.service_uuid(key)
if service_uuid:
config = json.loads(config)
results.append(tf.set_config_for_service(self.__cm_connection, self.__constellation, service_uuid, config))
else:
results.append(False)
return results
def DeleteConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]:
LOGGER.info(f"DeleteConfig {resources=}")
LOGGER.info(f"DeleteConfig[{self}]: {resources=}")
# Input looks like:
# resources=[('/service[c8a35e81-88d8-4468-9afc-a8abd92a64d0:optical]', '{"uuid": "c8a35e81-88d8-4468-9afc-a8abd92a64d0:optical"}')]
results = []
if len(resources) == 0:
return results
# Temporary dummy version
for key, _config in resources:
service_uuid = self.__cm_connection.service_uuid(key)
if service_uuid:
connection = self.__cm_connection.get_connection_by_teraflow_uuid(service_uuid)
if connection is None:
LOGGER.info(f"DeleteConfig: Connection {service_uuid} does not exist, delete is no-op")
results.append(True)
else:
was_deleted = self.__cm_connection.delete_connection(connection.href)
if was_deleted:
LOGGER.info(f"DeleteConfig: Connection {service_uuid} deleted (was {str(connection)})")
with self.__lock:
results = []
if len(resources) == 0:
return results
# Temporary dummy version
for key, _config in resources:
service_uuid = self.__cm_connection.service_uuid(key)
if service_uuid:
connection = self.__cm_connection.get_connection_by_teraflow_uuid(service_uuid)
if connection is None:
LOGGER.info(f"DeleteConfig: Connection {service_uuid} does not exist, delete is no-op")
results.append(True)
else:
LOGGER.info(f"DeleteConfig: Connection {service_uuid} delete failure (was {str(connection)})")
if self.__constellation.is_vti_mode():
active_tc = self.__cm_connection.get_transport_capacity_by_teraflow_uuid(service_uuid)
if active_tc is not None:
if self.__cm_connection.delete_transport_capacity(active_tc.href):
LOGGER.info(f"DeleteConfig: Transport Capacity {active_tc} deleted")
else:
LOGGER.error(f"DeleteConfig: Transport Capacity {active_tc} delete failure")
results.append(was_deleted)
else:
results.append(False)
was_deleted = self.__cm_connection.delete_connection(connection.href)
if was_deleted:
LOGGER.info(f"DeleteConfig: Connection {service_uuid} deleted (was {str(connection)})")
else:
LOGGER.info(f"DeleteConfig: Connection {service_uuid} delete failure (was {str(connection)})")
if self.__constellation.is_vti_mode():
active_tc = self.__cm_connection.get_transport_capacity_by_teraflow_uuid(service_uuid)
if active_tc is not None:
if self.__cm_connection.delete_transport_capacity(active_tc.href):
LOGGER.info(f"DeleteConfig: Transport Capacity {active_tc} deleted")
else:
LOGGER.error(f"DeleteConfig: Transport Capacity {active_tc} delete failure")
results.append(was_deleted)
else:
results.append(False)
return results
return results
def SubscribeState(self, subscriptions : List[Tuple[str, float, float]]) -> List[Union[bool, Exception]]:
# Not supported
......
This diff is collapsed.
[
{
"href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd",
"hubModule": {
"href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd/hubModule",
"id": "519cc31f-b736-4e4c-b78d-600562d92911",
"parentId": "233e169b-5d88-481d-bfe2-c909a2a859dd",
"rt": [
"cm.xr-network.hubModule"
],
"state": {
"endpoints": [
{
"hostPort": {
"chassisId": "192.168.100.1",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-1/0/0:0",
"portId": "et-1/0/0:0",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:00:11",
"sysName": "SanJose"
},
"moduleIf": {
"clientIfAid": "XR-T1",
"clientIfColId": 1,
"clientIfPortSpeed": 100
}
},
{
"hostPort": {
"chassisId": "192.168.100.1",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-1/0/0:1",
"portId": "et-1/0/0:1",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:00:12",
"sysName": "SanJose"
},
"moduleIf": {
"clientIfAid": "XR-T2",
"clientIfColId": 2,
"clientIfPortSpeed": 100
}
},
{
"hostPort": {
"chassisId": "192.168.100.1",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-1/0/0:2",
"portId": "et-1/0/0:2",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:00:13",
"sysName": "SanJose"
},
"moduleIf": {
"clientIfAid": "XR-T3",
"clientIfColId": 3,
"clientIfPortSpeed": 100
}
},
{
"hostPort": {
"chassisId": "192.168.100.1",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-1/0/0:3",
"portId": "et-1/0/0:3",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:00:14",
"sysName": "SanJose"
},
"moduleIf": {
"clientIfAid": "XR-T4",
"clientIfColId": 4,
"clientIfPortSpeed": 100
}
}
],
"lifecycleState": "configured",
"module": {
"baudRate": 50,
"capacity": 400,
"clientPortMode": "ethernet",
"configuredRole": "auto",
"constellationFrequency": 192000000,
"currentRole": "hub",
"fiberConnectionMode": "dual",
"frequencyCtrl": "xr",
"macAddress": "00:0B:F8:00:00:01",
"modulation": "16QAM",
"moduleId": "d859de3c-c463-4be5-7a8d-a198275f10f4",
"moduleName": "XR HUB 1",
"ncoFrequency": 0,
"operatingFrequency": 192000000,
"roleStatus": "ready",
"serialNumber": "000000009",
"trafficMode": "L1Mode",
"txPowerTargetPerDsc": -6.4
}
}
},
"id": "233e169b-5d88-481d-bfe2-c909a2a859dd",
"leafModules": [
{
"href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd/leafModules/7e9da66b-8bf8-4eea-b4a7-045e5ba3bfd8",
"id": "7e9da66b-8bf8-4eea-b4a7-045e5ba3bfd8",
"parentId": "233e169b-5d88-481d-bfe2-c909a2a859dd",
"rt": [
"cm.xr-network.leafModule"
],
"state": {
"endpoints": [
{
"hostPort": {
"chassisId": "192.168.101.1",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-1/0/0:0",
"portId": "et-1/0/0:0",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:11:01",
"sysName": "PaloAlto"
},
"moduleIf": {
"clientIfAid": "XR-T1",
"clientIfColId": 1,
"clientIfPortSpeed": 100
}
}
],
"lifecycleState": "configured",
"module": {
"baudRate": 50,
"capacity": 100,
"clientPortMode": "ethernet",
"configuredRole": "auto",
"constellationFrequency": 192000000,
"currentRole": "leaf",
"fiberConnectionMode": "dual",
"frequencyCtrl": "xr",
"macAddress": "00:0B:F8:00:01:01",
"maxAllowedDSCs": 4,
"modulation": "16QAM",
"moduleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c",
"moduleName": "XR LEAF 1",
"ncoFrequency": 0,
"operatingFrequency": 192000000,
"roleStatus": "ready",
"serialNumber": "00000000B",
"trafficMode": "L1Mode",
"txPowerTargetPerDsc": -6.4
}
}
},
{
"href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd/leafModules/7473b336-ef92-4508-b260-c096d05e4943",
"id": "7473b336-ef92-4508-b260-c096d05e4943",
"parentId": "233e169b-5d88-481d-bfe2-c909a2a859dd",
"rt": [
"cm.xr-network.leafModule"
],
"state": {
"endpoints": [
{
"hostPort": {
"chassisId": "192.168.101.2",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-2/0/0:0",
"portId": "et-2/0/0:0",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:12:01",
"sysName": "Cupertino"
},
"moduleIf": {
"clientIfAid": "XR-T1",
"clientIfColId": 1,
"clientIfPortSpeed": 100
}
}
],
"lifecycleState": "configured",
"module": {
"baudRate": 50,
"capacity": 100,
"clientPortMode": "ethernet",
"configuredRole": "auto",
"constellationFrequency": 192000000,
"currentRole": "leaf",
"fiberConnectionMode": "dual",
"frequencyCtrl": "xr",
"macAddress": "00:0B:F8:00:01:02",
"maxAllowedDSCs": 4,
"modulation": "16QAM",
"moduleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40",
"moduleName": "XR LEAF 2",
"ncoFrequency": 0,
"operatingFrequency": 192000000,
"roleStatus": "ready",
"serialNumber": "00000000C",
"trafficMode": "L1Mode",
"txPowerTargetPerDsc": -6.4
}
}
}
],
"reachableModules": [
{
"href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd/reachableModules/58785cd9-c642-43e4-a8b5-6d136acd8ae5",
"id": "58785cd9-c642-43e4-a8b5-6d136acd8ae5",
"parentId": "233e169b-5d88-481d-bfe2-c909a2a859dd",
"rt": [
"cm.xr-network.reachableModule"
],
"state": {
"discoveredTime": "2022-06-28T09:04:08Z",
"endpoints": [
{
"hostPort": {
"chassisId": "192.168.101.3",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-3/0/0:0",
"portId": "et-3/0/0:0",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:13:01",
"sysName": "Sunnnyvale"
},
"moduleIf": {
"clientIfAid": "XR-T1",
"clientIfColId": 1,
"clientIfPortSpeed": 100
}
}
],
"module": {
"baudRate": 50,
"capacity": 100,
"clientPortMode": "ethernet",
"configuredRole": "auto",
"constellationFrequency": 193000000,
"currentRole": "leaf",
"fiberConnectionMode": "dual",
"frequencyCtrl": "xr",
"macAddress": "00:0B:F8:00:01:03",
"modulation": "16QAM",
"moduleId": "572b2d8a-8d0b-40a0-5823-e53041ca2194",
"moduleName": "XR LEAF 3",
"ncoFrequency": 0,
"operatingFrequency": 193000000,
"roleStatus": "ready",
"serialNumber": "00000000D",
"trafficMode": "L1Mode",
"txPowerTargetPerDsc": -6.4
}
}
},
{
"href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd/reachableModules/be85d276-6f30-4c7b-9f63-de8679dfab85",
"id": "be85d276-6f30-4c7b-9f63-de8679dfab85",
"parentId": "233e169b-5d88-481d-bfe2-c909a2a859dd",
"rt": [
"cm.xr-network.reachableModule"
],
"state": {
"discoveredTime": "2022-06-28T09:04:05Z",
"endpoints": [
{
"hostPort": {
"chassisId": "192.168.101.1",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-1/0/0:0",
"portId": "et-1/0/0:0",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:11:01",
"sysName": "PaloAlto"
},
"moduleIf": {
"clientIfAid": "XR-T1",
"clientIfColId": 1,
"clientIfPortSpeed": 100
}
}
],
"module": {
"baudRate": 50,
"capacity": 100,
"clientPortMode": "ethernet",
"configuredRole": "auto",
"constellationFrequency": 192000000,
"currentRole": "leaf",
"fiberConnectionMode": "dual",
"frequencyCtrl": "xr",
"macAddress": "00:0B:F8:00:01:01",
"modulation": "16QAM",
"moduleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c",
"moduleName": "XR LEAF 1",
"ncoFrequency": 0,
"operatingFrequency": 192000000,
"roleStatus": "ready",
"serialNumber": "00000000B",
"trafficMode": "L1Mode",
"txPowerTargetPerDsc": -6.4
}
}
},
{
"href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd/reachableModules/212cf331-c133-4321-8e74-023549b9afee",
"id": "212cf331-c133-4321-8e74-023549b9afee",
"parentId": "233e169b-5d88-481d-bfe2-c909a2a859dd",
"rt": [
"cm.xr-network.reachableModule"
],
"state": {
"discoveredTime": "2022-06-28T09:04:06Z",
"endpoints": [
{
"hostPort": {
"chassisId": "192.168.101.2",
"chassisIdSubtype": "networkAddress",
"portDescr": "et-2/0/0:0",
"portId": "et-2/0/0:0",
"portIdSubtype": "interfaceName",
"portSourceMAC": "58:00:BB:00:12:01",
"sysName": "Cupertino"
},
"moduleIf": {
"clientIfAid": "XR-T1",
"clientIfColId": 1,
"clientIfPortSpeed": 100
}
}
],
"module": {
"baudRate": 50,
"capacity": 100,
"clientPortMode": "ethernet",
"configuredRole": "auto",
"constellationFrequency": 192000000,
"currentRole": "leaf",
"fiberConnectionMode": "dual",
"frequencyCtrl": "xr",
"macAddress": "00:0B:F8:00:01:02",
"modulation": "16QAM",
"moduleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40",
"moduleName": "XR LEAF 2",
"ncoFrequency": 0,
"operatingFrequency": 192000000,
"roleStatus": "ready",
"serialNumber": "00000000C",
"trafficMode": "L1Mode",
"txPowerTargetPerDsc": -6.4
}
}
}
],
"rt": [
"cm.xr-network"
],
"state": {
"constellationFrequency": 192000000,
"controlLinks": [
{
"conState": "active",
"destinationModuleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c",
"lastConStateChange": "2022-06-28T09:04:05Z",
"sourceModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4"
},
{
"conState": "active",
"destinationModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4",
"lastConStateChange": "2022-06-28T09:04:05Z",
"sourceModuleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c"
},
{
"conState": "active",
"destinationModuleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40",
"lastConStateChange": "2022-06-28T09:04:06Z",
"sourceModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4"
},
{
"conState": "active",
"destinationModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4",
"lastConStateChange": "2022-06-28T09:04:05Z",
"sourceModuleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40"
}
],
"lifecycleState": "configured",
"modulation": "16QAM"
}
}
]
#pylint: disable=invalid-name, missing-function-docstring, line-too-long, logging-fstring-interpolation, missing-class-docstring, missing-module-docstring
import inspect
import os
import requests_mock
#from ..tf_service import TFService
from ..cm_connection import CmConnection
access_token = r'{"access_token":"eyI3...","expires_in":3600,"refresh_expires_in":0,"refresh_token":"ey...","token_type":"Bearer","not-before-policy":0,"session_state":"f6e235c4-4ca4-4258-bede-4f2b7125adfb","scope":"profile email offline_access"}'
resources = os.path.join(os.path.dirname(os.path.abspath(inspect.stack()[0][1])), "resources")
with open(os.path.join(resources, "constellations-expanded.json"), "r", encoding="UTF-8") as f:
res_constellations = f.read()
with open(os.path.join(resources, "constellation-by-name-hub1.json"), "r", encoding="UTF-8") as f:
res_constellation_by_name_hub1 = f.read()
def mock_cm_connectivity():
m = requests_mock.Mocker()
m.post('https://127.0.0.1:9999/realms/xr-cm/protocol/openid-connect/token', text=access_token)
return m
def test_cmc_connect():
# Valid access token
with requests_mock.Mocker() as m:
m.post('https://127.0.0.1:9999/realms/xr-cm/protocol/openid-connect/token', text=access_token)
cm = CmConnection("127.0.0.1", 9999, "xr-user", "xr-password", tls_verify=False)
assert cm.Connect()
# Valid JSON but no access token
with requests_mock.Mocker() as m:
m.post('https://127.0.0.1:9999/realms/xr-cm/protocol/openid-connect/token', text=r'{"a": "b"}')
cm = CmConnection("127.0.0.1", 9999, "xr-user", "xr-password", tls_verify=False)
assert not cm.Connect()
# Invalid JSON
with requests_mock.Mocker() as m:
m.post('https://127.0.0.1:9999/realms/xr-cm/protocol/openid-connect/token', text=r'}}}')
cm = CmConnection("127.0.0.1", 9999, "xr-user", "xr-password", tls_verify=False)
assert not cm.Connect()
with requests_mock.Mocker() as m:
# No mock present for the destination
cm = CmConnection("127.0.0.1", 9999, "xr-user", "xr-password", tls_verify=False)
assert not cm.Connect()
def test_cmc_get_constellations():
with mock_cm_connectivity() as m:
m.get("https://127.0.0.1:9999/api/v1/ns/xr-networks?content=expanded", text=res_constellations)
cm = CmConnection("127.0.0.1", 9999, "xr-user", "xr-password", tls_verify=False)
assert cm.Connect()
# List all constellations
constellations = cm.list_constellations()
assert len(constellations) == 2
cids = [c.constellation_id for c in constellations]
assert cids == ["6774cc4e-b0b1-43a1-923f-80fb1bec094b", "233e169b-5d88-481d-bfe2-c909a2a859dd"]
ifnames = [c.ifnames() for c in constellations]
assert ifnames == [['XR HUB 2|XR-T1', 'XR HUB 2|XR-T2', 'XR HUB 2|XR-T3', 'XR HUB 2|XR-T4', 'XR LEAF 3|XR-T1'],
['XR HUB 1|XR-T1', 'XR HUB 1|XR-T2', 'XR HUB 1|XR-T3', 'XR HUB 1|XR-T4', 'XR LEAF 1|XR-T1', 'XR LEAF 2|XR-T1']]
# Get constellation by hub module name
m.get("https://127.0.0.1:9999/api/v1/ns/xr-networks?content=expanded&content=expanded&q=%7B%22hubModule.state.module.moduleName%22%3A+%22XR+HUB+1%22%7D", text=res_constellation_by_name_hub1)
constellation = cm.get_constellation_by_hub_name("XR HUB 1")
assert constellation
assert constellation.ifnames() == ['XR HUB 1|XR-T1', 'XR HUB 1|XR-T2', 'XR HUB 1|XR-T3', 'XR HUB 1|XR-T4', 'XR LEAF 1|XR-T1', 'XR LEAF 2|XR-T1']
assert constellation.constellation_id == "233e169b-5d88-481d-bfe2-c909a2a859dd"
\ No newline at end of file
......@@ -12,18 +12,12 @@ def test_constellation_json():
with open(os.path.join(resources, "constellations-expanded.json"), "r", encoding="UTF-8") as f:
j = json.load(f)
# A pre-planned constellation without endpoints
constellation = Constellation(j[0])
assert constellation.constellation_id == "169860ee-c1b8-4ae1-8f6e-81920a6ee09d"
assert not constellation.is_vti_mode()
assert not constellation.ifnames()
# Proper constellation with endpoints
constellation = Constellation(j[1])
assert constellation.constellation_id == "84d9b09c-017d-4ac5-b8cd-d1102db1e070"
assert constellation.constellation_id == "233e169b-5d88-481d-bfe2-c909a2a859dd"
assert not constellation.is_vti_mode()
print(constellation.ifnames())
assert ['XR HUB 2|XR-T4', 'XR HUB 2|XR-T1', 'XR HUB 2|XR-T2', 'XR HUB 2|XR-T3', 'XR LEAF 3|XR-T1'] == constellation.ifnames()
assert ['XR HUB 1|XR-T1', 'XR HUB 1|XR-T2', 'XR HUB 1|XR-T3', 'XR HUB 1|XR-T4', 'XR LEAF 1|XR-T1', 'XR LEAF 2|XR-T1'] == constellation.ifnames()
# Remove mandatory key, will raise an exception
del j[0]["hubModule"]["state"]
......
#pylint: disable=invalid-name, missing-function-docstring, line-too-long, logging-fstring-interpolation, missing-class-docstring, missing-module-docstring
import inspect
import os
import json
import requests_mock
import traceback
from ..cm_connection import CmConnection
from ..tf import set_config_for_service
access_token = r'{"access_token":"eyI3...","expires_in":3600,"refresh_expires_in":0,"refresh_token":"ey...","token_type":"Bearer","not-before-policy":0,"session_state":"f6e235c4-4ca4-4258-bede-4f2b7125adfb","scope":"profile email offline_access"}'
resources = os.path.join(os.path.dirname(os.path.abspath(inspect.stack()[0][1])), "resources")
with open(os.path.join(resources, "constellation-by-name-hub1.json"), "r", encoding="UTF-8") as f:
res_constellation_by_name_hub1 = f.read()
with open(os.path.join(resources, "connections-expanded.json"), "r", encoding="UTF-8") as f:
j = json.load(f)
# Fake reference data to have the name this test case needs for the given teraflow UUID
# (=no need for too large set of reference material)
j[0]["state"]["name"] = "TF:12345ABCDEFGHIJKLMN"
res_connection_by_name_json = [j[0]] # Single item list
def mock_cm():
m = requests_mock.Mocker()
m.post('https://127.0.0.1:9999/realms/xr-cm/protocol/openid-connect/token', text=access_token)
m.get("https://127.0.0.1:9999/api/v1/ns/xr-networks?content=expanded&content=expanded&q=%7B%22hubModule.state.module.moduleName%22%3A+%22XR+HUB+1%22%7D", text=res_constellation_by_name_hub1)
m.post("https://127.0.0.1:9999/api/v1/ncs/network-connections", text='[{"href":"/network-connections/c3b31608-0bb7-4a4f-9f9a-88b24a059432","rt":["cm.network-connection"]}]', status_code=202)
return m
uuid = "12345ABCDEFGHIJKLMN"
config = {
"input_sip": "XR HUB 1|XR-T4;",
"output_sip": "XR LEAF 1|XR-T1",
"capacity_value": 125,
"capacity_unit": "gigabit"
}
def _validate_result(result, expect):
if isinstance(result, Exception):
traceback.print_exception(result)
assert result is expect # Not, "is", not ==, we want type checking in this case, as also an exception can be returned (as return value)
def test_xr_set_config():
with mock_cm() as m:
cm = CmConnection("127.0.0.1", 9999, "xr-user", "xr-password", tls_verify=False)
assert cm.Connect()
constellation = cm.get_constellation_by_hub_name("XR HUB 1")
assert constellation
result = set_config_for_service(cm, constellation, uuid, config)
_validate_result(result, True)
called_mocks = [(r._request.method, r._request.url) for r in m._adapter.request_history]
expected_mocks = [
('POST', 'https://127.0.0.1:9999/realms/xr-cm/protocol/openid-connect/token'), # Authentication
('GET', 'https://127.0.0.1:9999/api/v1/ns/xr-networks?content=expanded&content=expanded&q=%7B%22hubModule.state.module.moduleName%22%3A+%22XR+HUB+1%22%7D'), # Hub module by name
('GET', 'https://127.0.0.1:9999/api/v1/ncs/network-connections?content=expanded&q=%7B%22state.name%22%3A+%22TF%3A12345ABCDEFGHIJKLMN%22%7D'), # Get by name, determine update or create
('POST', 'https://127.0.0.1:9999/api/v1/ncs/network-connections') # Create
]
assert called_mocks == expected_mocks
def test_xr_set_config_update_case():
with mock_cm() as m:
cm = CmConnection("127.0.0.1", 9999, "xr-user", "xr-password", tls_verify=False)
assert cm.Connect()
constellation = cm.get_constellation_by_hub_name("XR HUB 1")
assert constellation
# Fake existing service (--> update path is taken)
m.get("https://127.0.0.1:9999/api/v1/ncs/network-connections?content=expanded&q=%7B%22state.name%22%3A+%22TF%3A12345ABCDEFGHIJKLMN%22%7D", json=res_connection_by_name_json)
# Delete endpoint that is no longer necessary
m.delete("https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03/endpoints/1d58ba8f-4d51-4213-83e1-97a0e0bdd388", text="", status_code = 202)
# Update changed endpoint
m.put("https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03/endpoints/230516d0-7e38-44b1-b174-1ba7d4454ee6", text="", status_code = 202)
# Create the newly added endpoint
m.post("https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03/endpoints", json=[{"href":"/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03/endpoint/somethingplausible","rt":["plausible"]}], status_code=202)
# Update the connection itself
m.put("https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03", text="", status_code=202)
result = set_config_for_service(cm, constellation, uuid, config)
_validate_result(result, True)
called_mocks = [(r._request.method, r._request.url) for r in m._adapter.request_history]
expected_mocks = [
('POST', 'https://127.0.0.1:9999/realms/xr-cm/protocol/openid-connect/token'), # Authentication
('GET', 'https://127.0.0.1:9999/api/v1/ns/xr-networks?content=expanded&content=expanded&q=%7B%22hubModule.state.module.moduleName%22%3A+%22XR+HUB+1%22%7D'), # Hub module by name
('GET', 'https://127.0.0.1:9999/api/v1/ncs/network-connections?content=expanded&q=%7B%22state.name%22%3A+%22TF%3A12345ABCDEFGHIJKLMN%22%7D'), # Get by name, determine update or create
('DELETE', 'https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03/endpoints/1d58ba8f-4d51-4213-83e1-97a0e0bdd388'), # Delete unnecessary endpoint
('PUT', 'https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03/endpoints/230516d0-7e38-44b1-b174-1ba7d4454ee6'), # Update changed endpoint
('POST', 'https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03/endpoints'), # Add new endpoint
('PUT', 'https://127.0.0.1:9999/api/v1/ncs/network-connections/4505d5d3-b2f3-40b8-8ec2-4a5b28523c03') # Update the connection itself
]
assert called_mocks == expected_mocks
......@@ -45,10 +45,10 @@ def set_config_for_service(cm_connection: CmConnection, constellation: Constella
connection = Connection(from_tf_service=service)
href = cm_connection.create_or_update_connection(connection)
if href:
LOGGER.info(f"set_config_for_service: Created service {uuid} as {href} ({connection=})")
LOGGER.info(f"set_config_for_service: Created service {uuid} as {href} (connection={str(connection)})")
return True
else:
LOGGER.error(f"set_config_for_service: Service creation failure for {uuid} ({connection=})")
LOGGER.error(f"set_config_for_service: Service creation failure for {uuid} (connection={str(connection)})")
return False
# Intentionally catching all exceptions, as they are stored in a list as return values
# by the caller
......
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