X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=tests%2Ftransportpce_tests%2Fcommon%2Ftest_utils_rfc8040.py;h=63ab18735479f8877df43371f7b41962324efde2;hb=27444f6cbb1711c988dc255736b26613f6b3114c;hp=5c88187b138c532abf4791ca0ed3c97df3eba296;hpb=e50901c4b06c82b91f136dac09bacce01258d7b2;p=transportpce.git diff --git a/tests/transportpce_tests/common/test_utils_rfc8040.py b/tests/transportpce_tests/common/test_utils_rfc8040.py index 5c88187b1..63ab18735 100644 --- a/tests/transportpce_tests/common/test_utils_rfc8040.py +++ b/tests/transportpce_tests/common/test_utils_rfc8040.py @@ -29,8 +29,7 @@ import simulators SIMS = simulators.SIMS HONEYNODE_OK_START_MSG = 'Netconf SSH endpoint started successfully at 0.0.0.0' -KARAF_OK_START_MSG = re.escape( - "Blueprint container for bundle org.opendaylight.netconf.restconf")+".* was successfully created" +KARAF_OK_START_MSG = "Blueprint container for bundle org.opendaylight.netconf.restconf.* was successfully created" LIGHTY_OK_START_MSG = re.escape("lighty.io and RESTCONF-NETCONF started") ODL_LOGIN = 'admin' @@ -41,8 +40,13 @@ NODES_PWD = 'admin' TYPE_APPLICATION_JSON = {'Content-Type': 'application/json', 'Accept': 'application/json'} TYPE_APPLICATION_XML = {'Content-Type': 'application/xml', 'Accept': 'application/xml'} +REQUEST_TIMEOUT = 10 + CODE_SHOULD_BE_200 = 'Http status code should be 200' CODE_SHOULD_BE_201 = 'Http status code should be 201' +T100GE = 'Transponder 100GE' +T0_MULTILAYER_TOPO = 'T0 - Multi-layer topology' +T0_FULL_MULTILAYER_TOPO = 'T0 - Full Multi-layer topology' SIM_LOG_DIRECTORY = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'log') @@ -63,7 +67,7 @@ if 'USE_ODL_RESTCONF_VERSION' in os.environ: else: RESTCONF_VERSION = 'rfc8040' -RESTCONF_BASE_URL = 'http://localhost:' + RESTCONF_PORT + RESTCONF_PATH_PREFIX[RESTCONF_VERSION] +RESTCONF_BASE_URL = 'http://localhost:' + str(RESTCONF_PORT) + RESTCONF_PATH_PREFIX[RESTCONF_VERSION] if 'USE_ODL_ALT_KARAF_INSTALL_DIR' in os.environ: KARAF_INSTALLDIR = os.environ['USE_ODL_ALT_KARAF_INSTALL_DIR'] @@ -88,7 +92,8 @@ def get_request(url): return requests.request( 'GET', url.format(RESTCONF_BASE_URL), headers=TYPE_APPLICATION_JSON, - auth=(ODL_LOGIN, ODL_PWD)) + auth=(ODL_LOGIN, ODL_PWD), + timeout=REQUEST_TIMEOUT) def put_request(url, data): @@ -96,28 +101,31 @@ def put_request(url, data): 'PUT', url.format(RESTCONF_BASE_URL), data=json.dumps(data), headers=TYPE_APPLICATION_JSON, - auth=(ODL_LOGIN, ODL_PWD)) + auth=(ODL_LOGIN, ODL_PWD), + timeout=REQUEST_TIMEOUT) def delete_request(url): return requests.request( 'DELETE', url.format(RESTCONF_BASE_URL), headers=TYPE_APPLICATION_JSON, - auth=(ODL_LOGIN, ODL_PWD)) + auth=(ODL_LOGIN, ODL_PWD), + timeout=REQUEST_TIMEOUT) def post_request(url, data): if data: - print(json.dumps(data)) return requests.request( "POST", url.format(RESTCONF_BASE_URL), data=json.dumps(data), headers=TYPE_APPLICATION_JSON, - auth=(ODL_LOGIN, ODL_PWD)) + auth=(ODL_LOGIN, ODL_PWD), + timeout=REQUEST_TIMEOUT) return requests.request( "POST", url.format(RESTCONF_BASE_URL), headers=TYPE_APPLICATION_JSON, - auth=(ODL_LOGIN, ODL_PWD)) + auth=(ODL_LOGIN, ODL_PWD), + timeout=REQUEST_TIMEOUT) # # Process management @@ -282,7 +290,7 @@ def mount_device(node: str, sim: str): 'netconf-node-topology:tcp-only': 'false', 'netconf-node-topology:pass-through': {}}]} response = put_request(url[RESTCONF_VERSION].format('{}', node), body) - if wait_until_log_contains(TPCE_LOG, re.escape('Triggering notification stream NETCONF for node ' + node), 180): + if wait_until_log_contains(TPCE_LOG, 'Triggering notification stream NETCONF for node ' + node, 180): print('Node ' + node + ' correctly added to tpce topology', end='... ', flush=True) else: print('Node ' + node + ' still not added to tpce topology', end='... ', flush=True) @@ -304,7 +312,7 @@ def unmount_device(node: str): def check_device_connection(node: str): - url = {'rfc8040': '{}/data/network-topology:network-topology/topology=topology-netconf/node={}', + url = {'rfc8040': '{}/data/network-topology:network-topology/topology=topology-netconf/node={}?content=nonconfig', 'draft-bierman02': '{}/operational/network-topology:network-topology/topology/topology-netconf/node/{}'} response = get_request(url[RESTCONF_VERSION].format('{}', node)) res = response.json() @@ -317,60 +325,102 @@ def check_device_connection(node: str): return {'status_code': response.status_code, 'connection-status': connection_status} -# -# Portmapping operations -# - -def get_portmapping(node: str): - url = {'rfc8040': '{}/data/transportpce-portmapping:network/nodes={}', - 'draft-bierman02': '{}/config/transportpce-portmapping:network/nodes/{}'} +def check_node_request(node: str): + # pylint: disable=line-too-long + url = {'rfc8040': '{}/data/network-topology:network-topology/topology=topology-netconf/node={}/yang-ext:mount/org-openroadm-device:org-openroadm-device?content=config', # nopep8 + 'draft-bierman02': '{}/config/network-topology:network-topology/topology/topology-netconf/node/{}/yang-ext:mount/org-openroadm-device:org-openroadm-device'} # nopep8 response = get_request(url[RESTCONF_VERSION].format('{}', node)) res = response.json() - return_key = {'rfc8040': 'transportpce-portmapping:nodes', - 'draft-bierman02': 'nodes'} - nodes = res[return_key[RESTCONF_VERSION]] + return_key = {'rfc8040': 'org-openroadm-device:org-openroadm-device', + 'draft-bierman02': 'org-openroadm-device'} + if return_key[RESTCONF_VERSION] in res.keys(): + response_attribute = res[return_key[RESTCONF_VERSION]] + else: + response_attribute = res['errors']['error'][0] return {'status_code': response.status_code, - 'nodes': nodes} + 'org-openroadm-device': response_attribute} -def get_portmapping_node_info(node: str): - url = {'rfc8040': '{}/data/transportpce-portmapping:network/nodes={}/node-info', - 'draft-bierman02': '{}/config/transportpce-portmapping:network/nodes/{}/node-info'} - response = get_request(url[RESTCONF_VERSION].format('{}', node)) +def check_node_attribute_request(node: str, attribute: str, attribute_value: str): + # pylint: disable=line-too-long + url = {'rfc8040': '{}/data/network-topology:network-topology/topology=topology-netconf/node={}/yang-ext:mount/org-openroadm-device:org-openroadm-device/{}={}?content=nonconfig', # nopep8 + 'draft-bierman02': '{}/operational/network-topology:network-topology/topology/topology-netconf/node/{}/yang-ext:mount/org-openroadm-device:org-openroadm-device/{}/{}'} # nopep8 + response = get_request(url[RESTCONF_VERSION].format('{}', node, attribute, attribute_value)) res = response.json() - return_key = {'rfc8040': 'transportpce-portmapping:node-info', - 'draft-bierman02': 'node-info'} + return_key = {'rfc8040': 'org-openroadm-device:' + attribute, + 'draft-bierman02': attribute} if return_key[RESTCONF_VERSION] in res.keys(): - node_info = res[return_key[RESTCONF_VERSION]] + response_attribute = res[return_key[RESTCONF_VERSION]] else: - node_info = res['errors']['error'][0] + response_attribute = res['errors']['error'][0] return {'status_code': response.status_code, - 'node-info': node_info} + attribute: response_attribute} -def portmapping_request(node: str, mapping: str): - url = {'rfc8040': '{}/data/transportpce-portmapping:network/nodes={}/mapping={}', - 'draft-bierman02': '{}/config/transportpce-portmapping:network/nodes/{}/mapping/{}'} - response = get_request(url[RESTCONF_VERSION].format('{}', node, mapping)) +def check_node_attribute2_request(node: str, attribute: str, attribute_value: str, attribute2: str): + # pylint: disable=line-too-long + url = {'rfc8040': '{}/data/network-topology:network-topology/topology=topology-netconf/node={}/yang-ext:mount/org-openroadm-device:org-openroadm-device/{}={}/{}?content=config', # nopep8 + 'draft-bierman02': '{}/config/network-topology:network-topology/topology/topology-netconf/node/{}/yang-ext:mount/org-openroadm-device:org-openroadm-device/{}/{}/{}'} # nopep8 + response = get_request(url[RESTCONF_VERSION].format('{}', node, attribute, attribute_value, attribute2)) res = response.json() - return_key = {'rfc8040': 'transportpce-portmapping:mapping', - 'draft-bierman02': 'mapping'} - mapping = res[return_key[RESTCONF_VERSION]] + if attribute2 in res.keys(): + response_attribute = res[attribute2] + else: + response_attribute = res['errors']['error'][0] return {'status_code': response.status_code, - 'mapping': mapping} + attribute2: response_attribute} + + +def del_node_attribute_request(node: str, attribute: str, attribute_value: str): + # pylint: disable=line-too-long + url = {'rfc8040': '{}/data/network-topology:network-topology/topology=topology-netconf/node={}/yang-ext:mount/org-openroadm-device:org-openroadm-device/{}={}', # nopep8 + 'draft-bierman02': '{}/config/network-topology:network-topology/topology/topology-netconf/node/{}/yang-ext:mount/org-openroadm-device:org-openroadm-device/{}/{}'} # nopep8 + response = delete_request(url[RESTCONF_VERSION].format('{}', node, attribute, attribute_value)) + return response + +# +# Portmapping operations +# + +def post_portmapping(payload: str): + url = {'rfc8040': '{}/data/transportpce-portmapping:network', + 'draft-bierman02': '{}/config/transportpce-portmapping:network'} + json_payload = json.loads(payload) + response = post_request(url[RESTCONF_VERSION].format('{}'), json_payload) + return {'status_code': response.status_code} -def portmapping_mc_capa_request(node: str, mc_capa: str): - url = {'rfc8040': '{}/data/transportpce-portmapping:network/nodes={}/mc-capabilities={}', - 'draft-bierman02': '{}/config/transportpce-portmapping:network/nodes/{}/mc-capabilities/{}'} - response = get_request(url[RESTCONF_VERSION].format('{}', node, mc_capa)) + +def del_portmapping(): + url = {'rfc8040': '{}/data/transportpce-portmapping:network', + 'draft-bierman02': '{}/config/transportpce-portmapping:network'} + response = delete_request(url[RESTCONF_VERSION].format('{}')) + return {'status_code': response.status_code} + + +def get_portmapping_node_attr(node: str, attr: str, value: str): + # pylint: disable=consider-using-f-string + url = {'rfc8040': '{}/data/transportpce-portmapping:network/nodes={}', + 'draft-bierman02': '{}/config/transportpce-portmapping:network/nodes/{}'} + target_url = url[RESTCONF_VERSION].format('{}', node) + if attr is not None: + target_url = (target_url + '/{}').format('{}', attr) + if value is not None: + suffix = {'rfc8040': '={}', 'draft-bierman02': '/{}'} + target_url = (target_url + suffix[RESTCONF_VERSION]).format('{}', value) + else: + attr = 'nodes' + response = get_request(target_url) res = response.json() - return_key = {'rfc8040': 'transportpce-portmapping:mc-capabilities', - 'draft-bierman02': 'mc-capabilities'} - capabilities = res[return_key[RESTCONF_VERSION]] + return_key = {'rfc8040': 'transportpce-portmapping:' + attr, + 'draft-bierman02': attr} + if return_key[RESTCONF_VERSION] in res.keys(): + return_output = res[return_key[RESTCONF_VERSION]] + else: + return_output = res['errors']['error'][0] return {'status_code': response.status_code, - 'mc-capabilities': capabilities} + attr: return_output} # # Topology operations @@ -387,14 +437,32 @@ def get_ietf_network_request(network: str, content: str): else: format_args = ('{}', 'operational', network) response = get_request(url[RESTCONF_VERSION].format(*format_args)) - res = response.json() - return_key = {'rfc8040': 'ietf-network:network', - 'draft-bierman02': 'network'} - networks = res[return_key[RESTCONF_VERSION]] + if bool(response): + res = response.json() + return_key = {'rfc8040': 'ietf-network:network', + 'draft-bierman02': 'network'} + networks = res[return_key[RESTCONF_VERSION]] + else: + networks = None return {'status_code': response.status_code, 'network': networks} +def put_ietf_network(network: str, payload: str): + url = {'rfc8040': '{}/data/ietf-network:networks/network={}', + 'draft-bierman02': '{}/config/ietf-network:networks/network/{}'} + json_payload = json.loads(payload) + response = put_request(url[RESTCONF_VERSION].format('{}', network), json_payload) + return {'status_code': response.status_code} + + +def del_ietf_network(network: str): + url = {'rfc8040': '{}/data/ietf-network:networks/network={}', + 'draft-bierman02': '{}/config/ietf-network:networks/network/{}'} + response = delete_request(url[RESTCONF_VERSION].format('{}', network)) + return {'status_code': response.status_code} + + def get_ietf_network_link_request(network: str, link: str, content: str): url = {'rfc8040': '{}/data/ietf-network:networks/network={}/ietf-network-topology:link={}?content={}', 'draft-bierman02': '{}/{}/ietf-network:networks/network/{}/ietf-network-topology:link/{}'} @@ -444,6 +512,27 @@ def del_oms_attr_request(link: str,): return response +def get_ietf_network_node_request(network: str, node: str, content: str): + url = {'rfc8040': '{}/data/ietf-network:networks/network={}/node={}?content={}', + 'draft-bierman02': '{}/{}/ietf-network:networks/network/{}/node/{}'} + if RESTCONF_VERSION == 'rfc8040': + format_args = ('{}', network, node, content) + elif content == 'config': + format_args = ('{}', content, network, node) + else: + format_args = ('{}', 'operational', network, node) + response = get_request(url[RESTCONF_VERSION].format(*format_args)) + if bool(response): + res = response.json() + return_key = {'rfc8040': 'ietf-network:node', + 'draft-bierman02': 'node'} + node = res[return_key[RESTCONF_VERSION]][0] + else: + node = None + return {'status_code': response.status_code, + 'node': node} + + def del_ietf_network_node_request(network: str, node: str, content: str): url = {'rfc8040': '{}/data/ietf-network:networks/network={}/node={}?content={}', 'draft-bierman02': '{}/{}/ietf-network:networks/network/{}/node/{}'} @@ -456,42 +545,99 @@ def del_ietf_network_node_request(network: str, node: str, content: str): response = delete_request(url[RESTCONF_VERSION].format(*format_args)) return response + +# +# Service list operations +# + + +def get_ordm_serv_list_request(): + url = {'rfc8040': '{}/data/org-openroadm-service:service-list?content=nonconfig', + 'draft-bierman02': '{}/operational/org-openroadm-service:service-list/'} + response = get_request(url[RESTCONF_VERSION]) + res = response.json() + return_key = {'rfc8040': 'org-openroadm-service:service-list', + 'draft-bierman02': 'service-list'} + if return_key[RESTCONF_VERSION] in res.keys(): + response_attribute = res[return_key[RESTCONF_VERSION]] + else: + response_attribute = res['errors']['error'][0] + return {'status_code': response.status_code, + 'service-list': response_attribute} + + +def get_ordm_serv_list_attr_request(attribute: str, value: str): + url = {'rfc8040': '{}/data/org-openroadm-service:service-list/{}={}?content=nonconfig', + 'draft-bierman02': '{}/operational/org-openroadm-service:service-list/{}/{}'} + if RESTCONF_VERSION == 'rfc8040': + format_args = ('{}', attribute, value) + else: + format_args = ('{}', attribute, value) + response = get_request(url[RESTCONF_VERSION].format(*format_args)) + res = response.json() + return_key = {'rfc8040': 'org-openroadm-service:' + attribute, + 'draft-bierman02': attribute} + if return_key[RESTCONF_VERSION] in res.keys(): + response_attribute = res[return_key[RESTCONF_VERSION]] + else: + response_attribute = res['errors']['error'][0] + return {'status_code': response.status_code, + attribute: response_attribute} + + +def get_serv_path_list_attr(attribute: str, value: str): + url = {'rfc8040': '{}/data/transportpce-service-path:service-path-list/{}={}?content=nonconfig', + 'draft-bierman02': '{}/operational/transportpce-service-path:service-path-list/{}/{}'} + response = get_request(url[RESTCONF_VERSION].format('{}', attribute, value)) + res = response.json() + return_key = {'rfc8040': 'transportpce-service-path:' + attribute, + 'draft-bierman02': attribute} + if return_key[RESTCONF_VERSION] in res.keys(): + response_attribute = res[return_key[RESTCONF_VERSION]] + else: + response_attribute = res['errors']['error'][0] + return {'status_code': response.status_code, + attribute: response_attribute} + + # -# TransportPCE network utils operations +# TransportPCE internal API RPCs # -def connect_xpdr_to_rdm_request(payload: dict): - url = "{}/operations/transportpce-networkutils:init-xpdr-rdm-links" - payload_prefix = {'rfc8040': '', 'draft-bierman02': 'networkutils:'} - data = { - payload_prefix[RESTCONF_VERSION] + "input": { - payload_prefix[RESTCONF_VERSION] + "links-input": { - payload_prefix[RESTCONF_VERSION] + "xpdr-node": payload['xpdr-node'], - payload_prefix[RESTCONF_VERSION] + "xpdr-num": payload['xpdr-num'], - payload_prefix[RESTCONF_VERSION] + "network-num": payload['network-num'], - payload_prefix[RESTCONF_VERSION] + "rdm-node": payload['rdm-node'], - payload_prefix[RESTCONF_VERSION] + "srg-num": payload['srg-num'], - payload_prefix[RESTCONF_VERSION] + "termination-point-num": payload['termination-point-num'] - } - } - } - return post_request(url, data) - - -def connect_rdm_to_xpdr_request(payload: dict): - url = "{}/operations/transportpce-networkutils:init-rdm-xpdr-links" - payload_prefix = {'rfc8040': '', 'draft-bierman02': 'networkutils:'} - data = { - payload_prefix[RESTCONF_VERSION] + "input": { - payload_prefix[RESTCONF_VERSION] + "links-input": { - payload_prefix[RESTCONF_VERSION] + "xpdr-node": payload['xpdr-node'], - payload_prefix[RESTCONF_VERSION] + "xpdr-num": payload['xpdr-num'], - payload_prefix[RESTCONF_VERSION] + "network-num": payload['network-num'], - payload_prefix[RESTCONF_VERSION] + "rdm-node": payload['rdm-node'], - payload_prefix[RESTCONF_VERSION] + "srg-num": payload['srg-num'], - payload_prefix[RESTCONF_VERSION] + "termination-point-num": payload['termination-point-num'] - } - } - } - return post_request(url, data) +def prepend_dict_keys(input_dict: dict, prefix: str): + return_dict = {} + for key, value in input_dict.items(): + newkey = prefix + key + if isinstance(value, dict): + return_dict[newkey] = prepend_dict_keys(value, prefix) + # TODO: perhaps some recursion depth limit or another solution has to be considered here + # even if recursion depth is given by the input_dict argument + # direct (self-)recursive functions may carry unwanted side-effects such as ressource consumptions + else: + return_dict[newkey] = value + return return_dict + + +def transportpce_api_rpc_request(api_module: str, rpc: str, payload: dict): + # pylint: disable=consider-using-f-string + url = "{}/operations/{}:{}".format('{}', api_module, rpc) + if payload is None: + data = None + elif RESTCONF_VERSION == 'draft-bierman02': + data = prepend_dict_keys({'input': payload}, api_module + ':') + else: + data = {'input': payload} + response = post_request(url, data) + if response.status_code == requests.codes.no_content: + return_output = None + else: + res = response.json() + return_key = {'rfc8040': api_module + ':output', + 'draft-bierman02': 'output'} + if response.status_code == requests.codes.internal_server_error: + return_output = res + else: + return_output = res[return_key[RESTCONF_VERSION]] + return {'status_code': response.status_code, + 'output': return_output}