From 631bdf9157892e675361260de92c31d1e2a7ff9d Mon Sep 17 00:00:00 2001 From: MUTHU-RAKESH-27 <19cs127@psgitech.ac.in> Date: Fri, 7 Jun 2024 11:32:28 +0530 Subject: [PATCH 1/4] Added the maximum timeout for checking the execution of task id and execution id --- plugins/module_utils/dnac.py | 24 +++++++++++++++---- .../network_settings_workflow_manager.py | 2 +- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/plugins/module_utils/dnac.py b/plugins/module_utils/dnac.py index b378420177..0f817f3cb5 100644 --- a/plugins/module_utils/dnac.py +++ b/plugins/module_utils/dnac.py @@ -68,6 +68,7 @@ def __init__(self, module): 'parsed': self.verify_diff_parsed } self.dnac_log = dnac_params.get("dnac_log") + self.max_timeout = self.params.get('dnac_api_task_timeout') if self.dnac_log and not DnacBase.__is_log_init: self.dnac_log_level = dnac_params.get("dnac_log_level") or 'WARNING' @@ -331,7 +332,14 @@ def check_task_response_status(self, response, validation_string, data=False): return self task_id = response.get("taskId") + start_time = time.time() while True: + end_time = time.time() + if (end_time - start_time) >= self.max_timeout: + self.log("Max timeout of {0} sec has reached for the task id '{1}' for the event and unexpected " + "api status so moving out of the loop.".format(self.max_timeout, task_id), "WARNING") + break + task_details = self.get_task_details(task_id) self.log('Getting task details from task ID {0}: {1}'.format(task_id, task_details), "DEBUG") @@ -401,9 +409,16 @@ def check_execution_response_status(self, response): self.status = "failed" return self - executionid = response.get("executionId") + execution_id = response.get("executionId") + start_time = time.time() while True: - execution_details = self.get_execution_details(executionid) + end_time = time.time() + if (end_time - start_time) >= self.max_timeout: + self.log("Max timeout of {0} sec has reached for the execution id '{1}' for the event and unexpected " + "api status so moving out of the loop.".format(self.max_timeout, execution_id), "WARNING") + break + + execution_details = self.get_execution_details(execution_id) if execution_details.get("status") == "SUCCESS": self.result['changed'] = True self.msg = "Successfully executed" @@ -529,15 +544,14 @@ def check_status_api_events(self, status_execution_id): response from the API. If the timeout is reached first, the method logs a warning and returns None. """ - max_timeout = self.params.get('dnac_api_task_timeout') events_response = None start_time = time.time() while True: end_time = time.time() - if (end_time - start_time) >= max_timeout: + if (end_time - start_time) >= self.max_timeout: self.log("""Max timeout of {0} sec has reached for the execution id '{1}' for the event and unexpected - api status so moving out of the loop.""".format(max_timeout, status_execution_id), "WARNING") + api status so moving out of the loop.""".format(self.max_timeout, status_execution_id), "WARNING") break # Now we check the status of API Events for configuring destination and notifications response = self.dnac._exec( diff --git a/plugins/modules/network_settings_workflow_manager.py b/plugins/modules/network_settings_workflow_manager.py index 48c478a628..ff49b5bd9e 100644 --- a/plugins/modules/network_settings_workflow_manager.py +++ b/plugins/modules/network_settings_workflow_manager.py @@ -1540,7 +1540,7 @@ def get_have_network(self, network_details): site_id = self.get_site_id(site_name) if site_id is None: - self.msg = "Failed to get site id from {0}".format(site_name) + self.msg = "The site with the name '{0}' is not available in the DNAC".format(site_name) self.status = "failed" return self From 34aea4622a730033866d49392366b0a5553f5bd1 Mon Sep 17 00:00:00 2001 From: MUTHU-RAKESH-27 <19cs127@psgitech.ac.in> Date: Fri, 7 Jun 2024 12:02:39 +0530 Subject: [PATCH 2/4] Addressed the review comments --- plugins/module_utils/dnac.py | 10 +++++----- plugins/modules/network_settings_workflow_manager.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/module_utils/dnac.py b/plugins/module_utils/dnac.py index 0f817f3cb5..2472f192c1 100644 --- a/plugins/module_utils/dnac.py +++ b/plugins/module_utils/dnac.py @@ -336,8 +336,8 @@ def check_task_response_status(self, response, validation_string, data=False): while True: end_time = time.time() if (end_time - start_time) >= self.max_timeout: - self.log("Max timeout of {0} sec has reached for the task id '{1}' for the event and unexpected " - "api status so moving out of the loop.".format(self.max_timeout, task_id), "WARNING") + self.log("Max timeout of {0} sec has reached for the execution id '{1}'. Exiting the loop due to unexpected API status." + .format(self.max_timeout, task_id), "WARNING") break task_details = self.get_task_details(task_id) @@ -358,7 +358,7 @@ def check_task_response_status(self, response, validation_string, data=False): self.status = "success" break - self.log("progress set to {0} for taskid: {1}".format(task_details.get('progress'), task_id), "DEBUG") + self.log("Progress is {0} for task ID: {1}".format(task_details.get('progress'), task_id), "DEBUG") return self @@ -414,8 +414,8 @@ def check_execution_response_status(self, response): while True: end_time = time.time() if (end_time - start_time) >= self.max_timeout: - self.log("Max timeout of {0} sec has reached for the execution id '{1}' for the event and unexpected " - "api status so moving out of the loop.".format(self.max_timeout, execution_id), "WARNING") + self.log("Max timeout of {0} sec has reached for the execution id '{1}'. Exiting the loop due to unexpected API status." + .format(self.max_timeout, execution_id), "WARNING") break execution_details = self.get_execution_details(execution_id) diff --git a/plugins/modules/network_settings_workflow_manager.py b/plugins/modules/network_settings_workflow_manager.py index ff49b5bd9e..b1f4e9d1a8 100644 --- a/plugins/modules/network_settings_workflow_manager.py +++ b/plugins/modules/network_settings_workflow_manager.py @@ -1540,7 +1540,7 @@ def get_have_network(self, network_details): site_id = self.get_site_id(site_name) if site_id is None: - self.msg = "The site with the name '{0}' is not available in the DNAC".format(site_name) + self.msg = "The site with the name '{0}' is not available in the Catalyst Center".format(site_name) self.status = "failed" return self From 5b456e1c3a68e82195978bee06365fd8b3697a7d Mon Sep 17 00:00:00 2001 From: MUTHU-RAKESH-27 <19cs127@psgitech.ac.in> Date: Fri, 7 Jun 2024 12:50:56 +0530 Subject: [PATCH 3/4] Added the API name in check_task_response_status and check_execution_response_status --- plugins/module_utils/dnac.py | 19 ++++++++++++------- .../device_credential_workflow_manager.py | 6 +++--- ...ise_radius_integration_workflow_manager.py | 4 ++-- .../network_settings_workflow_manager.py | 14 +++++++------- plugins/modules/template_workflow_manager.py | 6 ++++-- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/plugins/module_utils/dnac.py b/plugins/module_utils/dnac.py index 2472f192c1..a890469c9d 100644 --- a/plugins/module_utils/dnac.py +++ b/plugins/module_utils/dnac.py @@ -302,14 +302,16 @@ def get_task_details(self, task_id): return result - def check_task_response_status(self, response, validation_string, data=False): + def check_task_response_status(self, response, validation_string, api_name="", data=False): """ Get the site id from the site name. Parameters: self - The current object details. response (dict) - API response. - validation_string (string) - String used to match the progress status. + validation_string (str) - String used to match the progress status. + api_name (str) - API name. + data (bool) - Set to True if the API is returning any information. Else, False. Returns: self @@ -336,8 +338,9 @@ def check_task_response_status(self, response, validation_string, data=False): while True: end_time = time.time() if (end_time - start_time) >= self.max_timeout: - self.log("Max timeout of {0} sec has reached for the execution id '{1}'. Exiting the loop due to unexpected API status." - .format(self.max_timeout, task_id), "WARNING") + self.log("Max timeout of {0} sec has reached for the execution id '{1}'. " + "Exiting the loop due to unexpected API '{2}' status." + .format(self.max_timeout, task_id, api_name), "WARNING") break task_details = self.get_task_details(task_id) @@ -388,12 +391,13 @@ def get_execution_details(self, execid): self.log("Response for the current execution: {0}".format(response)) return response - def check_execution_response_status(self, response): + def check_execution_response_status(self, response, api_name=""): """ Checks the reponse status provided by API in the Cisco Catalyst Center Parameters: response (dict) - API response + api_name (str) - API name Returns: self @@ -414,8 +418,9 @@ def check_execution_response_status(self, response): while True: end_time = time.time() if (end_time - start_time) >= self.max_timeout: - self.log("Max timeout of {0} sec has reached for the execution id '{1}'. Exiting the loop due to unexpected API status." - .format(self.max_timeout, execution_id), "WARNING") + self.log("Max timeout of {0} sec has reached for the execution id '{1}'. " + "Exiting the loop due to unexpected API '{2}' status." + .format(self.max_timeout, execution_id, api_name), "WARNING") break execution_details = self.get_execution_details(execution_id) diff --git a/plugins/modules/device_credential_workflow_manager.py b/plugins/modules/device_credential_workflow_manager.py index 48f7fbaba0..1d412f5013 100644 --- a/plugins/modules/device_credential_workflow_manager.py +++ b/plugins/modules/device_credential_workflow_manager.py @@ -2223,7 +2223,7 @@ def create_device_credentials(self): self.log("Received API response from 'create_global_credentials_v2': {0}" .format(response), "DEBUG") validation_string = "global credential addition performed" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "create_global_credentials_v2").check_return_status() self.log("Global credential created successfully", "INFO") result_global_credential.update({ "Creation": { @@ -2288,7 +2288,7 @@ def update_device_credentials(self): self.log("Received API response for 'update_global_credentials_v2': {0}" .format(response), "DEBUG") validation_string = "global credential update performed" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "update_global_credentials_v2").check_return_status() self.log("Updating device credential API input parameters: {0}" .format(final_response), "DEBUG") self.log("Global device credential updated successfully", "INFO") @@ -2344,7 +2344,7 @@ def assign_credentials_to_site(self): self.log("Received API response for 'assign_device_credential_to_site_v2': {0}" .format(response), "DEBUG") validation_string = "desired common settings operation successful" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "assign_device_credential_to_site_v2").check_return_status() self.log("Device credential assigned to site {0} is successfully." .format(site_ids), "INFO") self.log("Desired State for assign credentials to a site: {0}" diff --git a/plugins/modules/ise_radius_integration_workflow_manager.py b/plugins/modules/ise_radius_integration_workflow_manager.py index d795d78fa1..d8d463f508 100644 --- a/plugins/modules/ise_radius_integration_workflow_manager.py +++ b/plugins/modules/ise_radius_integration_workflow_manager.py @@ -1338,7 +1338,7 @@ def update_auth_policy_server(self, ipAddress): params=auth_server_params, ) validation_string = "successfully updated aaa settings" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "edit_authentication_and_policy_server_access_configuration").check_return_status() self.log("Authentication and Policy Server '{0}' updated successfully" .format(ipAddress), "INFO") result_auth_server.get("response").get(ipAddress) \ @@ -1399,7 +1399,7 @@ def delete_auth_policy_server(self, ipAddress): # Check the task status validation_string = "successfully deleted aaa settings" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "delete_authentication_and_policy_server_access_configuration").check_return_status() taskid = response.get("response").get("taskId") # Update result information diff --git a/plugins/modules/network_settings_workflow_manager.py b/plugins/modules/network_settings_workflow_manager.py index b1f4e9d1a8..9cf3cc2a9e 100644 --- a/plugins/modules/network_settings_workflow_manager.py +++ b/plugins/modules/network_settings_workflow_manager.py @@ -2223,7 +2223,7 @@ def update_global_pool(self, global_pool): op_modifies=True, params=pool_params, ) - self.check_execution_response_status(response).check_return_status() + self.check_execution_response_status(response, "create_global_pool").check_return_status() self.log("Successfully created global pool successfully.", "INFO") for item in pool_params.get("settings").get("ippool"): name = item.get("ipPoolName") @@ -2267,7 +2267,7 @@ def update_global_pool(self, global_pool): params=pool_params, ) - self.check_execution_response_status(response).check_return_status() + self.check_execution_response_status(response, "update_global_pool").check_return_status() for item in pool_params.get("settings").get("ippool"): name = item.get("ipPoolName") self.log("Global pool '{0}' Updated successfully.".format(name), "INFO") @@ -2316,7 +2316,7 @@ def update_reserve_pool(self, reserve_pool): op_modifies=True, params=reserve_params, ) - self.check_execution_response_status(response).check_return_status() + self.check_execution_response_status(response, "reserve_ip_subpool").check_return_status() self.log("Successfully created IP subpool reservation '{0}'.".format(name), "INFO") result_reserve_pool.get("response") \ .update({name: self.want.get("wantReserve")[reserve_pool_index]}) @@ -2347,7 +2347,7 @@ def update_reserve_pool(self, reserve_pool): op_modifies=True, params=reserve_params, ) - self.check_execution_response_status(response).check_return_status() + self.check_execution_response_status(response, "update_reserve_ip_subpool").check_return_status() self.log("Reserved ip subpool '{0}' updated successfully.".format(name), "INFO") result_reserve_pool.get("response") \ .update({name: reserve_params}) @@ -2402,7 +2402,7 @@ def update_network(self, config): ) self.log("Received API response of 'update_network_v2': {0}".format(response), "DEBUG") validation_string = "desired common settings operation successful" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "update_network_v2").check_return_status() self.log("Network has been changed successfully", "INFO") result_network.get("msg") \ .update({site_name: "Network Updated successfully"}) @@ -2469,7 +2469,7 @@ def delete_reserve_pool(self, reserve_pool_details): op_modifies=True, params={"id": _id}, ) - self.check_execution_response_status(response).check_return_status() + self.check_execution_response_status(response, "release_reserve_ip_subpool").check_return_status() executionid = response.get("executionId") result_reserve_pool = self.result.get("response")[1].get("reservePool") result_reserve_pool.get("response").update({name: {}}) @@ -2513,7 +2513,7 @@ def delete_global_pool(self, global_pool_details): ) # Check the execution status - self.check_execution_response_status(response).check_return_status() + self.check_execution_response_status(response, "delete_global_ip_pool").check_return_status() executionid = response.get("executionId") # Update result information diff --git a/plugins/modules/template_workflow_manager.py b/plugins/modules/template_workflow_manager.py index afa3fc2b17..976cbd6e5d 100644 --- a/plugins/modules/template_workflow_manager.py +++ b/plugins/modules/template_workflow_manager.py @@ -2181,6 +2181,7 @@ def handle_export(self, export): validation_string = "successfully exported project" self.check_task_response_status(response, validation_string, + "export_projects", True).check_return_status() self.result['response'][1].get("export").get("response").update({"exportProject": self.msg}) @@ -2200,6 +2201,7 @@ def handle_export(self, export): validation_string = "successfully exported template" self.check_task_response_status(response, validation_string, + "export_templates", True).check_return_status() self.result['response'][1].get("export").get("response").update({"exportTemplate": self.msg}) @@ -2248,7 +2250,7 @@ def handle_import(self, _import): params=_import_project, ) validation_string = "successfully imported project" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "imports_the_projects_provided").check_return_status() self.result['response'][2].get("import").get("response").update({"importProject": validation_string}) else: self.msg = "Projects '{0}' already available.".format(payload) @@ -2334,7 +2336,7 @@ def handle_import(self, _import): params=import_template ) validation_string = "successfully imported template" - self.check_task_response_status(response, validation_string).check_return_status() + self.check_task_response_status(response, validation_string, "imports_the_templates_provided").check_return_status() self.result['response'][2].get("import").get("response") \ .update({"importTemplate": "Successfully imported the templates"}) From e6de4ad067d09686d36afcc335a7fb1e8f2c4d0f Mon Sep 17 00:00:00 2001 From: MUTHU-RAKESH-27 <19cs127@psgitech.ac.in> Date: Fri, 7 Jun 2024 13:11:59 +0530 Subject: [PATCH 4/4] Addressed the review comments --- plugins/module_utils/dnac.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/module_utils/dnac.py b/plugins/module_utils/dnac.py index a890469c9d..0dae9078f7 100644 --- a/plugins/module_utils/dnac.py +++ b/plugins/module_utils/dnac.py @@ -302,7 +302,7 @@ def get_task_details(self, task_id): return result - def check_task_response_status(self, response, validation_string, api_name="", data=False): + def check_task_response_status(self, response, validation_string, api_name, data=False): """ Get the site id from the site name. @@ -391,7 +391,7 @@ def get_execution_details(self, execid): self.log("Response for the current execution: {0}".format(response)) return response - def check_execution_response_status(self, response, api_name=""): + def check_execution_response_status(self, response, api_name): """ Checks the reponse status provided by API in the Cisco Catalyst Center