diff --git a/src/device/requirements.in b/src/device/requirements.in index e5aaddecb4901da55a411d83c8c1df26f8d47069..0902a65793813c4f22a1b27b83e89e085ca64a5a 100644 --- a/src/device/requirements.in +++ b/src/device/requirements.in @@ -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. diff --git a/src/device/service/drivers/xr/XrDriver.py b/src/device/service/drivers/xr/XrDriver.py index c3325b14f3732483a675d6e58768f9b01aaa2d6d..51fd29ad11af5ccdad7e5c49e7d069a1bf2e8ffb 100644 --- a/src/device/service/drivers/xr/XrDriver.py +++ b/src/device/service/drivers/xr/XrDriver.py @@ -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 diff --git a/src/device/service/drivers/xr/cm/cm_connection.py b/src/device/service/drivers/xr/cm/cm_connection.py index f86bb3179261309c2f263957a50a89c9d352195f..1ea71cd13f3b7ea70ecceef1b19a98e8fd9414f2 100644 --- a/src/device/service/drivers/xr/cm/cm_connection.py +++ b/src/device/service/drivers/xr/cm/cm_connection.py @@ -1,8 +1,9 @@ #pylint: disable=invalid-name, missing-function-docstring, line-too-long, logging-fstring-interpolation, missing-class-docstring, missing-module-docstring +import collections.abc import logging import json import time -from typing import Optional, List #Any, Iterator, , Union +from typing import Optional, List, Dict, Union import re import requests import urllib3 @@ -31,6 +32,69 @@ class ExpiringValue: else: return False +class UnexpectedEmptyBody(Exception): + pass + +class HttpResult: + def __init__(self, method: str, url: str, params: Dict[str, any] = None): + self.method = method + self.url = url + self.text = None + self.json = None + self.status_code = None + self.params = params + self.exception = None + + def __str__(self): + status_code = self.status_code if self.status_code is not None else "<not executed>" + return f"{self.method} {self.url} {self.params}, status {status_code}" + + def process_http_response(self, response: requests.Response, permit_empty_body:bool = False): + LOGGER.info(f"process_http_response(): {self.method}: {self.url} qparams={self.params} ==> {response.status_code}") # FIXME: params + self.status_code = response.status_code + if response.content != b'null' and len(response.text): + self.text = response.text + + try: + r_json = json.loads(response.text) + self.json = r_json + except json.JSONDecodeError as json_err: + LOGGER.info(f"{self.method}: {self.url} ==> response json decode error: {str(json_err)}") + self.exception = json_err + elif not permit_empty_body: + raise UnexpectedEmptyBody(f"No body in HTTP response for {self.method} {self.url} (status code {response.status_code}") + + def __bool__(self): + # Error codes start at 400, codes below it are successes + return self.status_code is not None and self.text is not None and self.status_code < 400 and self.exception is None + + def is_valid_with_status_ignore_body(self, expected_status_code: int) -> bool: + return self.status_code is not None and self.status_code == expected_status_code and self.exception is None + + def is_valid_json_with_status(self, expected_status_code: int) -> bool: + return bool(self) and self.status_code == expected_status_code and self.json is not None + + def is_valid_json_list_with_status(self, expected_status_code: int, min_entries=-1, max_entries=-1) -> bool: + if not self.is_valid_json_with_status(expected_status_code): + return False + if not isinstance(self.json, collections.abc.Sequence): + return False + + if min_entries >=0 and len(self.json) < min_entries: + return False + + if max_entries >=0 and len(self.json) > max_entries: + return False + return True + + def is_valid_json_obj_with_status(self, expected_status_code: int) -> bool: + if not self.is_valid_json_with_status(expected_status_code): + return False + if not isinstance(self.json, collections.abc.Mapping): + return False + + return True + class CmConnection: def __init__(self, address: str, port: int, username: str, password: str, timeout=30, tls_verify=True) -> None: self.__tls_verify = tls_verify @@ -43,78 +107,51 @@ class CmConnection: self.__cm_root = 'https://' + address + ':' + str(port) self.__access_token = None - def __post_w_headers(self, path, data, headers, data_as_json=True): - url = self.__cm_root + path + def __perform_request(self, http_result: HttpResult, permit_empty_body: bool, fn, *args, **kwargs): try: - if data_as_json: - response = requests.post(url, headers=headers, json=data, timeout=self.__timeout, verify=self.__tls_verify) - else: - response = requests.post(url, headers=headers, data=data, timeout=self.__timeout, verify=self.__tls_verify) - - LOGGER.info(f"POST: {url} ==> {response.status_code=}, {response.text=}") - resp = json.loads(response.text) - return (response.status_code, resp) - except requests.exceptions.Timeout: - LOGGER.info(f"POST: {url} ==> timeout") - return None - except json.JSONDecodeError as json_err: - LOGGER.info(f"POST: {url} ==> response json decode error: {str(json_err)}") - return None + response = fn(*args, **kwargs) + http_result.process_http_response(response, permit_empty_body) + except requests.exceptions.Timeout as e: + LOGGER.info(f"{http_result} ==> timeout") + http_result.exception = e except Exception as e: # pylint: disable=broad-except es=str(e) - LOGGER.info(f"POST: {url} ==> unexpected exception: {es}") - return None + LOGGER.info(f"{http_result} ==> unexpected exception: {es}") + http_result.exception = e + return http_result + + def __post_w_headers(self, path, data, headers, data_as_json=True) -> HttpResult: + url = self.__cm_root + path + rv = HttpResult("POST", url) + if data_as_json: + self.__perform_request(rv, False, requests.post, url, headers=headers, json=data, timeout=self.__timeout, verify=self.__tls_verify) + else: + self.__perform_request(rv, False, requests.post, url, headers=headers, data=data, timeout=self.__timeout, verify=self.__tls_verify) + return rv - def __post(self, path, data, data_as_json=True): + def __post(self, path, data, data_as_json=True) -> HttpResult: return self.__post_w_headers(path, data, self.__http_headers(), data_as_json=data_as_json) - def __put(self, path, data, data_as_json=True): + def __put(self, path: str, data: Union[str,Dict[str, any]], data_as_json:bool =True, permit_empty_body:bool =True) -> HttpResult: url = self.__cm_root + path - headers = self.__http_headers() - try: - if data_as_json: - response = requests.put(url, headers=headers, json=data, timeout=self.__timeout, verify=self.__tls_verify) - else: - response = requests.put(url, headers=headers, data=data, timeout=self.__timeout, verify=self.__tls_verify) - - LOGGER.info(f"PUT: {url} ==> {response.status_code}") + rv = HttpResult("PUT", url) + if data_as_json: + self.__perform_request(rv, permit_empty_body, requests.put, url, headers=self.__http_headers(), json=data, timeout=self.__timeout, verify=self.__tls_verify) + else: + self.__perform_request(rv, permit_empty_body, requests.put, url, headers=self.__http_headers(), data=data, timeout=self.__timeout, verify=self.__tls_verify) + return rv - if response.content == b'null': - return (response.status_code, None) - resp = json.loads(response.text) - return (response.status_code, resp) - except requests.exceptions.Timeout: - LOGGER.info(f"PUT: {url} ==> timeout") - return None - except json.JSONDecodeError as json_err: - LOGGER.info(f"PUT: {url} ==> response json decode error: {str(json_err)}") - return None - except Exception as e: # pylint: disable=broad-except - es=str(e) - LOGGER.info(f"PUT: {url} ==> unexpected exception: {es}") - return None + def __get(self, path, params: Dict[str, any]=None) -> HttpResult: + url = self.__cm_root + path + rv = HttpResult("GET", url, params) + self.__perform_request(rv, False, requests.get, url, headers=self.__http_headers(), timeout=self.__timeout,verify=self.__tls_verify, params=params) + return rv - def __delete(self, path, data=None): + def __delete(self, path, data=None) -> HttpResult: url = self.__cm_root + path - headers = self.__http_headers() - try: - response = requests.delete(url, headers=headers, data=data, timeout=self.__timeout, verify=self.__tls_verify) - LOGGER.info(f"DELETE: {url} ==> {response.status_code}") - - if response.content == b'null': - return (response.status_code, None) - resp = json.loads(response.text) - return (response.status_code, resp) - except requests.exceptions.Timeout: - LOGGER.info(f"DELETE: {url} ==> timeout") - return None - except json.JSONDecodeError as json_err: - LOGGER.info(f"DELETE: {url} ==> response json decode error: {str(json_err)}") - return None - except Exception as e: # pylint: disable=broad-except - es=str(e) - LOGGER.info(f"DELETE: {url} ==> unexpected exception: {es}") - return None + rv = HttpResult("DELETE", url) + self.__perform_request(rv, True, requests.delete, url, headers=self.__http_headers(), data=data, timeout=self.__timeout, verify=self.__tls_verify) + return rv def __http_headers(self): self.__ensure_valid_access_token() @@ -123,24 +160,6 @@ class CmConnection: else: return {} - def __get_json(self, path, params=None): - url = self.__cm_root + path - try: - response = requests.get(url,headers=self.__http_headers(), timeout=self.__timeout,verify=self.__tls_verify, params=params) - LOGGER.info(f"GET: {url} {params=} ==> {response.status_code}") - resp = json.loads(response.text) - return (response.status_code, resp) - except requests.exceptions.Timeout: - LOGGER.info(f"GET: {url} {params=} ==> timeout") - return None - except json.JSONDecodeError as json_err: - LOGGER.info(f"GET: {url} {params=} ==> response json decode error: {str(json_err)}") - return None - except Exception as e: # pylint: disable=broad-except - es=str(e) - LOGGER.info(f"GET: {url} {params=} ==> unexpected exception: {es}") - return None - def __acquire_access_token(self): path = '/realms/xr-cm/protocol/openid-connect/token' req = { @@ -150,12 +169,20 @@ class CmConnection: "client_secret": "xr-web-client", "client_id": "xr-web-client" } - (status_code, response) = self.__post_w_headers(path, req, None, data_as_json=False) - if 200 != status_code or 'access_token' not in response: - LOGGER.error(f"Authentication failure, status code {status_code}, data {response}") + resp = self.__post_w_headers(path, req, None, data_as_json=False) + # Slightly more verbose check/logging of failures for authentication to help + # diagnose connectivity problems + if resp.status_code is None: + LOGGER.error("Failed to contact authentication API endpoint") + return False + if not resp.is_valid_json_obj_with_status(200): + LOGGER.error(f"Authentication failure, status code {resp.status_code}, data {resp.text}") + return False + if 'access_token' not in resp.json: + LOGGER.error(f"Authentication failure: missing access_token in JSON, status code {resp.status_code}, data {resp.text}") return False - access_token = response['access_token'] - expires = int(response["expires_in"]) if "expires_in" in response else 0 + access_token = resp.json['access_token'] + expires = int(resp.json["expires_in"]) if "expires_in" in resp.json else 0 LOGGER.info(f"Obtained access token {access_token}, expires in {expires}") self.__access_token = ExpiringValue(access_token, expires) return True @@ -168,10 +195,10 @@ class CmConnection: return self.__acquire_access_token() def list_constellations(self) -> List[Constellation]: - status_code, constellations = self.__get_json("/api/v1/ns/xr-networks?content=expanded") - if not constellations or status_code != 200: + r = self.__get("/api/v1/ns/xr-networks?content=expanded") + if not r.is_valid_json_list_with_status(200): return [] - return [Constellation(c) for c in constellations] + return [Constellation(c) for c in r.json] def get_constellation_by_hub_name(self, hub_module_name: str) -> Optional[Constellation]: @@ -179,25 +206,25 @@ class CmConnection: ('content', 'expanded'), ('q', '{"hubModule.state.module.moduleName": "' + hub_module_name + '"}') ] - status_code, constellations = self.__get_json("/api/v1/ns/xr-networks?content=expanded", params=qparams) - if not constellations or status_code != 200 or len(constellations) != 1: + r = self.__get("/api/v1/ns/xr-networks?content=expanded", params=qparams) + if not r.is_valid_json_list_with_status(200, 1, 1): return None - return Constellation(constellations[0]) + return Constellation(r.json[0]) def get_transport_capacities(self) -> List[TransportCapacity]: - status_code, tc = self.__get_json("/api/v1/ns/transport-capacities?content=expanded") - if not tc or status_code != 200: + r= self.__get("/api/v1/ns/transport-capacities?content=expanded") + if not r.is_valid_json_list_with_status(200): return [] - return [TransportCapacity(from_json=t) for t in tc] + return [TransportCapacity(from_json=t) for t in r.json] def get_transport_capacity_by_name(self, tc_name: str) -> Optional[Connection]: qparams = [ ('content', 'expanded'), ('q', '{"state.name": "' + tc_name + '"}') ] - r = self.__get_json("/api/v1/ns/transport-capacities?content=expanded", params=qparams) - if r and r[0] == 200 and len(r[1]) == 1: - return TransportCapacity(from_json=r[1][0]) + r = self.__get("/api/v1/ns/transport-capacities?content=expanded", params=qparams) + if not r.is_valid_json_list_with_status(200, 1, 1): + return TransportCapacity(from_json=r.json[0]) else: return None @@ -208,10 +235,10 @@ class CmConnection: # Create wants a list, so wrap connection to list tc_config = [tc.create_config()] resp = self.__post("/api/v1/ns/transport-capacities", tc_config) - if resp and resp[0] == 202 and len(resp[1]) == 1 and "href" in resp[1][0]: - tc.href = resp[1][0]["href"] + if resp.is_valid_json_list_with_status(202, 1, 1) and "href" in resp.json[0]: + tc.href = resp.json[0]["href"] LOGGER.info(f"Created transport-capcity {tc}") - #LOGGER.info(self.__get_json(f"/api/v1/ns/transport-capacities{tc.href}?content=expanded")) + #LOGGER.info(self.__get(f"/api/v1/ns/transport-capacities{tc.href}?content=expanded")) return tc.href else: return None @@ -220,11 +247,11 @@ class CmConnection: resp = self.__delete(f"/api/v1/ns/transport-capacities{href}") # Returns empty body - if resp and resp[0] == 202: + if resp.is_valid_with_status_ignore_body(202): LOGGER.info(f"Deleted transport-capacity {href=}") return True else: - LOGGER.info(f"Deleting transport-capacity {href=} failed, status {resp[0]}") + LOGGER.info(f"Deleting transport-capacity {href=} failed, status {resp.status_code}") return False def create_connection(self, connection: Connection) -> Optional[str]: @@ -232,8 +259,8 @@ class CmConnection: cfg = [connection.create_config()] resp = self.__post("/api/v1/ncs/network-connections", cfg) - if resp and resp[0] == 202 and len(resp[1]) == 1 and "href" in resp[1][0]: - connection.href = resp[1][0]["href"] + if resp.is_valid_json_list_with_status(202, 1, 1) and "href" in resp.json[0]: + connection.href = resp.json[0]["href"] LOGGER.info(f"Created connection {connection}") return connection.href else: @@ -252,7 +279,6 @@ class CmConnection: del cfg["endpoints"] if existing_connection is None: existing_connection = self.get_connection_by_href(href) - print(existing_connection) ep_deletes, ep_creates, ep_updates = connection.get_endpoint_updates(existing_connection) #print(ep_deletes) #print(ep_creates) @@ -261,7 +287,7 @@ class CmConnection: # Perform deletes for ep_href in ep_deletes: resp = self.__delete(f"/api/v1/ncs{ep_href}") - if resp and resp[0] == 202: + if resp.is_valid_with_status_ignore_body(202): LOGGER.info(f"update_connection: EP-UPDATE: Deleted connection endpoint {ep_href}") else: LOGGER.info(f"update_connection: EP-UPDATE: Failed to delete connection endpoint {ep_href}: {resp}") @@ -269,22 +295,22 @@ class CmConnection: # Update capacities for otherwise similar endpoints for ep_href, ep_cfg in ep_updates: resp = self.__put(f"/api/v1/ncs{ep_href}", ep_cfg) - if resp and resp[0] == 202: + if resp.is_valid_with_status_ignore_body(202): LOGGER.info(f"update_connection: EP-UPDATE: Updated connection endpoint {ep_href} with {ep_cfg}") else: LOGGER.info(f"update_connection: EP-UPDATE: Failed to update connection endpoint {ep_href} with {ep_cfg}: {resp}") # Perform adds resp = self.__post(f"/api/v1/ncs{href}/endpoints", ep_creates) - if resp and resp[0] == 202 and len(resp[1]) == len(ep_creates): - LOGGER.info(f"update_connection: EP-UPDATE: Created connection endpoints {resp[1]} with {ep_creates}") + if resp.is_valid_json_list_with_status(202, 1, 1) and "href" in resp.json[0]: + LOGGER.info(f"update_connection: EP-UPDATE: Created connection endpoints {resp.json[0]} with {ep_creates}") else: - LOGGER.info(f"update_connection: EP-UPDATE: Failed to create connection endpoints {resp[1]} with {ep_creates}: {resp}") + LOGGER.info(f"update_connection: EP-UPDATE: Failed to create connection endpoints {resp.json[0] if resp.json else None} with {ep_creates}: {resp}") # Connection update (excluding endpoints) resp = self.__put(f"/api/v1/ncs{href}", cfg) # Returns empty body - if resp and resp[0] == 202: + if resp.is_valid_with_status_ignore_body(202): LOGGER.info(f"update_connection: Updated connection {connection}") # Return href used for update to be consisten with create return href @@ -296,7 +322,7 @@ class CmConnection: resp = self.__delete(f"/api/v1/ncs{href}") #print(resp) # Returns empty body - if resp and resp[0] == 202: + if resp.is_valid_with_status_ignore_body(202): LOGGER.info(f"Deleted connection {href=}") return True else: @@ -306,7 +332,7 @@ class CmConnection: def create_or_update_connection(self, connection: Connection) -> Optional[str]: existing_connection = self.get_connection_by_name(connection.name) if existing_connection: - return self.update_connection(existing_connection.href, connection) + return self.update_connection(existing_connection.href, connection, existing_connection) else: return self.create_connection(connection) @@ -315,9 +341,9 @@ class CmConnection: ('content', 'expanded'), ('q', '{"state.name": "' + connection_name + '"}') ] - r = self.__get_json("/api/v1/ncs/network-connections", params=qparams) - if r and r[0] == 200 and len(r[1]) == 1: - return Connection(from_json=r[1][0]) + r = self.__get("/api/v1/ncs/network-connections", params=qparams) + if r.is_valid_json_list_with_status(200, 1, 1): + return Connection(from_json=r.json[0]) else: return None @@ -325,9 +351,9 @@ class CmConnection: qparams = [ ('content', 'expanded'), ] - r = self.__get_json(f"/api/v1/ncs{href}", params=qparams) - if r and r[0] == 200: - return Connection(from_json=r[1]) + r = self.__get(f"/api/v1/ncs{href}", params=qparams) + if r.is_valid_json_obj_with_status(200): + return Connection(from_json=r.json) else: return None @@ -335,9 +361,9 @@ class CmConnection: return self.get_connection_by_name(f"TF:{uuid}") def get_connections(self): - r = self.__get_json("/api/v1/ncs/network-connections?content=expanded") - if r and r[0] == 200: - return [Connection(from_json=c) for c in r[1]] + r = self.__get("/api/v1/ncs/network-connections?content=expanded") + if r.is_valid_json_list_with_status(200): + return [Connection(from_json=c) for c in r.json] else: return [] diff --git a/src/device/service/drivers/xr/cm/tests/resources/constellation-by-name-hub1.json b/src/device/service/drivers/xr/cm/tests/resources/constellation-by-name-hub1.json new file mode 100644 index 0000000000000000000000000000000000000000..061d6453edebc764a96fe3eaeace1168200b1a20 --- /dev/null +++ b/src/device/service/drivers/xr/cm/tests/resources/constellation-by-name-hub1.json @@ -0,0 +1,388 @@ +[ + { + "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" + } + } +] diff --git a/src/device/service/drivers/xr/cm/tests/resources/constellations-expanded.json b/src/device/service/drivers/xr/cm/tests/resources/constellations-expanded.json index c4aff84bf75fc48cd30ba0dd8180b030a35dd78e..cfe310f4b1340395d660f775d34086591a8e8827 100644 --- a/src/device/service/drivers/xr/cm/tests/resources/constellations-expanded.json +++ b/src/device/service/drivers/xr/cm/tests/resources/constellations-expanded.json @@ -1,946 +1,41 @@ [ { - "config": { - "constellationFrequency": 191000000, - "modulation": "16QAM", - "name": "FooConstellation" - }, - "href": "/xr-networks/169860ee-c1b8-4ae1-8f6e-81920a6ee09d", - "hubModule": { - "config": { - "module": { - "fiberConnectionMode": "dual", - "maxAllowedDSCs": 16, - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - }, - "selector": { - "moduleSelectorByModuleName": { - "moduleName": "p2mp_HUB2" - } - } - }, - "href": "/xr-networks/169860ee-c1b8-4ae1-8f6e-81920a6ee09d/hubModule", - "id": "ec41b4b3-b8bf-4903-8054-8f85891dc057", - "parentId": "169860ee-c1b8-4ae1-8f6e-81920a6ee09d", - "rt": [ - "cm.xr-network.hubModule" - ], - "state": { - "lifecycleState": "pendingConfiguration", - "module": { - "baudRate": 50, - "capacity": 400, - "clientPortMode": "ethernet", - "configuredRole": "auto", - "constellationFrequency": 0, - "currentRole": "unknown", - "fiberConnectionMode": "dual", - "frequencyCtrl": "xr", - "macAddress": "00:0B:F8:FF:00:01", - "modulation": "16QAM", - "moduleId": "d01099e6-fa38-40dd-5c0d-6e7097b3f691", - "moduleName": "p2mp_HUB2", - "ncoFrequency": 0, - "operatingFrequency": 0, - "roleStatus": "scanning", - "serialNumber": "000000002", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - "id": "169860ee-c1b8-4ae1-8f6e-81920a6ee09d", - "leafModules": [ - { - "config": { - "module": { - "fiberConnectionMode": "dual", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - }, - "selector": { - "moduleSelectorByModuleName": { - "moduleName": "p2mp_LEAF4" - } - } - }, - "href": "/xr-networks/169860ee-c1b8-4ae1-8f6e-81920a6ee09d/leafModules/169a434d-90c7-429a-928a-aef7013af715", - "id": "169a434d-90c7-429a-928a-aef7013af715", - "parentId": "169860ee-c1b8-4ae1-8f6e-81920a6ee09d", - "rt": [ - "cm.xr-network.leafModule" - ], - "state": { - "lifecycleState": "pendingConfiguration", - "module": { - "baudRate": 50, - "capacity": 100, - "clientPortMode": "ethernet", - "configuredRole": "auto", - "constellationFrequency": 0, - "currentRole": "unknown", - "fiberConnectionMode": "dual", - "frequencyCtrl": "xr", - "macAddress": "00:0B:F8:FF:00:06", - "modulation": "16QAM", - "moduleId": "d9580d90-1dbd-43d8-64d6-20afba0dbfe7", - "moduleName": "p2mp_LEAF4", - "ncoFrequency": 0, - "operatingFrequency": 0, - "roleStatus": "scanning", - "serialNumber": "000000006", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - } - ], - "rt": [ - "cm.xr-network" - ], - "state": { - "constellationFrequency": 0, - "lifecycleState": "pendingConfiguration", - "modulation": "16QAM", - "name": "FooConstellation" - } - }, - { - "href": "/xr-networks/84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "hubModule": { - "href": "/xr-networks/84d9b09c-017d-4ac5-b8cd-d1102db1e070/hubModule", - "id": "921bdde3-88e3-40e6-8f6a-d5fffb9909fa", - "parentId": "84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "rt": [ - "cm.xr-network.hubModule" - ], - "state": { - "endpoints": [ - { - "hostPort": { - "chassisId": "192.168.100.1", - "chassisIdSubtype": "networkAddress", - "portDescr": "et-2/0/0:3", - "portId": "et-2/0/0:3", - "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:24" - }, - "moduleIf": { - "clientIfAid": "XR-T4", - "clientIfColId": 4, - "clientIfPortSpeed": 100 - } - }, - { - "hostPort": { - "chassisId": "192.168.100.1", - "chassisIdSubtype": "networkAddress", - "portDescr": "et-2/0/0:0", - "portId": "et-2/0/0:0", - "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:21" - }, - "moduleIf": { - "clientIfAid": "XR-T1", - "clientIfColId": 1, - "clientIfPortSpeed": 100 - } - }, - { - "hostPort": { - "chassisId": "192.168.100.1", - "chassisIdSubtype": "networkAddress", - "portDescr": "et-2/0/0:1", - "portId": "et-2/0/0:1", - "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:22" - }, - "moduleIf": { - "clientIfAid": "XR-T2", - "clientIfColId": 2, - "clientIfPortSpeed": 100 - } - }, - { - "hostPort": { - "chassisId": "192.168.100.1", - "chassisIdSubtype": "networkAddress", - "portDescr": "et-2/0/0:2", - "portId": "et-2/0/0:2", - "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:23" - }, - "moduleIf": { - "clientIfAid": "XR-T3", - "clientIfColId": 3, - "clientIfPortSpeed": 100 - } - } - ], - "lifecycleState": "configured", - "module": { - "baudRate": 50, - "capacity": 400, - "clientPortMode": "ethernet", - "configuredRole": "auto", - "constellationFrequency": 193000000, - "currentRole": "hub", - "fiberConnectionMode": "dual", - "frequencyCtrl": "xr", - "macAddress": "00:0B:F8:00:00:02", - "modulation": "16QAM", - "moduleId": "3691e001-1e0c-44ae-5fd6-4f4acb8b945c", - "moduleName": "XR HUB 2", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000A", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - "id": "84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "leafModules": [ - { - "href": "/xr-networks/84d9b09c-017d-4ac5-b8cd-d1102db1e070/leafModules/2a3503b0-4987-4720-8cc9-11a01183905c", - "id": "2a3503b0-4987-4720-8cc9-11a01183905c", - "parentId": "84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "rt": [ - "cm.xr-network.leafModule" - ], - "state": { - "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" - }, - "moduleIf": { - "clientIfAid": "XR-T1", - "clientIfColId": 1, - "clientIfPortSpeed": 100 - } - } - ], - "lifecycleState": "configured", - "module": { - "baudRate": 50, - "capacity": 100, - "clientPortMode": "ethernet", - "configuredRole": "auto", - "constellationFrequency": 193000000, - "currentRole": "leaf", - "fiberConnectionMode": "dual", - "frequencyCtrl": "xr", - "macAddress": "00:0B:F8:00:01:03", - "maxAllowedDSCs": 4, - "modulation": "16QAM", - "moduleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", - "moduleName": "XR LEAF 3", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000D", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - } - ], - "reachableModules": [ - { - "href": "/xr-networks/84d9b09c-017d-4ac5-b8cd-d1102db1e070/reachableModules/957dd5b2-2528-4d24-8d1f-1b8ca7fac33d", - "id": "957dd5b2-2528-4d24-8d1f-1b8ca7fac33d", - "parentId": "84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "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" - }, - "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": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", - "moduleName": "XR LEAF 3", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000D", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/84d9b09c-017d-4ac5-b8cd-d1102db1e070/reachableModules/d159d5e7-53d3-4770-94bf-4a53f22798e5", - "id": "d159d5e7-53d3-4770-94bf-4a53f22798e5", - "parentId": "84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "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" - }, - "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": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", - "moduleName": "XR LEAF 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000B", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/84d9b09c-017d-4ac5-b8cd-d1102db1e070/reachableModules/d9172426-fbe8-4e1b-9c80-373f09219831", - "id": "d9172426-fbe8-4e1b-9c80-373f09219831", - "parentId": "84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:08Z", - "endpoints": [ - { - "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": "9008a605-e6a1-4afd-5728-35dd711a4a15", - "moduleName": "XR LEAF 3", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000D", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/84d9b09c-017d-4ac5-b8cd-d1102db1e070/reachableModules/0074af01-7f70-48ab-9d98-e810af9f278a", - "id": "0074af01-7f70-48ab-9d98-e810af9f278a", - "parentId": "84d9b09c-017d-4ac5-b8cd-d1102db1e070", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:05Z", - "endpoints": [ - { - "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": "4f44c0b2-3d63-465d-6413-5bc46dfa5fbf", - "moduleName": "XR LEAF 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000B", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - } - ], - "rt": [ - "cm.xr-network" - ], - "state": { - "constellationFrequency": 193000000, - "controlLinks": [ - { - "conState": "active", - "destinationModuleId": "3691e001-1e0c-44ae-5fd6-4f4acb8b945c", - "lastConStateChange": "2022-06-28T09:04:07Z", - "sourceModuleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c" - }, - { - "conState": "active", - "destinationModuleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", - "lastConStateChange": "2022-06-28T09:04:08Z", - "sourceModuleId": "3691e001-1e0c-44ae-5fd6-4f4acb8b945c" - }, - { - "conState": "active", - "destinationModuleId": "9008a605-e6a1-4afd-5728-35dd711a4a15", - "lastConStateChange": "2022-06-28T09:04:08Z", - "sourceModuleId": "3691e001-1e0c-44ae-5fd6-4f4acb8b945c" - }, - { - "conState": "active", - "destinationModuleId": "3691e001-1e0c-44ae-5fd6-4f4acb8b945c", - "lastConStateChange": "2022-06-28T09:04:07Z", - "sourceModuleId": "9008a605-e6a1-4afd-5728-35dd711a4a15" - } - ], - "lifecycleState": "configured", - "modulation": "16QAM" - } - }, - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "hubModule": { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/hubModule", - "id": "975df7fe-dbd8-4681-83f3-2f2a57585b67", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "rt": [ - "cm.xr-network.hubModule" - ], - "state": { - "endpoints": [ - { - "moduleIf": { - "clientIfAid": "XR-T1", - "clientIfColId": 1, - "clientIfPortSpeed": 100 - } - }, - { - "moduleIf": { - "clientIfAid": "XR-T2", - "clientIfColId": 2, - "clientIfPortSpeed": 100 - } - }, - { - "moduleIf": { - "clientIfAid": "XR-T3", - "clientIfColId": 3, - "clientIfPortSpeed": 100 - } - }, - { - "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": "fda2a49d-d23c-4b7a-4b30-1d2de15b26d0", - "moduleName": "XR HUB 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "000000009", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - "id": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "leafModules": [ - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/leafModules/55386ab9-d2e3-428d-82d1-d940c6017959", - "id": "55386ab9-d2e3-428d-82d1-d940c6017959", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "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" - }, - "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", - "modulation": "16QAM", - "moduleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", - "moduleName": "XR LEAF 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000B", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/leafModules/a0c8b77d-41e7-4c25-9c99-468dee383ec6", - "id": "a0c8b77d-41e7-4c25-9c99-468dee383ec6", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "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" - }, - "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", - "modulation": "16QAM", - "moduleId": "50842917-0da4-4976-63de-706b62cefd7e", - "moduleName": "XR LEAF 2", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000C", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - } - ], - "reachableModules": [ - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/reachableModules/949d5565-eaf7-43a1-838e-c2d4fdbe4c77", - "id": "949d5565-eaf7-43a1-838e-c2d4fdbe4c77", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "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" - }, - "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": "50842917-0da4-4976-63de-706b62cefd7e", - "moduleName": "XR LEAF 2", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000C", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/reachableModules/d6ab2382-1095-4f98-bfb6-a0e85830c997", - "id": "d6ab2382-1095-4f98-bfb6-a0e85830c997", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "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" - }, - "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": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", - "moduleName": "XR LEAF 3", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000D", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/reachableModules/e02496f1-3aec-4cd0-810e-5ff79448b4c4", - "id": "e02496f1-3aec-4cd0-810e-5ff79448b4c4", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "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" - }, - "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": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", - "moduleName": "XR LEAF 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000B", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/reachableModules/4021ad07-d20e-4149-a63c-a69c36197fba", - "id": "4021ad07-d20e-4149-a63c-a69c36197fba", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:08Z", - "endpoints": [ - { - "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": "9008a605-e6a1-4afd-5728-35dd711a4a15", - "moduleName": "XR LEAF 3", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000D", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/reachableModules/b376688f-21ef-4f3c-81da-15718b2bf9b4", - "id": "b376688f-21ef-4f3c-81da-15718b2bf9b4", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:05Z", - "endpoints": [ - { - "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": "4f44c0b2-3d63-465d-6413-5bc46dfa5fbf", - "moduleName": "XR LEAF 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000B", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/b7d4bbac-8d87-4dfe-af52-be1ef0b905d8/reachableModules/37ac5291-bbf4-4c0b-ab0b-bdbe519f01ef", - "id": "37ac5291-bbf4-4c0b-ab0b-bdbe519f01ef", - "parentId": "b7d4bbac-8d87-4dfe-af52-be1ef0b905d8", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:06Z", - "endpoints": [ - { - "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": "c896fa4a-200f-40b1-449b-337c29c5e6e8", - "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": "fda2a49d-d23c-4b7a-4b30-1d2de15b26d0", - "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66" - }, - { - "conState": "active", - "destinationModuleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", - "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "fda2a49d-d23c-4b7a-4b30-1d2de15b26d0" - }, - { - "conState": "active", - "destinationModuleId": "fda2a49d-d23c-4b7a-4b30-1d2de15b26d0", - "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "50842917-0da4-4976-63de-706b62cefd7e" - }, - { - "conState": "active", - "destinationModuleId": "50842917-0da4-4976-63de-706b62cefd7e", - "lastConStateChange": "2022-06-28T09:04:06Z", - "sourceModuleId": "fda2a49d-d23c-4b7a-4b30-1d2de15b26d0" - } - ], - "lifecycleState": "configured", - "modulation": "16QAM" - } - }, - { - "href": "/xr-networks/8f6ba601-6814-4fb7-acc9-c1999a9cd396", + "href": "/xr-networks/6774cc4e-b0b1-43a1-923f-80fb1bec094b", "hubModule": { - "href": "/xr-networks/8f6ba601-6814-4fb7-acc9-c1999a9cd396/hubModule", - "id": "795fab13-e345-45a3-8225-e83720952ac7", - "parentId": "8f6ba601-6814-4fb7-acc9-c1999a9cd396", + "href": "/xr-networks/6774cc4e-b0b1-43a1-923f-80fb1bec094b/hubModule", + "id": "353563a1-895f-4110-abec-8f59ffb5ecc7", + "parentId": "6774cc4e-b0b1-43a1-923f-80fb1bec094b", "rt": [ "cm.xr-network.hubModule" ], "state": { "endpoints": [ { + "hostPort": { + "chassisId": "192.168.100.1", + "chassisIdSubtype": "networkAddress", + "portDescr": "et-2/0/0:0", + "portId": "et-2/0/0:0", + "portIdSubtype": "interfaceName", + "portSourceMAC": "58:00:BB:00:00:21", + "sysName": "SanJose" + }, + "moduleIf": { + "clientIfAid": "XR-T1", + "clientIfColId": 1, + "clientIfPortSpeed": 100 + } + }, + { + "hostPort": { + "chassisId": "192.168.100.1", + "chassisIdSubtype": "networkAddress", + "portDescr": "et-2/0/0:1", + "portId": "et-2/0/0:1", + "portIdSubtype": "interfaceName", + "portSourceMAC": "58:00:BB:00:00:22", + "sysName": "SanJose" + }, "moduleIf": { "clientIfAid": "XR-T2", "clientIfColId": 2, @@ -948,6 +43,15 @@ } }, { + "hostPort": { + "chassisId": "192.168.100.1", + "chassisIdSubtype": "networkAddress", + "portDescr": "et-2/0/0:2", + "portId": "et-2/0/0:2", + "portIdSubtype": "interfaceName", + "portSourceMAC": "58:00:BB:00:00:23", + "sysName": "SanJose" + }, "moduleIf": { "clientIfAid": "XR-T3", "clientIfColId": 3, @@ -955,18 +59,20 @@ } }, { + "hostPort": { + "chassisId": "192.168.100.1", + "chassisIdSubtype": "networkAddress", + "portDescr": "et-2/0/0:3", + "portId": "et-2/0/0:3", + "portIdSubtype": "interfaceName", + "portSourceMAC": "58:00:BB:00:00:24", + "sysName": "SanJose" + }, "moduleIf": { "clientIfAid": "XR-T4", "clientIfColId": 4, "clientIfPortSpeed": 100 } - }, - { - "moduleIf": { - "clientIfAid": "XR-T1", - "clientIfColId": 1, - "clientIfPortSpeed": 100 - } } ], "lifecycleState": "configured", @@ -981,7 +87,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:00:02", "modulation": "16QAM", - "moduleId": "72415e29-6c91-40cc-588f-5ec5ee735123", + "moduleId": "3a2b5cfe-6265-4b68-549d-340c58363b85", "moduleName": "XR HUB 2", "ncoFrequency": 0, "operatingFrequency": 193000000, @@ -992,12 +98,12 @@ } } }, - "id": "8f6ba601-6814-4fb7-acc9-c1999a9cd396", + "id": "6774cc4e-b0b1-43a1-923f-80fb1bec094b", "leafModules": [ { - "href": "/xr-networks/8f6ba601-6814-4fb7-acc9-c1999a9cd396/leafModules/2693aaf2-d66b-458c-95aa-149c11fb7915", - "id": "2693aaf2-d66b-458c-95aa-149c11fb7915", - "parentId": "8f6ba601-6814-4fb7-acc9-c1999a9cd396", + "href": "/xr-networks/6774cc4e-b0b1-43a1-923f-80fb1bec094b/leafModules/e659ad54-9e6d-492c-ac56-09b3b681c5ed", + "id": "e659ad54-9e6d-492c-ac56-09b3b681c5ed", + "parentId": "6774cc4e-b0b1-43a1-923f-80fb1bec094b", "rt": [ "cm.xr-network.leafModule" ], @@ -1010,7 +116,8 @@ "portDescr": "et-3/0/0:0", "portId": "et-3/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:13:01" + "portSourceMAC": "58:00:BB:00:13:01", + "sysName": "Sunnnyvale" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1031,7 +138,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:01:03", "modulation": "16QAM", - "moduleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", + "moduleId": "572b2d8a-8d0b-40a0-5823-e53041ca2194", "moduleName": "XR LEAF 3", "ncoFrequency": 0, "operatingFrequency": 193000000, @@ -1045,9 +152,9 @@ ], "reachableModules": [ { - "href": "/xr-networks/8f6ba601-6814-4fb7-acc9-c1999a9cd396/reachableModules/e01f6d1c-09b2-4e64-bb5b-b2b3fa1d6d0c", - "id": "e01f6d1c-09b2-4e64-bb5b-b2b3fa1d6d0c", - "parentId": "8f6ba601-6814-4fb7-acc9-c1999a9cd396", + "href": "/xr-networks/6774cc4e-b0b1-43a1-923f-80fb1bec094b/reachableModules/ede4b98b-a6a7-48fa-89c0-b981e7d4a98c", + "id": "ede4b98b-a6a7-48fa-89c0-b981e7d4a98c", + "parentId": "6774cc4e-b0b1-43a1-923f-80fb1bec094b", "rt": [ "cm.xr-network.reachableModule" ], @@ -1061,7 +168,8 @@ "portDescr": "et-3/0/0:0", "portId": "et-3/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:13:01" + "portSourceMAC": "58:00:BB:00:13:01", + "sysName": "Sunnnyvale" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1081,7 +189,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:01:03", "modulation": "16QAM", - "moduleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", + "moduleId": "572b2d8a-8d0b-40a0-5823-e53041ca2194", "moduleName": "XR LEAF 3", "ncoFrequency": 0, "operatingFrequency": 193000000, @@ -1093,9 +201,9 @@ } }, { - "href": "/xr-networks/8f6ba601-6814-4fb7-acc9-c1999a9cd396/reachableModules/5ca5564c-5d6b-4d12-bc0e-daa552587b8c", - "id": "5ca5564c-5d6b-4d12-bc0e-daa552587b8c", - "parentId": "8f6ba601-6814-4fb7-acc9-c1999a9cd396", + "href": "/xr-networks/6774cc4e-b0b1-43a1-923f-80fb1bec094b/reachableModules/004ffffb-290f-45d8-90bf-4e0c914eb39c", + "id": "004ffffb-290f-45d8-90bf-4e0c914eb39c", + "parentId": "6774cc4e-b0b1-43a1-923f-80fb1bec094b", "rt": [ "cm.xr-network.reachableModule" ], @@ -1109,7 +217,8 @@ "portDescr": "et-1/0/0:0", "portId": "et-1/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:11:01" + "portSourceMAC": "58:00:BB:00:11:01", + "sysName": "PaloAlto" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1129,87 +238,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:01:01", "modulation": "16QAM", - "moduleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", - "moduleName": "XR LEAF 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000B", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/8f6ba601-6814-4fb7-acc9-c1999a9cd396/reachableModules/214932f0-a0bb-43a3-ab30-0568630d0929", - "id": "214932f0-a0bb-43a3-ab30-0568630d0929", - "parentId": "8f6ba601-6814-4fb7-acc9-c1999a9cd396", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:08Z", - "endpoints": [ - { - "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": "9008a605-e6a1-4afd-5728-35dd711a4a15", - "moduleName": "XR LEAF 3", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000D", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/8f6ba601-6814-4fb7-acc9-c1999a9cd396/reachableModules/b2a3b179-b57e-4933-b9fb-e43f438bd17b", - "id": "b2a3b179-b57e-4933-b9fb-e43f438bd17b", - "parentId": "8f6ba601-6814-4fb7-acc9-c1999a9cd396", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:05Z", - "endpoints": [ - { - "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": "4f44c0b2-3d63-465d-6413-5bc46dfa5fbf", + "moduleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c", "moduleName": "XR LEAF 1", "ncoFrequency": 0, "operatingFrequency": 192000000, @@ -1229,15 +258,15 @@ "controlLinks": [ { "conState": "active", - "destinationModuleId": "72415e29-6c91-40cc-588f-5ec5ee735123", + "destinationModuleId": "3a2b5cfe-6265-4b68-549d-340c58363b85", "lastConStateChange": "2022-06-28T09:04:07Z", - "sourceModuleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c" + "sourceModuleId": "572b2d8a-8d0b-40a0-5823-e53041ca2194" }, { "conState": "active", - "destinationModuleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", + "destinationModuleId": "572b2d8a-8d0b-40a0-5823-e53041ca2194", "lastConStateChange": "2022-06-28T09:04:08Z", - "sourceModuleId": "72415e29-6c91-40cc-588f-5ec5ee735123" + "sourceModuleId": "3a2b5cfe-6265-4b68-549d-340c58363b85" } ], "lifecycleState": "configured", @@ -1245,11 +274,11 @@ } }, { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954", + "href": "/xr-networks/233e169b-5d88-481d-bfe2-c909a2a859dd", "hubModule": { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/hubModule", - "id": "4760494d-0639-4a56-8045-a181f48d34a8", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", + "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" ], @@ -1262,7 +291,8 @@ "portDescr": "et-1/0/0:0", "portId": "et-1/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:11" + "portSourceMAC": "58:00:BB:00:00:11", + "sysName": "SanJose" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1277,7 +307,8 @@ "portDescr": "et-1/0/0:1", "portId": "et-1/0/0:1", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:12" + "portSourceMAC": "58:00:BB:00:00:12", + "sysName": "SanJose" }, "moduleIf": { "clientIfAid": "XR-T2", @@ -1292,7 +323,8 @@ "portDescr": "et-1/0/0:2", "portId": "et-1/0/0:2", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:13" + "portSourceMAC": "58:00:BB:00:00:13", + "sysName": "SanJose" }, "moduleIf": { "clientIfAid": "XR-T3", @@ -1307,7 +339,8 @@ "portDescr": "et-1/0/0:3", "portId": "et-1/0/0:3", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:00:14" + "portSourceMAC": "58:00:BB:00:00:14", + "sysName": "SanJose" }, "moduleIf": { "clientIfAid": "XR-T4", @@ -1328,7 +361,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:00:01", "modulation": "16QAM", - "moduleId": "841480aa-d5c4-4911-5088-0cfea7970ba7", + "moduleId": "d859de3c-c463-4be5-7a8d-a198275f10f4", "moduleName": "XR HUB 1", "ncoFrequency": 0, "operatingFrequency": 192000000, @@ -1339,12 +372,12 @@ } } }, - "id": "5456336f-24e4-4862-9fc0-81a843f07954", + "id": "233e169b-5d88-481d-bfe2-c909a2a859dd", "leafModules": [ { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/leafModules/ba954cda-485f-4b18-acdc-ba701f876ce3", - "id": "ba954cda-485f-4b18-acdc-ba701f876ce3", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", + "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" ], @@ -1357,7 +390,8 @@ "portDescr": "et-1/0/0:0", "portId": "et-1/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:11:01" + "portSourceMAC": "58:00:BB:00:11:01", + "sysName": "PaloAlto" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1379,7 +413,7 @@ "macAddress": "00:0B:F8:00:01:01", "maxAllowedDSCs": 4, "modulation": "16QAM", - "moduleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", + "moduleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c", "moduleName": "XR LEAF 1", "ncoFrequency": 0, "operatingFrequency": 192000000, @@ -1391,9 +425,9 @@ } }, { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/leafModules/e9188272-71a6-4a03-96eb-9462eb16cf36", - "id": "e9188272-71a6-4a03-96eb-9462eb16cf36", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", + "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" ], @@ -1406,7 +440,8 @@ "portDescr": "et-2/0/0:0", "portId": "et-2/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:12:01" + "portSourceMAC": "58:00:BB:00:12:01", + "sysName": "Cupertino" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1428,7 +463,7 @@ "macAddress": "00:0B:F8:00:01:02", "maxAllowedDSCs": 4, "modulation": "16QAM", - "moduleId": "50842917-0da4-4976-63de-706b62cefd7e", + "moduleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40", "moduleName": "XR LEAF 2", "ncoFrequency": 0, "operatingFrequency": 192000000, @@ -1442,57 +477,9 @@ ], "reachableModules": [ { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/reachableModules/f8b554d3-4776-4260-8f20-eea0d0c92629", - "id": "f8b554d3-4776-4260-8f20-eea0d0c92629", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", - "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" - }, - "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": "50842917-0da4-4976-63de-706b62cefd7e", - "moduleName": "XR LEAF 2", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000C", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/reachableModules/3a45656a-6585-4ec6-a0be-365c9734827f", - "id": "3a45656a-6585-4ec6-a0be-365c9734827f", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", + "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" ], @@ -1506,7 +493,8 @@ "portDescr": "et-3/0/0:0", "portId": "et-3/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:13:01" + "portSourceMAC": "58:00:BB:00:13:01", + "sysName": "Sunnnyvale" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1526,7 +514,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:01:03", "modulation": "16QAM", - "moduleId": "1d23a10c-f5fb-4c2e-69ed-92608ce8e54c", + "moduleId": "572b2d8a-8d0b-40a0-5823-e53041ca2194", "moduleName": "XR LEAF 3", "ncoFrequency": 0, "operatingFrequency": 193000000, @@ -1538,9 +526,9 @@ } }, { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/reachableModules/2b675693-a1b3-48d6-81d9-4b3a38c7a81e", - "id": "2b675693-a1b3-48d6-81d9-4b3a38c7a81e", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", + "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" ], @@ -1554,7 +542,8 @@ "portDescr": "et-1/0/0:0", "portId": "et-1/0/0:0", "portIdSubtype": "interfaceName", - "portSourceMAC": "58:00:BB:00:11:01" + "portSourceMAC": "58:00:BB:00:11:01", + "sysName": "PaloAlto" }, "moduleIf": { "clientIfAid": "XR-T1", @@ -1574,87 +563,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:01:01", "modulation": "16QAM", - "moduleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", - "moduleName": "XR LEAF 1", - "ncoFrequency": 0, - "operatingFrequency": 192000000, - "roleStatus": "ready", - "serialNumber": "00000000B", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/reachableModules/711f1c32-459c-4332-8722-244108210de2", - "id": "711f1c32-459c-4332-8722-244108210de2", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:08Z", - "endpoints": [ - { - "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": "9008a605-e6a1-4afd-5728-35dd711a4a15", - "moduleName": "XR LEAF 3", - "ncoFrequency": 0, - "operatingFrequency": 193000000, - "roleStatus": "ready", - "serialNumber": "00000000D", - "trafficMode": "L1Mode", - "txPowerTargetPerDsc": -6.4 - } - } - }, - { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/reachableModules/e62157e5-fd40-44a3-9ff6-7c5f4fe48089", - "id": "e62157e5-fd40-44a3-9ff6-7c5f4fe48089", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", - "rt": [ - "cm.xr-network.reachableModule" - ], - "state": { - "discoveredTime": "2022-06-28T09:04:05Z", - "endpoints": [ - { - "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": "4f44c0b2-3d63-465d-6413-5bc46dfa5fbf", + "moduleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c", "moduleName": "XR LEAF 1", "ncoFrequency": 0, "operatingFrequency": 192000000, @@ -1666,9 +575,9 @@ } }, { - "href": "/xr-networks/5456336f-24e4-4862-9fc0-81a843f07954/reachableModules/8c344a79-1075-4d0f-90f1-cd8d4f030d64", - "id": "8c344a79-1075-4d0f-90f1-cd8d4f030d64", - "parentId": "5456336f-24e4-4862-9fc0-81a843f07954", + "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" ], @@ -1676,6 +585,15 @@ "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, @@ -1694,7 +612,7 @@ "frequencyCtrl": "xr", "macAddress": "00:0B:F8:00:01:02", "modulation": "16QAM", - "moduleId": "c896fa4a-200f-40b1-449b-337c29c5e6e8", + "moduleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40", "moduleName": "XR LEAF 2", "ncoFrequency": 0, "operatingFrequency": 192000000, @@ -1714,51 +632,27 @@ "controlLinks": [ { "conState": "active", - "destinationModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7", - "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66" - }, - { - "conState": "active", - "destinationModuleId": "9b7fb759-c952-420a-7b1e-5b3b496e1f66", - "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7" - }, - { - "conState": "active", - "destinationModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7", - "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "50842917-0da4-4976-63de-706b62cefd7e" - }, - { - "conState": "active", - "destinationModuleId": "50842917-0da4-4976-63de-706b62cefd7e", - "lastConStateChange": "2022-06-28T09:04:06Z", - "sourceModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7" - }, - { - "conState": "active", - "destinationModuleId": "4f44c0b2-3d63-465d-6413-5bc46dfa5fbf", + "destinationModuleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c", "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7" + "sourceModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4" }, { "conState": "active", - "destinationModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7", + "destinationModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4", "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "4f44c0b2-3d63-465d-6413-5bc46dfa5fbf" + "sourceModuleId": "7c33d7d0-4f7b-4525-5d57-58589adbd47c" }, { "conState": "active", - "destinationModuleId": "c896fa4a-200f-40b1-449b-337c29c5e6e8", + "destinationModuleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40", "lastConStateChange": "2022-06-28T09:04:06Z", - "sourceModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7" + "sourceModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4" }, { "conState": "active", - "destinationModuleId": "841480aa-d5c4-4911-5088-0cfea7970ba7", + "destinationModuleId": "d859de3c-c463-4be5-7a8d-a198275f10f4", "lastConStateChange": "2022-06-28T09:04:05Z", - "sourceModuleId": "c896fa4a-200f-40b1-449b-337c29c5e6e8" + "sourceModuleId": "d68a6b4e-03e4-4c89-5ad5-c5e782325e40" } ], "lifecycleState": "configured", diff --git a/src/device/service/drivers/xr/cm/tests/test_cm_connection.py b/src/device/service/drivers/xr/cm/tests/test_cm_connection.py new file mode 100644 index 0000000000000000000000000000000000000000..0d52c71d68bcbf311ff01c486a04f75f22649830 --- /dev/null +++ b/src/device/service/drivers/xr/cm/tests/test_cm_connection.py @@ -0,0 +1,67 @@ +#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 diff --git a/src/device/service/drivers/xr/cm/tests/test_constellation.py b/src/device/service/drivers/xr/cm/tests/test_constellation.py index 6d40e2acb929b7b044dbafa987db85fcf849dca8..89b449ec03c309d704dccbc13cbaa78377bb716c 100644 --- a/src/device/service/drivers/xr/cm/tests/test_constellation.py +++ b/src/device/service/drivers/xr/cm/tests/test_constellation.py @@ -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"] diff --git a/src/device/service/drivers/xr/cm/tests/test_xr_service_set_config.py b/src/device/service/drivers/xr/cm/tests/test_xr_service_set_config.py new file mode 100644 index 0000000000000000000000000000000000000000..0565a8bc71d8443a4d8f497d8a4962c246ffa579 --- /dev/null +++ b/src/device/service/drivers/xr/cm/tests/test_xr_service_set_config.py @@ -0,0 +1,95 @@ +#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 diff --git a/src/device/service/drivers/xr/cm/tf.py b/src/device/service/drivers/xr/cm/tf.py index 6bf7d58de80a41e2495b33b8f62b3553bccc5a61..938dcfbb84806f006fe5de3aa6450ebd31d1c8dd 100644 --- a/src/device/service/drivers/xr/cm/tf.py +++ b/src/device/service/drivers/xr/cm/tf.py @@ -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