Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for UC 5.2.X #81

Merged
merged 2 commits into from
Feb 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,7 @@ def execute_mount_cli(task):
)
response_code, response_json = parse_response(r)

error_message_for_already_installed = "Node has already been installed using CLI protocol"

failed = response_json.get("output", {}).get("status") == "fail"
already_installed = (
response_json.get("output", {}).get("error-message") == error_message_for_already_installed
)

if not failed or already_installed:
if response_code in [requests.codes.no_content, requests.codes.conflict]:
return {
"status": "COMPLETED",
"output": {
Expand Down
25 changes: 20 additions & 5 deletions frinx_conductor_workers/frinx_conductor_workers/cli_worker_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@
}
}

cli_node_already_installed = {
"errors": {
"error": [
{
"error-tag": "data-exists",
"error-info": {"node-id": "xr5", "topology-id": "protocol"},
"error-message": "Node has already been installed using other protocols",
"error-type": "application",
}
]
}
}


class MockResponse:
def __init__(self, content, status_code):
Expand All @@ -110,7 +123,7 @@ def json(self):
class TestMount(unittest.TestCase):
def test_mount_new_device(self):
with patch("frinx_conductor_workers.cli_worker.requests.post") as mock:
mock.return_value = MockResponse(bytes(json.dumps({}), encoding="utf-8"), 201)
mock.return_value = MockResponse(bytes(json.dumps({}), encoding="utf-8"), 204)
request = frinx_conductor_workers.cli_worker.execute_mount_cli(
{
"inputData": {
Expand All @@ -131,12 +144,14 @@ def test_mount_new_device(self):
request["output"]["url"],
uniconfig_url_base + "/operations/connection-manager:install-node",
)
self.assertEqual(request["output"]["response_code"], 201)
self.assertEqual(request["output"]["response_code"], 204)
self.assertEqual(request["output"]["response_body"], {})

def test_mount_existing_device(self):
with patch("frinx_conductor_workers.cli_worker.requests.post") as mock:
mock.return_value = MockResponse(bytes(json.dumps({}), encoding="utf-8"), 204)
mock.return_value = MockResponse(
bytes(json.dumps(cli_node_already_installed), encoding="utf-8"), 409
)
request = frinx_conductor_workers.cli_worker.execute_mount_cli(
{
"inputData": {
Expand All @@ -156,8 +171,8 @@ def test_mount_existing_device(self):
request["output"]["url"],
uniconfig_url_base + "/operations/connection-manager:install-node",
)
self.assertEqual(request["output"]["response_code"], 204)
self.assertEqual(request["output"]["response_body"], {})
self.assertEqual(request["output"]["response_code"], 409)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is 409 ok status code? just to be sure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the code it seems that if the node was already installed the task should end successfully.
UC 5.2.7 sends 409 for that scenario
image

self.assertEqual(request["output"]["response_body"], cli_node_already_installed)


class TestUnmount(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,11 @@ def execute_install_nodes(task):

response_code, response_json = parse_response(r)

if response_code is 200:
if response_code in [requests.codes.no_content, requests.codes.conflict]:
status = "COMPLETED"

for node in response_json["output"]["node-results"]:
if status_condition and node["status"] == "fail":
status = "FAILED"
break
if status_condition and response_code == requests.codes.conflict:
status = "FAILED"

return {
"status": status,
Expand Down Expand Up @@ -97,13 +95,11 @@ def execute_uninstall_nodes(task):

response_code, response_json = parse_response(r)

if response_code is 200:
if response_code in [requests.codes.no_content, requests.codes.not_found]:
status = "COMPLETED"

for node in response_json["output"]["node-results"]:
if status_condition and node["status"] == "fail":
status = "FAILED"
break
if status_condition and response_code == requests.codes.not_found:
status = "FAILED"

return {
"status": status,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""This module contains helper functions and objects for logging."""

import io
import logging

Expand Down
15 changes: 4 additions & 11 deletions frinx_conductor_workers/frinx_conductor_workers/netconf_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ def execute_mount_netconf(task):
and task["inputData"]["between-attempts-timeout-millis"] is not None
and task["inputData"]["between-attempts-timeout-millis"] is not ""
):
mount_body["input"]["netconf"][
"netconf-node-topology:between-attempts-timeout-millis"
] = task["inputData"]["between-attempts-timeout-millis"]
mount_body["input"]["netconf"]["netconf-node-topology:between-attempts-timeout-millis"] = (
task["inputData"]["between-attempts-timeout-millis"]
)

if (
"connection-timeout-millis" in task["inputData"]
Expand Down Expand Up @@ -165,14 +165,7 @@ def execute_mount_netconf(task):
)
response_code, response_json = parse_response(r)

error_message_for_already_installed = "Node has already been installed using NETCONF protocol"

failed = response_json.get("output", {}).get("status") == "fail"
already_installed = (
response_json.get("output", {}).get("error-message") == error_message_for_already_installed
)

if not failed or already_installed:
if response_code in [requests.codes.no_content, requests.codes.conflict]:
return {
"status": "COMPLETED",
"output": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,19 @@
}
}

netconf_node_already_installed = {
"errors": {
"error": [
{
"error-tag": "data-exists",
"error-info": {"node-id": "xr6", "topology-id": "protocol"},
"error-message": "Node has already been installed using other protocols",
"error-type": "application",
}
]
}
}


class MockResponse:
def __init__(self, content, status_code):
Expand All @@ -96,7 +109,7 @@ def json(self):
class TestMount(unittest.TestCase):
def test_mount_new_device(self):
with patch("frinx_conductor_workers.netconf_worker.requests.post") as mock:
mock.return_value = MockResponse(bytes(json.dumps({}), encoding="utf-8"), 201)
mock.return_value = MockResponse(bytes(json.dumps({}), encoding="utf-8"), 204)
request = frinx_conductor_workers.netconf_worker.execute_mount_netconf(
{
"inputData": {
Expand All @@ -115,12 +128,14 @@ def test_mount_new_device(self):
request["output"]["url"],
uniconfig_url_base + "/operations/connection-manager:install-node",
)
self.assertEqual(request["output"]["response_code"], 201)
self.assertEqual(request["output"]["response_code"], 204)
self.assertEqual(request["output"]["response_body"], {})

def test_mount_existing_device(self):
with patch("frinx_conductor_workers.netconf_worker.requests.post") as mock:
mock.return_value = MockResponse(bytes(json.dumps({}), encoding="utf-8"), 204)
mock.return_value = MockResponse(
bytes(json.dumps(netconf_node_already_installed), encoding="utf-8"), 409
)
request = frinx_conductor_workers.netconf_worker.execute_mount_netconf(
{
"inputData": {
Expand All @@ -139,8 +154,8 @@ def test_mount_existing_device(self):
request["output"]["url"],
uniconfig_url_base + "/operations/connection-manager:install-node",
)
self.assertEqual(request["output"]["response_code"], 204)
self.assertEqual(request["output"]["response_body"], {})
self.assertEqual(request["output"]["response_code"], 409)
self.assertEqual(request["output"]["response_body"], netconf_node_already_installed)


class TestUnmount(unittest.TestCase):
Expand Down
50 changes: 29 additions & 21 deletions frinx_conductor_workers/frinx_conductor_workers/uniconfig_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,15 @@ def replace_config_with_oper(task):
)


def create_commit_request(device_list):
commit_body = {"input": {"target-nodes": {}}}
commit_body["input"]["target-nodes"]["node"] = device_list
return commit_body
def create_nodes_request(device_list):
input_body = {"input": {"target-nodes": {}}}
input_body["input"]["target-nodes"]["node"] = device_list
return input_body


def create_global_request():
input_body = {"input": {}}
return input_body


def parse_devices(task, fail_on_empty=True):
Expand All @@ -297,7 +302,11 @@ def parse_devices(task, fail_on_empty=True):
return extracted_devices


def request_uniconfig(devices, url, uniconfig_cookies_multizone={}):
def request_uniconfig(devices, url, uniconfig_cookies_multizone=None):

if not uniconfig_cookies_multizone:
uniconfig_cookies_multizone = {}

responses = []

original_url = url
Expand All @@ -308,7 +317,7 @@ def request_uniconfig(devices, url, uniconfig_cookies_multizone={}):

r = requests.post(
url,
data=json.dumps(create_commit_request(device.device_names)),
data=json.dumps(create_nodes_request(device.device_names)),
cookies=uniconfig_cookies,
**additional_uniconfig_request_params,
)
Expand All @@ -320,18 +329,18 @@ def request_uniconfig(devices, url, uniconfig_cookies_multizone={}):
"response_code": response_code,
"response_body": response_json,
}
if (
response_code == requests.codes.ok
and response_json["output"]["overall-status"] == "complete"
):
if response_code in [requests.codes.ok, requests.codes.no_content]:
responses.append(response)
else:
return util.failed_response(response)

return util.completed_response({"responses": responses})


def commit_uniconfig(devices, url, uniconfig_cookies_multizone={}):
def commit_uniconfig(devices, url, uniconfig_cookies_multizone=None):
if not uniconfig_cookies_multizone:
uniconfig_cookies_multizone = {}

responses = []

original_url = url
Expand All @@ -342,7 +351,7 @@ def commit_uniconfig(devices, url, uniconfig_cookies_multizone={}):

r = requests.post(
url,
data=json.dumps(create_commit_request(device.device_names)),
data=json.dumps(create_global_request()),
cookies=uniconfig_cookies,
**additional_uniconfig_request_params,
)
Expand All @@ -355,22 +364,21 @@ def commit_uniconfig(devices, url, uniconfig_cookies_multizone={}):
"response_body": response_body,
}

if (
response_code == requests.codes.ok
and response_body["output"]["overall-status"] == "complete"
):
if response_code in [requests.codes.ok, requests.codes.no_content]:
responses.append(response)

else:
# If there's error-message key in the the response body,
# pass it to the user.
error_messages = {}
try:
nodes = response_body["output"]["node-results"]["node-result"]
errors = response_body["errors"]["error"]

for node in nodes:
if node.get("error-message"):
error_messages.update({node["node-id"]: node["error-message"]})
for error in errors:
if error.get("error-message"):
error_messages.update(
{error["error-info"]["node-id"]: error["error-message"]}
)

except KeyError:
error_messages["uncaught_error"] = response
Expand Down Expand Up @@ -719,7 +727,7 @@ def revert_tx_internal(uniconfig_cluster, tx_id, uniconfig_cookies):
**additional_uniconfig_request_params,
)

if response.status_code != requests.codes.ok:
if response.status_code != requests.codes.no_content:
response_body = response.content.decode("utf8")
response_code = response.status_code
# return_logs.error(
Expand Down
Loading
Loading