Skip to content

Commit

Permalink
Merge pull request #45 from madhansansel/main
Browse files Browse the repository at this point in the history
latest changes 04/08/2024
  • Loading branch information
rukapse authored Apr 8, 2024
2 parents 59e394d + fd9dcc8 commit b6ae730
Show file tree
Hide file tree
Showing 12 changed files with 844 additions and 518 deletions.
14 changes: 14 additions & 0 deletions changelogs/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,20 @@ releases:
- Added attributes 'dnac_api_task_timeout' and 'dnac_task_poll_interval' in intent and workflow_manager modules.
- inventory_workflow_manager - Added attributes 'add_user_defined_field', 'update_interface_details', 'export_device_list' and 'admin_status'
- inventory_workflow_manager - Removed attributes 'provision_wireless_device', 'reprovision_wired_device'
6.13.2:
release_date: "2024-04-03"
changes:
release_summary: Enhancements in discovery, site, swim and inventory workflow manager modules.
minor_changes:
- Added the op_modifies=True when calling SDK APIs in the workflow manager modules.
- Added a method to validate IP addresses.
- Fixed a minor issue in the site workflow manager module.
- Updating galaxy.yml ansible.utils dependencies.
6.13.3:
release_date: "2024-04-08"
changes:
release_summary: Enhancements in discovery, template, swim and inventory workflow manager modules.
minor_changes:
- Adding support to importing a template using JSON file
- Changes in discovery workflow manager modules relating to different states of the discovery job
- Changes in inventory and swim workflow manager modules.
4 changes: 2 additions & 2 deletions galaxy.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
namespace: cisco
name: dnac
version: 6.13.1
version: 6.13.3
readme: README.md
authors:
- Rafael Campos <[email protected]>
Expand All @@ -27,7 +27,7 @@ tags:
- networking
- sdn
dependencies:
ansible.utils: ">=2.0.0,<4.0"
ansible.utils: ">=2.0.0,<5.0"
repository: https://github.com/cisco-en-programmability/dnacenter-ansible
documentation: https://cisco-en-programmability.github.io/dnacenter-ansible/
homepage: https://github.com/cisco-en-programmability/dnacenter-ansible
Expand Down
20 changes: 1 addition & 19 deletions playbooks/device_details.template
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,7 @@ template_details:
import_template:
do_version: false
project_name: 'Onboarding Configuration'
payload:
- name: 'Platinum-Onboarding-Template-J21'
device_types:
- product_family: 'Switches and Hubs'
productSeries: 'Cisco Catalyst 9300 Series Switches'
software_type: 'IOS'
language: 'JINJA'
- name: 'Platinum-Onboarding-Template-J22'
device_types:
- product_family: 'Switches and Hubs'
productSeries: 'Cisco Catalyst 9300 Series Switches'
software_type: 'IOS'
language: 'JINJA'
- name: 'Platinum-Onboarding-Template-J23'
device_types:
- product_family: 'Switches and Hubs'
productSeries: 'Cisco Catalyst 9300 Series Switches'
software_type: 'IOS'
language: 'JINJA'
template_file: 'JSON template file'

device_details:
- site_name: 'Global/Chennai/Trill'
Expand Down
10 changes: 5 additions & 5 deletions playbooks/template_workflow_manager.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
dnac_password: "{{ dnac_password }}"
dnac_verify: "{{ dnac_verify }}"
dnac_debug: "{{ dnac_debug }}"
dnac_log: true
dnac_log_level: "{{ dnac_debug }}"
dnac_log_append: true
dnac_log: True
dnac_log_level: DEBUG
dnac_log_append: True
dnac_log_file_path: "{{ dnac_log_file_path }}"
validate_response_schema: false
validate_response_schema: False
state: "merged"
config_verify: true
#ignore_errors: true #Enable this to continue execution even the task fails
Expand All @@ -41,7 +41,7 @@
template_name: AP_Onboarding
import:
project: "{{ item.import_project }}"
# template: "{{ item.import_template }}"
template: "{{ item.import_template }}"
register: template_result
with_items: '{{ template_details }}'
tags:
Expand Down
36 changes: 36 additions & 0 deletions plugins/module_utils/dnac.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,42 @@ def is_valid_ipv4(self, ip_address):
except socket.error:
return False

def is_path_exists(self, file_path):
"""
Check if the file path 'file_path' exists or not.
Parameters:
file_path (string) - Path of the provided file.
Returns:
True/False (bool) - True if the file path exists, else False.
"""

if not os.path.exists(file_path):
return False

return True

def is_json(self, file_path):
"""
Check if the file in the file path is JSON or not.
Parameters:
file_path (string) - Path of the provided file.
Returns:
True/False (bool) - True if the file is in JSON format, else False.
"""

try:
with open(file_path, 'r') as file:
json.load(file)
return True

except (ValueError, FileNotFoundError):
self.log("The provided file '{0}' is not in JSON format".format(file_path), "CRITICAL")
return False


def is_list_complex(x):
return isinstance(x[0], dict) or isinstance(x[0], list)
Expand Down
103 changes: 81 additions & 22 deletions plugins/modules/discovery_intent.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@
pass a list with single element like - 10.197.156.22. For CIDR based discovery, we should pass a list with
single element like - 10.197.156.22/22. For RANGE based discovery, we should pass a list with single element
and range like - 10.197.156.1-10.197.156.100. For MULTI RANGE based discovery, we should pass a list with multiple
elementd like - 10.197.156.1-10.197.156.100 and in next line - 10.197.157.1-10.197.157.100.
elementd like - 10.197.156.1-10.197.156.100 and in next line - 10.197.157.1-10.197.157.100. Maximum of 8 IP address ranges
are allowed.
type: list
elements: str
required: true
Expand Down Expand Up @@ -1060,6 +1061,10 @@ def preprocess_device_discovery(self, ip_address_list=None):
else:
self.preprocess_device_discovery_handle_error()
else:
if len(ip_address_list) > 8:
msg = "Maximum of 8 IP ranges are allowed."
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
new_ip_collected = []
for ip in ip_address_list:
if len(str(ip).split("-")) != 2:
Expand Down Expand Up @@ -1305,11 +1310,11 @@ def create_discovery(self, ip_address_list=None):
self.log("Task Id of the API task created is {0}".format(result.response.get('taskId')), "INFO")
return result.response.get('taskId')

def get_task_status(self, task_id=None):
def get_merged_task_status(self, task_id=None):
"""
Monitor the status of a task in the Cisco Catalyst Center. It checks the task
status periodically until the task is no longer 'In Progress'.
If the task encounters an error or fails, it immediately fails the
Monitor the status of a task of creation of dicovery in the Cisco Catalyst Center.
It checks the task status periodically until the task is no longer 'In Progress'
or other states. If the task encounters an error or fails, it immediately fails the
module and returns False.
Parameters:
Expand All @@ -1329,7 +1334,7 @@ def get_task_status(self, task_id=None):
op_modifies=True,
)
response = response.response
self.log("Task status for the task id {0} is {1}".format(str(task_id), str(response)), "INFO")
self.log("Task status for the task id {0} is {1}, is_error: {2}".format(str(task_id), str(response), str(response.get('isError'))), "INFO")
if response.get('isError') or re.search(
'failed', response.get('progress'), flags=re.IGNORECASE
):
Expand All @@ -1338,17 +1343,62 @@ def get_task_status(self, task_id=None):
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
return False

self.log("Task status for the task id (before checking status) {0} is {1}".format(str(task_id), str(response)), "INFO")
progress = response.get('progress')
if progress in ('In Progress', 'Inventory service initiating discovery'):
try:
progress_value = int(progress)
result = True
self.log("The discovery process is completed", "INFO")
self.result.update(dict(discovery_task=response))
return result
except Exception:
self.log("The progress status is {0}, continue to check the status after 3 seconds. Putting into sleep for 3 seconds".format(progress))
time.sleep(3)
continue
else:

def get_deleted_task_status(self, task_id=None):
"""
Monitor the status of a task of deletion of dicovery in the Cisco Catalyst Center.
It checks the itask status periodically until the task is 'Discovery deleted successfully'.
If the task encounters an error or fails, it immediately fails the module and returns False.
Parameters:
- task_id: The ID of the task to monitor.
Returns:
- result: True if the task completed successfully, False otherwise.
"""

result = False
params = dict(task_id=task_id)
while True:
response = self.dnac_apply['exec'](
family="task",
function='get_task_by_id',
params=params,
op_modifies=True,
)
response = response.response
self.log("Task status for the task id {0} is {1}, is_error: {2}".format(str(task_id), str(response), str(response.get('isError'))), "INFO")
if response.get('isError') or re.search(
'failed', response.get('progress'), flags=re.IGNORECASE
):
msg = 'Discovery task with id {0} has not completed - Reason: {1}'.format(
task_id, response.get("failureReason"))
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
return False

self.log("Task status for the task id (before checking status) {0} is {1}".format(str(task_id), str(response)), "INFO")
progress = response.get('progress')
if re.search('Discovery deleted successfully.', response.get('progress')):
result = True
self.log("The Process is completed", "INFO")
break
self.result.update(dict(discovery_task=response))
return result
self.log("The discovery process is completed", "INFO")
self.result.update(dict(discovery_task=response))
return result

self.log("The progress status is {0}, continue to check the status after 3 seconds. Putting into sleep for 3 seconds".format(progress))
time.sleep(3)

def lookup_discovery_by_range_via_name(self):
"""
Expand Down Expand Up @@ -1414,6 +1464,7 @@ def get_discoveries_by_range_until_success(self):
"""

result = False
aborted = False
discovery = self.lookup_discovery_by_range_via_name()

if not discovery:
Expand All @@ -1424,17 +1475,25 @@ def get_discoveries_by_range_until_success(self):

while True:
discovery = self.lookup_discovery_by_range_via_name()
if discovery.get('discoveryCondition') == 'Complete':
discovery_condition = discovery.get('discoveryCondition')
if discovery_condition == 'Complete':
result = True
break

elif discovery_condition == 'Aborted':
aborted = True
break
time.sleep(3)

if not result:
msg = 'Cannot find any discovery task with name {0} -- Discovery result: {1}'.format(
str(self.validated_config[0].get("discovery_name")), str(discovery))
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
if aborted is True:
msg = 'Discovery with name {0} is aborted by the user on the GUI'.format(str(self.validated_config[0].get("discovery_name")))
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)
else:
msg = 'Cannot find any discovery task with name {0} -- Discovery result: {1}'.format(
str(self.validated_config[0].get("discovery_name")), str(discovery))
self.log(msg, "CRITICAL")
self.module.fail_json(msg=msg)

self.result.update(dict(discovery_range=discovery))
return discovery
Expand Down Expand Up @@ -1563,11 +1622,11 @@ def get_diff_merged(self):
if exist_discovery:
params = dict(id=exist_discovery.get('id'))
discovery_task_id = self.delete_exist_discovery(params=params)
complete_discovery = self.get_task_status(task_id=discovery_task_id)
complete_discovery = self.get_deleted_task_status(task_id=discovery_task_id)

discovery_task_id = self.create_discovery(
ip_address_list=ip_address_list)
complete_discovery = self.get_task_status(task_id=discovery_task_id)
complete_discovery = self.get_merged_task_status(task_id=discovery_task_id)
discovery_task_info = self.get_discoveries_by_range_until_success()
result = self.get_discovery_device_info(discovery_id=discovery_task_info.get('id'))
self.result["changed"] = True
Expand Down Expand Up @@ -1620,7 +1679,7 @@ def get_diff_deleted(self):

params = dict(id=exist_discovery.get('id'))
discovery_task_id = self.delete_exist_discovery(params=params)
complete_discovery = self.get_task_status(task_id=discovery_task_id)
complete_discovery = self.get_deleted_task_status(task_id=discovery_task_id)
self.result["changed"] = True
self.result['msg'] = "Successfully deleted discovery"
self.result['diff'] = self.validated_config
Expand Down
Loading

0 comments on commit b6ae730

Please sign in to comment.