diff --git a/Pipfile b/Pipfile new file mode 100644 index 0000000000..fbe2bde8da --- /dev/null +++ b/Pipfile @@ -0,0 +1,12 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] +dnacentersdk = ">=2.7.0" + +[dev-packages] + +[requires] +python_version = "3.12" diff --git a/README.md b/README.md index 4d2835f33d..7909c6776b 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ The dnacenter-ansible project provides an Ansible collection for managing and automating your Cisco DNA Center environment. It consists of a set of modules and roles for performing tasks related to DNA Center. -This collection has been tested and supports Cisco DNA Center 2.3.5.3. +This collection has been tested and supports Cisco DNA Center 2.3.7.6. *Note: This collection is not compatible with versions of Ansible before v2.8.* @@ -15,11 +15,11 @@ The following table shows the supported versions. | Cisco DNA Center version | Ansible "cisco.dnac" version | Python "dnacentersdk" version | |--------------------------|------------------------------|-------------------------------| -| 2.1.1 | 3.0.0 | 2.2.5 | | 2.2.2.3 | 3.3.1 | 2.3.3 | | 2.2.3.3 | 6.4.0 | 2.4.11 | | 2.3.3.0 | 6.6.4 | 2.5.5 | -| 2.3.5.3 | ^6.13.0 | ^2.6.0 | +| 2.3.5.3 | 6.13.3 | 2.6.11 | +| 2.3.7.6 | ^6.14.0 | ^2.7.1 | If your Ansible collection is older please consider updating it first. @@ -45,7 +45,7 @@ ansible-galaxy collection install cisco.dnac:3.3.1 ## Requirements - Ansible >= 2.15 -- [Python DNA Center SDK](https://github.com/cisco-en-programmability/dnacentersdk) v2.6.0 or newer +- [Python DNA Center SDK](https://github.com/cisco-en-programmability/dnacentersdk) v2.7.0 or newer - Python >= 3.9, as the DNA Center SDK doesn't support Python version 2.x ## Install @@ -76,7 +76,7 @@ export DNAC_HOST= export DNAC_PORT=443 # optional, defaults to 443 export DNAC_USERNAME= export DNAC_PASSWORD= -export DNAC_VERSION=2.3.5.3 # optional, defaults to 2.3.5.3. See the Compatibility matrix +export DNAC_VERSION=2.3.7.6 # optional, defaults to 2.3.7.6. See the Compatibility matrix export DNAC_VERIFY=False # optional, defaults to True export DNAC_DEBUG=False # optional, defaults to False ``` @@ -114,7 +114,7 @@ dnac_host: dnac_port: 443 # optional, defaults to 443 dnac_username: dnac_password: -dnac_version: 2.3.5.3 # optional, defaults to 2.3.5.3. See the Compatibility matrix +dnac_version: 2.3.7.6 # optional, defaults to 2.3.7.6. See the Compatibility matrix dnac_verify: False # optional, defaults to True dnac_debug: False # optional, defaults to False ``` diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index 81e4f43487..e1ce85f173 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -865,4 +865,47 @@ releases: 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 + 6.14.0: + release_date: "2024-05-31" + changes: + release_summary: New Dna Center API version 2.3.7.6, and addition of Workflow Manager modules support for device configuration backups, events and notifications, ISE and RADIUS server integrations, and network compliance. + minor_changes: + - device_configs_backup_workflow_manager - New workflow manager module for device configuration backup functions. + - events_and_notifications_workflow_manager - New workflow manager for configuring various types of destinations(Webhook, Email, Syslog, SNMP, ITSM) to deliver event notifications. + - ise_radius_integration_workflow_manager - New workflow manager for Authentication and Policy Servers(ISE/AAA). + - network_compliance_workflow_manager - New workflow manager for Network Compliance module for managing network compliance tasks on reachable device(s). + - device_credential_workflow_manager - Updated the log messages. + - inventory_workflow_manager - Updated changes related to provisioning devices. + - provision_workflow_manager - Updated changes related to handle errors. + - site_workflow_manager - Updated changes in Site updation. + - network_settings_workflow_manager - Added attributes 'ipv4_global_pool_name'. + - template_workflow_manager - Removed attributes 'create_time', 'failure_policy', 'last_update_time', 'latest_version_time', 'parent_template_id', 'project_id', 'validation_errors', 'rollback_template_params' and 'rollback_template_content'. - Changes in inventory and swim workflow manager modules. + - application_policy_application_set_count_info - new module + - application_policy_application_set_info - new module + - application_policy_application_set - new module + - applications_count_v2_info - new module + - applications_v2_info - new module + - applications_v2 - new module + - auth_token_create - new module + - authentication_policy_servers - new module + - device_reboot_apreboot - new module + - dna_event_snmp_config_info - new module + - event_snmp_config - new module + - event_webhook_read_info - new module + - flexible_report_content_info - new module + - flexible_report_execute - new module + - flexible_report_executions_info - new module + - flexible_report_schedule_info - new module + - flexible_report_schedule - new module + - integration_settings_itsm_instances_info - new module + - integration_settings_status_info - new module + - ise_integration_status_info - new module + - lan_automation_sessions_info - new module + - lan_automation_update_device - new module + - lan_automation_update_v2 - new module + - lan_automation_update - new module + - lan_automation_v2 - new module + - network_device_user_defined_field_delete - new module + - users_external_authentication - new module + - users_external_servers_aaa_attribute - new module diff --git a/galaxy.yml b/galaxy.yml index 9858ed672f..e07c825ab1 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,7 +1,7 @@ --- namespace: cisco name: dnac -version: 6.13.3 +version: 6.14.0 readme: README.md authors: - Rafael Campos diff --git a/playbooks/configs_backup.yml b/playbooks/configs_backup.yml new file mode 100644 index 0000000000..696e021843 --- /dev/null +++ b/playbooks/configs_backup.yml @@ -0,0 +1,39 @@ +--- +- name: Take running config backup of devices + hosts: localhost + connection: local + gather_facts: no + + vars_files: + - "{{ CLUSTERFILE }}" + + vars: + dnac_login: &dnac_login + dnac_host: "{{ dnac_host }}" + dnac_username: "{{ dnac_username }}" + dnac_password: "{{ dnac_password }}" + dnac_verify: "{{ dnac_verify }}" + dnac_port: "{{ dnac_port }}" + dnac_version: "{{ dnac_version }}" + dnac_debug: "{{ dnac_debug }}" + dnac_log_level: "DEBUG" + + tasks: + - name: Take backup of a wired 9500 switch + cisco.dnac.device_configs_backup_workflow_manager: + <<: *dnac_login + dnac_log: True + state: merged + config_verify: True + config: + - hostname: NY-BN-9500.cisco.local + file_path: /home/admin/madhan_ansible/collections/ansible_collections/cisco/dnac/playbooks/new_tmp + + - name: Take backup of all the switches + cisco.dnac.device_configs_backup_workflow_manager: + <<: *dnac_login + dnac_log: True + state: merged + config_verify: True + config: + - family: Switches and Hubs \ No newline at end of file diff --git a/playbooks/credentials.template b/playbooks/credentials.template index 5270c08164..4e2878d254 100644 --- a/playbooks/credentials.template +++ b/playbooks/credentials.template @@ -3,7 +3,7 @@ dnac_host: dnac_port: 443 dnac_username: dnac_password: -dnac_version: 2.3.5.3 +dnac_version: 2.3.7.6 dnac_verify: False dnac_debug: False dnac_log_level: [CRITICAL, ERROR, WARNING, INFO, DEBUG] diff --git a/playbooks/device_credential_workflow_manager.yml b/playbooks/device_credential_workflow_manager.yml index 3d77584f06..ffdc841100 100644 --- a/playbooks/device_credential_workflow_manager.yml +++ b/playbooks/device_credential_workflow_manager.yml @@ -4,7 +4,7 @@ gather_facts: no connection: local tasks: - - name: Create Credentials and assign it to a site. + - name: Create global device credentials. cisco.dnac.device_credential_workflow_manager: dnac_host: "{{ dnac_host }}" dnac_port: "{{ dnac_port }}" @@ -14,6 +14,7 @@ dnac_debug: "{{ dnac_debug }}" dnac_log: True state: merged + config_verify: True config: - global_credential_details: cli_credential: @@ -54,7 +55,20 @@ port: 443 # old_description: # old_username: - assign_credentials_to_site: + + - name: Assign global device credentials to a site. + cisco.dnac.device_credential_workflow_manager: + dnac_host: "{{ dnac_host }}" + dnac_port: "{{ dnac_port }}" + dnac_username: "{{ dnac_username }}" + dnac_password: "{{ dnac_password }}" + dnac_verify: "{{ dnac_verify }}" + dnac_debug: "{{ dnac_debug }}" + dnac_log: True + state: merged + config_verify: True + config: + - assign_credentials_to_site: cli_credential: description: CLI username: cli @@ -74,7 +88,7 @@ - Global/Chennai/Trill - Global/Chennai/Tidel - - name: Delete Credentials + - name: Delete credentials cisco.dnac.device_credential_workflow_manager: dnac_host: "{{ dnac_host }}" dnac_port: "{{ dnac_port }}" @@ -84,6 +98,7 @@ dnac_debug: "{{ dnac_debug }}" dnac_log: True state: deleted + config_verify: True config: - global_credential_details: cli_credential: diff --git a/playbooks/dnac.log b/playbooks/dnac.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/playbooks/events_and_notifications_workflow_manager.yml b/playbooks/events_and_notifications_workflow_manager.yml new file mode 100644 index 0000000000..a30918474b --- /dev/null +++ b/playbooks/events_and_notifications_workflow_manager.yml @@ -0,0 +1,65 @@ +--- +- name: Configure channels and create events in Cisco Catalyst Center + hosts: localhost + connection: local + gather_facts: no + vars_files: + - "input_events_and_notification.yml" + - "credentials.yml" + tasks: + - name: Add/update channels with destination and create/update events in Cisco Catalyst Center. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: DEBUG + dnac_log: true + config_verify: true + state: merged + config: + - syslog_destination: + name: "{{item.syslog_destination.name}}" + description: "{{item.syslog_destination.description}}" + server_address: "{{item.syslog_destination.server_address}}" + protocol: "{{item.syslog_destination.protocol}}" + port: "{{item.syslog_destination.port}}" + webhook_destination: + name: "{{item.webhook_destination.name}}" + description: "{{item.webhook_destination.description}}" + url: "{{item.webhook_destination.url}}" + method: "{{item.webhook_destination.method}}" + trust_cert: "{{item.webhook_destination.trust_cert}}" + email_destination: + from_email: "{{item.email_destination.from_email}}" + to_email: "{{item.email_destination.to_email}}" + subject: "{{item.email_destination.subject}}" + primary_smtp_config: + server_address: "{{item.email_destination.primary_smtp_config.server_address}}" + port: "{{item.email_destination.primary_smtp_config.port}}" + snmp_destination: + name: "{{item.snmp_destination.name}}" + description: "{{item.snmp_destination.description}}" + server_address: "{{item.snmp_destination.server_address}}" + port: "{{item.snmp_destination.port}}" + snmp_version: "{{item.snmp_destination.snmp_version}}" + username: "{{item.snmp_destination.username}}" + mode: "{{item.snmp_destination.mode}}" + auth_type: "{{item.snmp_destination.auth_type}}" + auth_password: "{{item.snmp_destination.auth_password}}" + privacy_type: "{{item.snmp_destination.privacy_type}}" + privacy_password: "{{item.snmp_destination.privacy_password}}" + itsm_setting: + instance_name: "{{item.itsm_setting.instance_name}}" + description: "{{item.itsm_setting.description}}" + connection_settings: + url: "{{item.itsm_setting.connection_settings.url}}" + username: "{{item.itsm_setting.connection_settings.username}}" + password: "{{item.itsm_setting.connection_settings.password}}" + + with_items: "{{ events_notification }}" + tags: + - events_testing diff --git a/playbooks/input_events_and_notification.yml b/playbooks/input_events_and_notification.yml new file mode 100644 index 0000000000..3642c4ce09 --- /dev/null +++ b/playbooks/input_events_and_notification.yml @@ -0,0 +1,40 @@ +--- +events_notification: + - syslog_destination: + name: Syslog Demo test + description: "Adding syslog destination for testing" + server_address: "10.30.0.90" + protocol: "TCP" + port: 652 + webhook_destination: + name: "webhook demo 19" + description: "webhhok description for testing" + url: "https://10.195.227.14/dna" + method: "POST" + trust_cert: False + email_destination: + from_email: "test@cisco.com" + to_email: "abmahesh@cisco.com" + subject: "Ansible testing" + primary_smtp_config: + server_address: "outbound.cisco.com" + port: '25' + snmp_destination: + name: Snmp test + description: "Adding snmp destination for testing for update" + server_address: "10.30.0.91" + port: '265' + snmp_version: "V3" + username: cisco123 + mode: AUTH_PRIVACY + auth_type: SHA + auth_password: authpass123 + privacy_type: AES128 + privacy_password: privacy123 + itsm_setting: + instance_name: "Playbook itsm demo" + description: "ITSM description for testing" + connection_settings: + url: "https://catalystcente1.com" + username: "catalyst" + password: "catalyst@123" diff --git a/playbooks/ise_radius_integration_workflow_manager.yml b/playbooks/ise_radius_integration_workflow_manager.yml new file mode 100644 index 0000000000..28dd61696f --- /dev/null +++ b/playbooks/ise_radius_integration_workflow_manager.yml @@ -0,0 +1,111 @@ +- hosts: dnac_servers + vars_files: + - credentials.yml + gather_facts: no + connection: local + tasks: + - name: Create an Authentication and Policy Server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{ dnac_host }}" + dnac_port: "{{ dnac_port }}" + dnac_username: "{{ dnac_username }}" + dnac_password: "{{ dnac_password }}" + dnac_verify: "{{ dnac_verify }}" + dnac_debug: "{{ dnac_debug }}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + dnac_log_append: True + dnac_log_file_path: "{{ dnac_log_file_path }}" + state: merged + config_verify: True + config: + - authentication_policy_server: + server_type: AAA # [ISE, AAA] + server_ip_address: 10.0.0.20 + shared_secret: cisco + protocol: RADIUS_TACACS # [TACACS, RADIUS, RADIUS_TACACS] + encryption_scheme: KEYWRAP # KEYWRAP or RADSEC + encryption_key: dnacsolutions123 # For KEYWRAP, must be 16 char long + message_authenticator_code_key: dnacisesolutions1234 # For KEYWRAP, must be 20 char long + authentication_port: 1800 + accounting_port: 1700 + port: 40 # For TACACS + retries: 3 # Range from 1 to 3 + timeout: 4 # Range from 2 to 20 + role: secondary + + - name: Delete Authentication and Policy Server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{ dnac_host }}" + dnac_port: "{{ dnac_port }}" + dnac_username: "{{ dnac_username }}" + dnac_password: "{{ dnac_password }}" + dnac_verify: "{{ dnac_verify }}" + dnac_debug: "{{ dnac_debug }}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + dnac_log_append: True + dnac_log_file_path: "{{ dnac_log_file_path }}" + state: deleted + config_verify: True + config: + - authentication_policy_server: + server_ip_address: 10.0.0.20 + + - name: Create ISE Server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{ dnac_host }}" + dnac_port: "{{ dnac_port }}" + dnac_username: "{{ dnac_username }}" + dnac_password: "{{ dnac_password }}" + dnac_verify: "{{ dnac_verify }}" + dnac_debug: "{{ dnac_debug }}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + dnac_log_append: True + dnac_log_file_path: "{{ dnac_log_file_path }}" + state: merged + config_verify: True + config: + - authentication_policy_server: + server_type: ISE # [ISE, AAA] + server_ip_address: 10.195.243.59 + shared_secret: cisco + protocol: RADIUS_TACACS # [TACACS, RADIUS, RADIUS_TACACS] + encryption_scheme: KEYWRAP # KEYWRAP or RADSEC + encryption_key: dnacsolutions123 # For KEYWRAP, must be 16 char long + message_authenticator_code_key: dnacisesolutions1234 # For KEYWRAP, must be 20 char long + authentication_port: 1800 + accounting_port: 1700 + port: 40 # For TACACS + retries: 3 # Range from 1 to 3 + timeout: 4 # Range from 2 to 20 + role: primary + pxgrid_enabled: False # Avaliable for Cisco ISE only + use_dnac_cert_for_pxgrid: False + cisco_ise_dtos: # use this for creating the Cisco ISE Server + - user_name: admin + password: abcd + fqdn: abc.cisco.com + ip_address: 10.195.243.59 + subscriber_name: abcde + description: CISCO ISE + trusted_server: True + + - name: Delete an ISE Server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{ dnac_host }}" + dnac_port: "{{ dnac_port }}" + dnac_username: "{{ dnac_username }}" + dnac_password: "{{ dnac_password }}" + dnac_verify: "{{ dnac_verify }}" + dnac_debug: "{{ dnac_debug }}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + dnac_log_append: True + dnac_log_file_path: "{{ dnac_log_file_path }}" + state: deleted + config_verify: True + config: + - authentication_policy_server: + server_ip_address: 10.195.243.59 diff --git a/playbooks/network_compliance_workflow_manager.yml b/playbooks/network_compliance_workflow_manager.yml new file mode 100644 index 0000000000..7bbe82f6c5 --- /dev/null +++ b/playbooks/network_compliance_workflow_manager.yml @@ -0,0 +1,151 @@ +--- +- name: Testing + hosts: dnac_servers + gather_facts: no + + vars_files: + - "credentials.yml" + + vars: + dnac_login: &dnac_login + dnac_host: "{{ dnac_host }}" + dnac_username: "{{ dnac_username }}" + dnac_password: "{{ dnac_password }}" + dnac_verify: "{{ dnac_verify }}" + dnac_port: "{{ dnac_port }}" + dnac_version: "{{ dnac_version }}" + dnac_debug: "{{ dnac_debug }}" + dnac_log: true + dnac_log_level: INFO + dnac_log_append: False + config_verify: true + + tasks: + - name: Run Compliance check using IP address list (run_compliance by default is True) + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + + - name: Run Compliance check using IP address list + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + run_compliance: True + + + - name: Run Compliance check using Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - site: "Global" + run_compliance: True + + + - name: Run Compliance check using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + + + - name: Run Compliance check with specific categories using IP address list + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + run_compliance_categories: ['INTENT', 'RUNNING_CONFIG', 'IMAGE', 'PSIRT'] + + + - name: Run Compliance check with specific categories using Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - site_name: "Global" + run_compliance_categories: ['INTENT', 'RUNNING_CONFIG', 'IMAGE', 'PSIRT'] + + + - name: Run Compliance check with specific categories using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance_categories: ['INTENT', 'RUNNING_CONFIG', 'IMAGE', 'PSIRT'] + + + - name: Sync Device Configuration using IP address list + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + run_compliance: False + sync_device_config: True + + + - name: Sync Device Configuration using Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: False + sync_device_config: True + + + - name: Sync Device Configuration using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: False + sync_device_config: True + + + - name: Run Compliance and Sync Device Configuration with IP address list + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + run_compliance: True + sync_device_config: True + + + - name: Run Compliance and Sync Device Configuration with Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + sync_device_config: True + + + - name: Run Compliance with specific categories and Sync Device Configuration with IP address list + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + run_compliance_categories: ['INTENT', 'RUNNING_CONFIG', 'IMAGE', 'PSIRT'] + sync_device_config: True + + + - name: Run Compliance with specific categories and Sync Device Configuration with Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance_categories: ['INTENT', 'RUNNING_CONFIG', 'IMAGE', 'PSIRT'] + sync_device_config: True + + + - name: Run Compliance and Sync Device Configuration using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + <<: *dnac_login + config: + - ip_address_list: ['204.1.2.2', '204.1.2.5', '204.1.2.4'] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + sync_device_config: True diff --git a/playbooks/network_settings_workflow_manager.yml b/playbooks/network_settings_workflow_manager.yml index 36b88ac2db..877b7849ca 100644 --- a/playbooks/network_settings_workflow_manager.yml +++ b/playbooks/network_settings_workflow_manager.yml @@ -13,7 +13,7 @@ dnac_verify: "{{ dnac_verify }}" dnac_debug: "{{ dnac_debug }}" dnac_log: True - dnac_log_level: "{{ dnac_log_level }}" + dnac_log_level: DEBUG dnac_log_append: True dnac_log_file_path: "{{ dnac_log_file_path }}" state: merged @@ -23,58 +23,70 @@ settings: ip_pool: - name: Global_Pool2 - gateway: '' #use this for updating + pool_type: Generic ip_address_space: IPv6 #required when we are creating cidr: 2001:db8::/64 #required when we are creating + gateway: '' #use this for updating + dhcp_server_ips: [] #use this for updating + dns_server_ips: [] #use this for updating + # prev_name: Global_Pool2 + - name: Global_Pool3 pool_type: Generic + ip_address_space: IPv4 #required when we are creating + cidr: 10.0.0.0/8 #required when we are creating + gateway: '' #use this for updating dhcp_server_ips: [] #use this for updating dns_server_ips: [] #use this for updating # prev_name: Global_Pool2 reserve_pool_details: + - site_name: Global/Chennai/Trill + name: IP_Pool_3 + pool_type: LAN ipv6_address_space: True - ipv4_global_pool: 100.0.0.0/8 + # ipv4_global_pool: 100.0.0.0/8 + ipv4_global_pool_name: Global_Pool1 ipv4_prefix: True ipv4_prefix_length: 9 ipv4_subnet: 100.128.0.0 ipv4_gateway: 100.128.0.1 - # ipv4_dns_servers: [100.128.0.1] - name: IP_Pool_3 + ipv4_dns_servers: [] ipv6_prefix: True ipv6_prefix_length: 64 ipv6_global_pool: 2001:db8::/64 + # ipv6_global_pool_name: Global_Pool2 ipv6_subnet: '2001:db8::' - site_name: Global/Chennai/Trill slaac_support: True # prev_name: IP_Pool_4 - pool_type: LAN network_management_details: + site_name: Global/Chennai settings: - dhcp_server: - - 10.0.0.1 - dns_server: - domain_name: cisco.com - primary_ip_address: 10.0.0.2 - secondary_ip_address: 10.0.0.3 + network_aaa: #works only if we system settigns is set + ip_address: 10.0.0.21 #Mandatory for ISE, sec ip for AAA + network: 10.0.0.20 + protocol: TACACS + servers: AAA + # shared_secret: string #ISE client_and_endpoint_aaa: #works only if we system settigns is set ip_address: 10.197.156.42 #Mandatory for ISE, sec ip for AAA network: 10.0.0.20 protocol: RADIUS servers: AAA # shared_secret: string #ISE + dhcp_server: + - 10.0.0.1 + dns_server: + domain_name: cisco.com + primary_ip_address: 10.0.0.2 + secondary_ip_address: 10.0.0.3 + ntp_server: + - 10.0.0.5 + timezone: GMT message_of_the_day: banner_message: hello retain_existing_banner: 'true' netflow_collector: ip_address: 10.0.0.4 port: 443 - network_aaa: #works only if we system settigns is set - ip_address: 10.0.0.21 #Mandatory for ISE, sec ip for AAA - network: 10.0.0.20 - protocol: TACACS - servers: AAA - # shared_secret: string #ISE - ntp_server: - - 10.0.0.5 snmp_server: configure_dnac_ip: false # ip_addresses: @@ -83,8 +95,6 @@ configure_dnac_ip: false # ip_addresses: # - 10.0.0.7 - timezone: GMT - site_name: Global/Chennai - name: Delete Global Pool and Release Pool Reservation cisco.dnac.network_settings_workflow_manager: @@ -104,5 +114,5 @@ ip_pool: - name: Global_Pool2 reserve_pool_details: + - site_name: Global/Chennai/Trill name: IP_Pool_3 - site_name: Global/Chennai/Trill diff --git a/plugins/action/application_policy_application_set.py b/plugins/action/application_policy_application_set.py new file mode 100644 index 0000000000..171175d4a6 --- /dev/null +++ b/plugins/action/application_policy_application_set.py @@ -0,0 +1,234 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["id"], True), + ("state", "present", ["payload"], True), + ("state", "absent", ["id"], True), + ("state", "absent", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ApplicationPolicyApplicationSet(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['attributes'] = self.new_object.get('attributes') + new_object_params['name'] = name or self.new_object.get('name') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method, using get all + try: + items = self.dnac.exec( + family="application_policy", + function="get_application_sets2", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + o_id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("name", "name"), + ("scalableGroupType", "scalableGroupType"), + ("defaultBusinessRelevance", "defaultBusinessRelevance"), + ("namespace", "namespace"), + ("qualifier", "qualifier"), + ("type", "type"), + ("scalableGroupExternalHandle", "scalableGroupExternalHandle"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="application_policy", + function="create_application_sets", + params=self.create_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="application_policy", + function="delete_application_set", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = ApplicationPolicyApplicationSet(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + dnac.object_present_and_different() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/application_policy_application_set_count_info.py b/plugins/action/application_policy_application_set_count_info.py new file mode 100644 index 0000000000..3a0a27f675 --- /dev/null +++ b/plugins/action/application_policy_application_set_count_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + scalableGroupType=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + scalable_group_type=params.get("scalableGroupType"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="application_policy", + function='get_application_set_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/application_policy_application_set_info.py b/plugins/action/application_policy_application_set_info.py new file mode 100644 index 0000000000..360ffb79e5 --- /dev/null +++ b/plugins/action/application_policy_application_set_info.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + attributes=dict(type="str"), + name=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + attributes=params.get("attributes"), + name=params.get("name"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="application_policy", + function='get_application_sets2', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/application_sets.py b/plugins/action/application_sets.py index b1bc7f48bf..f6877a3313 100644 --- a/plugins/action/application_sets.py +++ b/plugins/action/application_sets.py @@ -37,6 +37,7 @@ required_if = [ ("state", "present", ["payload"], True), + ("state", "absent", ["payload"], True), ] required_one_of = [] mutually_exclusive = [] @@ -151,12 +152,15 @@ def create(self): return result def delete(self): - id = self.new_object.get("id") - name = self.new_object.get("name") + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") result = None result = self.dnac.exec( family="application_policy", - function="delete_application_set", + function="delete_application_set2", params=self.delete_all_params(), ) return result diff --git a/plugins/action/application_sets_info.py b/plugins/action/application_sets_info.py index 9e388f1ac8..870d0e3c1c 100644 --- a/plugins/action/application_sets_info.py +++ b/plugins/action/application_sets_info.py @@ -25,8 +25,8 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), name=dict(type="str"), headers=dict(type="dict"), )) diff --git a/plugins/action/applications.py b/plugins/action/applications.py index 81c404e886..cc378dc1b0 100644 --- a/plugins/action/applications.py +++ b/plugins/action/applications.py @@ -37,6 +37,7 @@ required_if = [ ("state", "present", ["payload"], True), + ("state", "absent", ["payload"], True), ] required_one_of = [] mutually_exclusive = [] @@ -79,7 +80,7 @@ def get_object_by_name(self, name): try: items = self.dnac.exec( family="application_policy", - function="get_applications", + function="get_applications2", params=self.get_all_params(name=name), ) if isinstance(items, dict): @@ -96,7 +97,7 @@ def get_object_by_id(self, id): try: items = self.dnac.exec( family="application_policy", - function="get_applications", + function="get_applications2", params=self.get_all_params(id=id), ) if isinstance(items, dict): @@ -175,12 +176,15 @@ def update(self): return result def delete(self): - id = self.new_object.get("id") - name = self.new_object.get("name") + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") result = None result = self.dnac.exec( family="application_policy", - function="delete_application", + function="delete_application2", params=self.delete_all_params(), ) return result diff --git a/plugins/action/applications_count_v2_info.py b/plugins/action/applications_count_v2_info.py new file mode 100644 index 0000000000..f8d2365693 --- /dev/null +++ b/plugins/action/applications_count_v2_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + scalableGroupType=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + scalable_group_type=params.get("scalableGroupType"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="application_policy", + function='get_application_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/applications_health_info.py b/plugins/action/applications_health_info.py index 31d101b24c..dcb74b44d4 100644 --- a/plugins/action/applications_health_info.py +++ b/plugins/action/applications_health_info.py @@ -28,11 +28,11 @@ siteId=dict(type="str"), deviceId=dict(type="str"), macAddress=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), applicationHealth=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), applicationName=dict(type="str"), headers=dict(type="dict"), )) diff --git a/plugins/action/applications_info.py b/plugins/action/applications_info.py index 8d12751750..5a1ccaf658 100644 --- a/plugins/action/applications_info.py +++ b/plugins/action/applications_info.py @@ -25,8 +25,8 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), name=dict(type="str"), headers=dict(type="dict"), )) @@ -85,7 +85,7 @@ def run(self, tmp=None, task_vars=None): response = dnac.exec( family="application_policy", - function='get_applications', + function='get_applications2', params=self.get_object(self._task.args), ) self._result.update(dict(dnac_response=response)) diff --git a/plugins/action/applications_v2.py b/plugins/action/applications_v2.py new file mode 100644 index 0000000000..3771bb0045 --- /dev/null +++ b/plugins/action/applications_v2.py @@ -0,0 +1,275 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["id"], True), + ("state", "present", ["payload"], True), + ("state", "absent", ["id"], True), + ("state", "absent", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ApplicationsV2(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['attributes'] = self.new_object.get('attributes') + new_object_params['name'] = name or self.new_object.get('name') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="application_policy", + function="get_applications", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="application_policy", + function="get_applications", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self): + id_exists = False + name_exists = False + prev_obj = None + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + o_id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("instanceId", "instanceId"), + ("displayName", "displayName"), + ("instanceVersion", "instanceVersion"), + ("indicativeNetworkIdentity", "indicativeNetworkIdentity"), + ("name", "name"), + ("namespace", "namespace"), + ("networkApplications", "networkApplications"), + ("networkIdentity", "networkIdentity"), + ("parentScalableGroup", "parentScalableGroup"), + ("qualifier", "qualifier"), + ("scalableGroupExternalHandle", "scalableGroupExternalHandle"), + ("scalableGroupType", "scalableGroupType"), + ("type", "type"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="application_policy", + function="create_applications", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="application_policy", + function="edit_applications", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="application_policy", + function="delete_application", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = ApplicationsV2(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/applications_v2_info.py b/plugins/action/applications_v2_info.py new file mode 100644 index 0000000000..394363c015 --- /dev/null +++ b/plugins/action/applications_v2_info.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + attributes=dict(type="str"), + name=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + attributes=params.get("attributes"), + name=params.get("name"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="application_policy", + function='get_applications', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/auth_token_create.py b/plugins/action/auth_token_create.py new file mode 100644 index 0000000000..64e868966f --- /dev/null +++ b/plugins/action/auth_token_create.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="authentication", + function='authentication_api', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/authentication_policy_servers.py b/plugins/action/authentication_policy_servers.py new file mode 100644 index 0000000000..ea97f45b36 --- /dev/null +++ b/plugins/action/authentication_policy_servers.py @@ -0,0 +1,338 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + authenticationPort=dict(type="int"), + accountingPort=dict(type="int"), + ciscoIseDtos=dict(type="list"), + ipAddress=dict(type="str"), + pxgridEnabled=dict(type="bool"), + useDnacCertForPxgrid=dict(type="bool"), + isIseEnabled=dict(type="bool"), + port=dict(type="int"), + protocol=dict(type="str"), + retries=dict(type="str"), + role=dict(type="str"), + sharedSecret=dict(type="str"), + timeoutSeconds=dict(type="str"), + encryptionScheme=dict(type="str"), + messageKey=dict(type="str"), + encryptionKey=dict(type="str"), + externalCiscoIseIpAddrDtos=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["id", "role"], True), + ("state", "absent", ["id", "role"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class AuthenticationPolicyServers(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + authenticationPort=params.get("authenticationPort"), + accountingPort=params.get("accountingPort"), + ciscoIseDtos=params.get("ciscoIseDtos"), + ipAddress=params.get("ipAddress"), + pxgridEnabled=params.get("pxgridEnabled"), + useDnacCertForPxgrid=params.get("useDnacCertForPxgrid"), + isIseEnabled=params.get("isIseEnabled"), + port=params.get("port"), + protocol=params.get("protocol"), + retries=params.get("retries"), + role=params.get("role"), + sharedSecret=params.get("sharedSecret"), + timeoutSeconds=params.get("timeoutSeconds"), + encryptionScheme=params.get("encryptionScheme"), + messageKey=params.get("messageKey"), + encryptionKey=params.get("encryptionKey"), + externalCiscoIseIpAddrDtos=params.get("externalCiscoIseIpAddrDtos"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['is_ise_enabled'] = self.new_object.get('isIseEnabled') or \ + self.new_object.get('is_ise_enabled') + new_object_params['state'] = self.new_object.get('state_') or \ + self.new_object.get('state') + new_object_params['role'] = self.new_object.get('role') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['authenticationPort'] = self.new_object.get('authenticationPort') + new_object_params['accountingPort'] = self.new_object.get('accountingPort') + new_object_params['ciscoIseDtos'] = self.new_object.get('ciscoIseDtos') + new_object_params['ipAddress'] = self.new_object.get('ipAddress') + new_object_params['pxgridEnabled'] = self.new_object.get('pxgridEnabled') + new_object_params['useDnacCertForPxgrid'] = self.new_object.get('useDnacCertForPxgrid') + new_object_params['isIseEnabled'] = self.new_object.get('isIseEnabled') + new_object_params['port'] = self.new_object.get('port') + new_object_params['protocol'] = self.new_object.get('protocol') + new_object_params['retries'] = self.new_object.get('retries') + new_object_params['role'] = self.new_object.get('role') + new_object_params['sharedSecret'] = self.new_object.get('sharedSecret') + new_object_params['timeoutSeconds'] = self.new_object.get('timeoutSeconds') + new_object_params['encryptionScheme'] = self.new_object.get('encryptionScheme') + new_object_params['messageKey'] = self.new_object.get('messageKey') + new_object_params['encryptionKey'] = self.new_object.get('encryptionKey') + new_object_params['externalCiscoIseIpAddrDtos'] = self.new_object.get('externalCiscoIseIpAddrDtos') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_by_id_params(self): + new_object_params = {} + new_object_params['authenticationPort'] = self.new_object.get('authenticationPort') + new_object_params['accountingPort'] = self.new_object.get('accountingPort') + new_object_params['ciscoIseDtos'] = self.new_object.get('ciscoIseDtos') + new_object_params['ipAddress'] = self.new_object.get('ipAddress') + new_object_params['pxgridEnabled'] = self.new_object.get('pxgridEnabled') + new_object_params['useDnacCertForPxgrid'] = self.new_object.get('useDnacCertForPxgrid') + new_object_params['isIseEnabled'] = self.new_object.get('isIseEnabled') + new_object_params['port'] = self.new_object.get('port') + new_object_params['protocol'] = self.new_object.get('protocol') + new_object_params['retries'] = self.new_object.get('retries') + new_object_params['role'] = self.new_object.get('role') + new_object_params['sharedSecret'] = self.new_object.get('sharedSecret') + new_object_params['timeoutSeconds'] = self.new_object.get('timeoutSeconds') + new_object_params['encryptionScheme'] = self.new_object.get('encryptionScheme') + new_object_params['messageKey'] = self.new_object.get('messageKey') + new_object_params['encryptionKey'] = self.new_object.get('encryptionKey') + new_object_params['externalCiscoIseIpAddrDtos'] = self.new_object.get('externalCiscoIseIpAddrDtos') + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="system_settings", + function="get_authentication_and_policy_servers", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="system_settings", + function="get_authentication_and_policy_servers", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self): + id_exists = False + name_exists = False + prev_obj = None + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("authenticationPort", "authenticationPort"), + ("accountingPort", "accountingPort"), + ("ciscoIseDtos", "ciscoIseDtos"), + ("ipAddress", "ipAddress"), + ("pxgridEnabled", "pxgridEnabled"), + ("useDnacCertForPxgrid", "useDnacCertForPxgrid"), + ("isIseEnabled", "isIseEnabled"), + ("port", "port"), + ("protocol", "protocol"), + ("retries", "retries"), + ("role", "role"), + ("sharedSecret", "sharedSecret"), + ("timeoutSeconds", "timeoutSeconds"), + ("encryptionScheme", "encryptionScheme"), + ("messageKey", "messageKey"), + ("encryptionKey", "encryptionKey"), + ("externalCiscoIseIpAddrDtos", "externalCiscoIseIpAddrDtos"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="system_settings", + function="add_authentication_and_policy_server_access_configuration", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="system_settings", + function="edit_authentication_and_policy_server_access_configuration", + params=self.update_by_id_params(), + op_modifies=True, + ) + return result + + def delete(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="system_settings", + function="delete_authentication_and_policy_server_access_configuration", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = AuthenticationPolicyServers(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/buildings_planned_access_points_info.py b/plugins/action/buildings_planned_access_points_info.py index 1668873255..3c8647ac18 100644 --- a/plugins/action/buildings_planned_access_points_info.py +++ b/plugins/action/buildings_planned_access_points_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( buildingId=dict(type="str"), - limit=dict(type="int"), - offset=dict(type="int"), + limit=dict(type="float"), + offset=dict(type="float"), radios=dict(type="bool"), headers=dict(type="dict"), )) diff --git a/plugins/action/cli_credential.py b/plugins/action/cli_credential.py index 2b42190fa3..d10c90049a 100644 --- a/plugins/action/cli_credential.py +++ b/plugins/action/cli_credential.py @@ -127,7 +127,7 @@ def exists(self): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("username") or self.new_object.get("description") + name = self.new_object.get("description") or self.new_object.get("username") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) diff --git a/plugins/action/client_detail_info.py b/plugins/action/client_detail_info.py index e09db53c86..59b7fd8bb9 100644 --- a/plugins/action/client_detail_info.py +++ b/plugins/action/client_detail_info.py @@ -25,8 +25,8 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - timestamp=dict(type="str"), macAddress=dict(type="str"), + timestamp=dict(type="float"), headers=dict(type="dict"), )) @@ -65,8 +65,8 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( - timestamp=params.get("timestamp"), mac_address=params.get("macAddress"), + timestamp=params.get("timestamp"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/client_health_info.py b/plugins/action/client_health_info.py index 87275b0360..1f8a652b1e 100644 --- a/plugins/action/client_health_info.py +++ b/plugins/action/client_health_info.py @@ -25,7 +25,7 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - timestamp=dict(type="str"), + timestamp=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/client_proximity_info.py b/plugins/action/client_proximity_info.py index b9a411856f..af505d52a9 100644 --- a/plugins/action/client_proximity_info.py +++ b/plugins/action/client_proximity_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( username=dict(type="str"), - number_days=dict(type="int"), - time_resolution=dict(type="int"), + number_days=dict(type="float"), + time_resolution=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/compliance_device_by_id_info.py b/plugins/action/compliance_device_by_id_info.py index e2c684bfc3..e9e9397eee 100644 --- a/plugins/action/compliance_device_by_id_info.py +++ b/plugins/action/compliance_device_by_id_info.py @@ -29,8 +29,6 @@ category=dict(type="str"), complianceType=dict(type="str"), diffList=dict(type="bool"), - key=dict(type="str"), - value=dict(type="str"), headers=dict(type="dict"), )) @@ -73,8 +71,6 @@ def get_object(self, params): category=params.get("category"), compliance_type=params.get("complianceType"), diff_list=params.get("diffList"), - key=params.get("key"), - value=params.get("value"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/compliance_device_details_info.py b/plugins/action/compliance_device_details_info.py index 4fedf1aab5..44fbabc271 100644 --- a/plugins/action/compliance_device_details_info.py +++ b/plugins/action/compliance_device_details_info.py @@ -28,8 +28,8 @@ complianceType=dict(type="str"), complianceStatus=dict(type="str"), deviceUuid=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/compliance_device_info.py b/plugins/action/compliance_device_info.py index 25d2db9cb9..553523dd26 100644 --- a/plugins/action/compliance_device_info.py +++ b/plugins/action/compliance_device_info.py @@ -27,8 +27,6 @@ argument_spec.update(dict( complianceStatus=dict(type="str"), deviceUuid=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), headers=dict(type="dict"), )) @@ -69,8 +67,6 @@ def get_object(self, params): new_object = dict( compliance_status=params.get("complianceStatus"), device_uuid=params.get("deviceUuid"), - offset=params.get("offset"), - limit=params.get("limit"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/configuration_template_deploy.py b/plugins/action/configuration_template_deploy.py index 55b033a763..48ccdcf3ad 100644 --- a/plugins/action/configuration_template_deploy.py +++ b/plugins/action/configuration_template_deploy.py @@ -28,7 +28,7 @@ forcePushTemplate=dict(type="bool"), isComposite=dict(type="bool"), mainTemplateId=dict(type="str"), - memberTemplateDeploymentInfo=dict(type="str"), + memberTemplateDeploymentInfo=dict(type="list"), targetInfo=dict(type="list"), templateId=dict(type="str"), )) diff --git a/plugins/action/configuration_template_deploy_v2.py b/plugins/action/configuration_template_deploy_v2.py index 802c84d98b..fe1ec9b760 100644 --- a/plugins/action/configuration_template_deploy_v2.py +++ b/plugins/action/configuration_template_deploy_v2.py @@ -28,7 +28,7 @@ forcePushTemplate=dict(type="bool"), isComposite=dict(type="bool"), mainTemplateId=dict(type="str"), - memberTemplateDeploymentInfo=dict(type="str"), + memberTemplateDeploymentInfo=dict(type="list"), targetInfo=dict(type="list"), templateId=dict(type="str"), )) diff --git a/plugins/action/configuration_template_project.py b/plugins/action/configuration_template_project.py index e6e356aa0b..65017e94d1 100644 --- a/plugins/action/configuration_template_project.py +++ b/plugins/action/configuration_template_project.py @@ -37,7 +37,7 @@ id=dict(type="str"), lastUpdateTime=dict(type="int"), name=dict(type="str"), - templates=dict(type="dict"), + templates=dict(type="list"), projectId=dict(type="str"), )) diff --git a/plugins/action/device_configurations_export.py b/plugins/action/device_configurations_export.py index 20c129b992..665bcbf41e 100644 --- a/plugins/action/device_configurations_export.py +++ b/plugins/action/device_configurations_export.py @@ -25,8 +25,8 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - deviceId=dict(type="list"), password=dict(type="str", no_log=True), + deviceId=dict(type="str"), )) required_if = [] @@ -64,8 +64,8 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( - deviceId=params.get("deviceId"), password=params.get("password"), + deviceId=params.get("deviceId"), ) return new_object diff --git a/plugins/action/device_details_info.py b/plugins/action/device_details_info.py index 7a743804c0..4c64f60f98 100644 --- a/plugins/action/device_details_info.py +++ b/plugins/action/device_details_info.py @@ -25,9 +25,9 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - timestamp=dict(type="str"), - searchBy=dict(type="str"), + timestamp=dict(type="float"), identifier=dict(type="str"), + searchBy=dict(type="str"), headers=dict(type="dict"), )) @@ -67,8 +67,8 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( timestamp=params.get("timestamp"), - search_by=params.get("searchBy"), identifier=params.get("identifier"), + search_by=params.get("searchBy"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/device_health_info.py b/plugins/action/device_health_info.py index 68bd65bfec..5bae85ad7c 100644 --- a/plugins/action/device_health_info.py +++ b/plugins/action/device_health_info.py @@ -28,10 +28,10 @@ deviceRole=dict(type="str"), siteId=dict(type="str"), health=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), - limit=dict(type="int"), - offset=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), + limit=dict(type="float"), + offset=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/device_reboot_apreboot.py b/plugins/action/device_reboot_apreboot.py new file mode 100644 index 0000000000..70a7b3e621 --- /dev/null +++ b/plugins/action/device_reboot_apreboot.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + apMacAddresses=dict(type="list"), +)) + +required_if = [ +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class DeviceRebootApreboot(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + apMacAddresses=params.get("apMacAddresses"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['parent_task_id'] = self.new_object.get('parentTaskId') or \ + self.new_object.get('parent_task_id') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['apMacAddresses'] = self.new_object.get('apMacAddresses') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method, using get all + try: + items = self.dnac.exec( + family="wireless", + function="get_access_point_reboot_task_result", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("apMacAddresses", "apMacAddresses"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="wireless", + function="reboot_access_points", + params=self.create_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = DeviceRebootApreboot(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + dnac.object_present_and_different() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/discovery_summary_info.py b/plugins/action/discovery_summary_info.py index 9b64187b2a..4e4b9741aa 100644 --- a/plugins/action/discovery_summary_info.py +++ b/plugins/action/discovery_summary_info.py @@ -80,7 +80,7 @@ def get_object(self, params): ip_address=params.get("ipAddress"), ping_status=params.get("pingStatus"), snmp_status=params.get("snmpStatus"), - cli_status=params.get("cliStatus"), + clistatus=params.get("cliStatus"), netconf_status=params.get("netconfStatus"), http_status=params.get("httpStatus"), headers=params.get("headers"), diff --git a/plugins/action/dna_event_snmp_config_info.py b/plugins/action/dna_event_snmp_config_info.py new file mode 100644 index 0000000000..19ad20c2dd --- /dev/null +++ b/plugins/action/dna_event_snmp_config_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + configId=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + sortBy=dict(type="str"), + order=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + config_id=params.get("configId"), + offset=params.get("offset"), + limit=params.get("limit"), + sort_by=params.get("sortBy"), + order=params.get("order"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="event_management", + function='get_snmp_destination', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/eox_status_device_info.py b/plugins/action/eox_status_device_info.py index 06ef71e8bd..40d675cce1 100644 --- a/plugins/action/eox_status_device_info.py +++ b/plugins/action/eox_status_device_info.py @@ -82,8 +82,8 @@ def run(self, tmp=None, task_vars=None): id = self._task.args.get("deviceId") if id: response = dnac.exec( - family="eo_x", - function='get_eo_x_details_per_device', + family="eox", + function='get_eox_details_per_device', params=self.get_object(self._task.args), ) self._result.update(dict(dnac_response=response)) @@ -91,8 +91,8 @@ def run(self, tmp=None, task_vars=None): return self._result if not id: response = dnac.exec( - family="eo_x", - function='get_eo_x_status_for_all_devices', + family="eox", + function='get_eox_status_for_all_devices', params=self.get_object(self._task.args), ) self._result.update(dict(dnac_response=response)) diff --git a/plugins/action/eox_status_summary_info.py b/plugins/action/eox_status_summary_info.py index 5b449d6623..db8934816d 100644 --- a/plugins/action/eox_status_summary_info.py +++ b/plugins/action/eox_status_summary_info.py @@ -78,8 +78,8 @@ def run(self, tmp=None, task_vars=None): dnac = DNACSDK(params=self._task.args) response = dnac.exec( - family="eo_x", - function='get_eo_x_summary', + family="eox", + function='get_eox_summary', params=self.get_object(self._task.args), ) self._result.update(dict(dnac_response=response)) diff --git a/plugins/action/event_artifact_info.py b/plugins/action/event_artifact_info.py index 4376fd4f0a..beef1e6a9b 100644 --- a/plugins/action/event_artifact_info.py +++ b/plugins/action/event_artifact_info.py @@ -27,8 +27,8 @@ argument_spec.update(dict( eventIds=dict(type="str"), tags=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), search=dict(type="str"), diff --git a/plugins/action/event_info.py b/plugins/action/event_info.py index d22c13f363..f7bcd07c79 100644 --- a/plugins/action/event_info.py +++ b/plugins/action/event_info.py @@ -27,8 +27,8 @@ argument_spec.update(dict( eventId=dict(type="str"), tags=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_series_audit_logs_info.py b/plugins/action/event_series_audit_logs_info.py index a2f85bacd7..6bd1bd2f39 100644 --- a/plugins/action/event_series_audit_logs_info.py +++ b/plugins/action/event_series_audit_logs_info.py @@ -41,10 +41,10 @@ deviceId=dict(type="str"), isSystemEvents=dict(type="bool"), description=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), - startTime=dict(type="int"), - endTime=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), + startTime=dict(type="float"), + endTime=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_series_audit_logs_parent_records_info.py b/plugins/action/event_series_audit_logs_parent_records_info.py index b9839c20fd..ffd36b1fea 100644 --- a/plugins/action/event_series_audit_logs_parent_records_info.py +++ b/plugins/action/event_series_audit_logs_parent_records_info.py @@ -40,10 +40,10 @@ deviceId=dict(type="str"), isSystemEvents=dict(type="bool"), description=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), - startTime=dict(type="int"), - endTime=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), + startTime=dict(type="float"), + endTime=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_series_audit_logs_summary_info.py b/plugins/action/event_series_audit_logs_summary_info.py index 42d15ac742..47e4576a18 100644 --- a/plugins/action/event_series_audit_logs_summary_info.py +++ b/plugins/action/event_series_audit_logs_summary_info.py @@ -42,8 +42,8 @@ deviceId=dict(type="str"), isSystemEvents=dict(type="bool"), description=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/event_series_count_info.py b/plugins/action/event_series_count_info.py index 8e6372c923..5951fd1196 100644 --- a/plugins/action/event_series_count_info.py +++ b/plugins/action/event_series_count_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( eventIds=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), category=dict(type="str"), type=dict(type="str"), severity=dict(type="str"), diff --git a/plugins/action/event_series_info.py b/plugins/action/event_series_info.py index 8722bc05a8..31d06b5bb4 100644 --- a/plugins/action/event_series_info.py +++ b/plugins/action/event_series_info.py @@ -26,16 +26,16 @@ # Add arguments specific for this module argument_spec.update(dict( eventIds=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), category=dict(type="str"), type=dict(type="str"), severity=dict(type="str"), domain=dict(type="str"), subDomain=dict(type="str"), source=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), tags=dict(type="str"), diff --git a/plugins/action/event_snmp_config.py b/plugins/action/event_snmp_config.py new file mode 100644 index 0000000000..8c0683ce8e --- /dev/null +++ b/plugins/action/event_snmp_config.py @@ -0,0 +1,239 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + name=dict(type="str"), + description=dict(type="str"), + ipAddress=dict(type="str"), + port=dict(type="str"), + snmpVersion=dict(type="str"), + community=dict(type="str"), + userName=dict(type="str"), + snmpMode=dict(type="str"), + snmpAuthType=dict(type="str"), + authPassword=dict(type="str", no_log=True), + snmpPrivacyType=dict(type="str"), + privacyPassword=dict(type="str", no_log=True), + configId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["name"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class EventSnmpConfig(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + name=params.get("name"), + description=params.get("description"), + ipAddress=params.get("ipAddress"), + port=params.get("port"), + snmpVersion=params.get("snmpVersion"), + community=params.get("community"), + userName=params.get("userName"), + snmpMode=params.get("snmpMode"), + snmpAuthType=params.get("snmpAuthType"), + authPassword=params.get("authPassword"), + snmpPrivacyType=params.get("snmpPrivacyType"), + privacyPassword=params.get("privacyPassword"), + configId=params.get("configId"), + ) + + def create_params(self): + new_object_params = {} + new_object_params['name'] = self.new_object.get('name') + new_object_params['description'] = self.new_object.get('description') + new_object_params['ipAddress'] = self.new_object.get('ipAddress') + new_object_params['port'] = self.new_object.get('port') + new_object_params['snmpVersion'] = self.new_object.get('snmpVersion') + new_object_params['community'] = self.new_object.get('community') + new_object_params['userName'] = self.new_object.get('userName') + new_object_params['snmpMode'] = self.new_object.get('snmpMode') + new_object_params['snmpAuthType'] = self.new_object.get('snmpAuthType') + new_object_params['authPassword'] = self.new_object.get('authPassword') + new_object_params['snmpPrivacyType'] = self.new_object.get('snmpPrivacyType') + new_object_params['privacyPassword'] = self.new_object.get('privacyPassword') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['configId'] = self.new_object.get('configId') + new_object_params['name'] = self.new_object.get('name') + new_object_params['description'] = self.new_object.get('description') + new_object_params['ipAddress'] = self.new_object.get('ipAddress') + new_object_params['port'] = self.new_object.get('port') + new_object_params['snmpVersion'] = self.new_object.get('snmpVersion') + new_object_params['community'] = self.new_object.get('community') + new_object_params['userName'] = self.new_object.get('userName') + new_object_params['snmpMode'] = self.new_object.get('snmpMode') + new_object_params['snmpAuthType'] = self.new_object.get('snmpAuthType') + new_object_params['authPassword'] = self.new_object.get('authPassword') + new_object_params['snmpPrivacyType'] = self.new_object.get('snmpPrivacyType') + new_object_params['privacyPassword'] = self.new_object.get('privacyPassword') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name and get all + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("name", "name"), + ("description", "description"), + ("ipAddress", "ipAddress"), + ("port", "port"), + ("snmpVersion", "snmpVersion"), + ("community", "community"), + ("userName", "userName"), + ("snmpMode", "snmpMode"), + ("snmpAuthType", "snmpAuthType"), + ("authPassword", "authPassword"), + ("snmpPrivacyType", "snmpPrivacyType"), + ("privacyPassword", "privacyPassword"), + ("configId", "configId"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="event_management", + function="create_snmp_destination", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + result = self.dnac.exec( + family="event_management", + function="update_snmp_destination", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = EventSnmpConfig(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/event_subscription.py b/plugins/action/event_subscription.py index 52db4e8ad2..bb444e268c 100644 --- a/plugins/action/event_subscription.py +++ b/plugins/action/event_subscription.py @@ -37,6 +37,7 @@ required_if = [ ("state", "present", ["payload"], True), + ("state", "absent", ["payload"], True), ] required_one_of = [] mutually_exclusive = [] @@ -183,8 +184,11 @@ def update(self): return result def delete(self): - id = self.new_object.get("id") - name = self.new_object.get("name") + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") result = None result = self.dnac.exec( family="event_management", diff --git a/plugins/action/event_subscription_details_email_info.py b/plugins/action/event_subscription_details_email_info.py index 2ece6f956b..9681e5362a 100644 --- a/plugins/action/event_subscription_details_email_info.py +++ b/plugins/action/event_subscription_details_email_info.py @@ -27,8 +27,8 @@ argument_spec.update(dict( name=dict(type="str"), instanceId=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_subscription_details_rest_info.py b/plugins/action/event_subscription_details_rest_info.py index 9c73213176..147aaaa8d4 100644 --- a/plugins/action/event_subscription_details_rest_info.py +++ b/plugins/action/event_subscription_details_rest_info.py @@ -27,8 +27,8 @@ argument_spec.update(dict( name=dict(type="str"), instanceId=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_subscription_details_syslog_info.py b/plugins/action/event_subscription_details_syslog_info.py index fbec9c6ad7..27b88b23d7 100644 --- a/plugins/action/event_subscription_details_syslog_info.py +++ b/plugins/action/event_subscription_details_syslog_info.py @@ -27,8 +27,8 @@ argument_spec.update(dict( name=dict(type="str"), instanceId=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_subscription_email_info.py b/plugins/action/event_subscription_email_info.py index 9e5f52866e..93b4762e22 100644 --- a/plugins/action/event_subscription_email_info.py +++ b/plugins/action/event_subscription_email_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( eventIds=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), domain=dict(type="str"), diff --git a/plugins/action/event_subscription_info.py b/plugins/action/event_subscription_info.py index c5dc8d6f6c..7470087206 100644 --- a/plugins/action/event_subscription_info.py +++ b/plugins/action/event_subscription_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( eventIds=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_subscription_rest_info.py b/plugins/action/event_subscription_rest_info.py index 0466392604..f8c69c1683 100644 --- a/plugins/action/event_subscription_rest_info.py +++ b/plugins/action/event_subscription_rest_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( eventIds=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), domain=dict(type="str"), diff --git a/plugins/action/event_subscription_syslog_info.py b/plugins/action/event_subscription_syslog_info.py index d79db09534..c8338dffb4 100644 --- a/plugins/action/event_subscription_syslog_info.py +++ b/plugins/action/event_subscription_syslog_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( eventIds=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), domain=dict(type="str"), diff --git a/plugins/action/event_syslog_config.py b/plugins/action/event_syslog_config.py index e4aae36bbe..366d56718e 100644 --- a/plugins/action/event_syslog_config.py +++ b/plugins/action/event_syslog_config.py @@ -36,7 +36,7 @@ description=dict(type="str"), host=dict(type="str"), protocol=dict(type="str"), - port=dict(type="str"), + port=dict(type="int"), )) required_if = [ diff --git a/plugins/action/event_syslog_config_info.py b/plugins/action/event_syslog_config_info.py index bcef02393f..02c304e9bf 100644 --- a/plugins/action/event_syslog_config_info.py +++ b/plugins/action/event_syslog_config_info.py @@ -28,8 +28,8 @@ configId=dict(type="str"), name=dict(type="str"), protocol=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), sortBy=dict(type="str"), order=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/event_webhook_create.py b/plugins/action/event_webhook_create.py index de2b925147..ddbadcae42 100644 --- a/plugins/action/event_webhook_create.py +++ b/plugins/action/event_webhook_create.py @@ -32,6 +32,7 @@ method=dict(type="str"), trustCert=dict(type="bool"), headers=dict(type="list"), + isProxyRoute=dict(type="bool"), )) required_if = [] @@ -76,6 +77,7 @@ def get_object(self, params): method=params.get("method"), trustCert=params.get("trustCert"), headers=params.get("headers"), + isProxyRoute=params.get("isProxyRoute"), ) return new_object diff --git a/plugins/action/event_webhook_read_info.py b/plugins/action/event_webhook_read_info.py new file mode 100644 index 0000000000..9bb609a072 --- /dev/null +++ b/plugins/action/event_webhook_read_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + webhookIds=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + sortBy=dict(type="str"), + order=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + webhook_ids=params.get("webhookIds"), + offset=params.get("offset"), + limit=params.get("limit"), + sort_by=params.get("sortBy"), + order=params.get("order"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="event_management", + function='get_webhook_destination', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/event_webhook_update.py b/plugins/action/event_webhook_update.py index d11bc98a04..772b5e263a 100644 --- a/plugins/action/event_webhook_update.py +++ b/plugins/action/event_webhook_update.py @@ -32,6 +32,7 @@ method=dict(type="str"), trustCert=dict(type="bool"), headers=dict(type="list"), + isProxyRoute=dict(type="bool"), )) required_if = [] @@ -76,6 +77,7 @@ def get_object(self, params): method=params.get("method"), trustCert=params.get("trustCert"), headers=params.get("headers"), + isProxyRoute=params.get("isProxyRoute"), ) return new_object diff --git a/plugins/action/flexible_report_content_info.py b/plugins/action/flexible_report_content_info.py new file mode 100644 index 0000000000..ec95a02b73 --- /dev/null +++ b/plugins/action/flexible_report_content_info.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + reportId=dict(type="str"), + executionId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + report_id=params.get("reportId"), + execution_id=params.get("executionId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + id = self._task.args.get("reportId") + if id: + response = dnac.exec( + family="reports", + function='download_flexible_report', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result + if not id: + # NOTE: Does not have a get all method or it is in another action + response = None + dnac.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/flexible_report_execute.py b/plugins/action/flexible_report_execute.py new file mode 100644 index 0000000000..b2c481e10e --- /dev/null +++ b/plugins/action/flexible_report_execute.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + reportId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + report_id=params.get("reportId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="reports", + function='executing_the_flexible_report', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/flexible_report_executions_info.py b/plugins/action/flexible_report_executions_info.py new file mode 100644 index 0000000000..7340ddcd9d --- /dev/null +++ b/plugins/action/flexible_report_executions_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + reportId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + report_id=params.get("reportId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="reports", + function='get_execution_id_by_report_id', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/flexible_report_schedule.py b/plugins/action/flexible_report_schedule.py new file mode 100644 index 0000000000..f328936ebf --- /dev/null +++ b/plugins/action/flexible_report_schedule.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + schedule=dict(type="dict"), + reportId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["reportId"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class FlexibleReportSchedule(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + schedule=params.get("schedule"), + report_id=params.get("reportId"), + ) + + def update_by_id_params(self): + new_object_params = {} + new_object_params['schedule'] = self.new_object.get('schedule') + new_object_params['reportId'] = self.new_object.get('reportId') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name and get all + return result + + def get_object_by_id(self, id): + result = None + try: + items = self.dnac.exec( + family="reports", + function="get_flexible_report_schedule_by_report_id", + params={"report_id": id} + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'report_id', id) + except Exception: + result = None + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("id") + o_id = o_id or self.new_object.get("report_id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + _id = _id or prev_obj.get("reportId") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + self.new_object.update(dict(report_id=_id)) + if _id: + prev_obj = self.get_object_by_id(_id) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("schedule", "schedule"), + ("reportId", "report_id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def update(self): + id = self.new_object.get("id") + id = id or self.new_object.get("report_id") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + id_ = id_ or prev_obj_name.get("reportId") + if id_: + self.new_object.update(dict(report_id=id_)) + result = self.dnac.exec( + family="reports", + function="update_schedule_of_flexible_report", + params=self.update_by_id_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = FlexibleReportSchedule(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + dnac.fail_json("Object does not exists, plugin only has update") + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/flexible_report_schedule_info.py b/plugins/action/flexible_report_schedule_info.py new file mode 100644 index 0000000000..cf11f213cb --- /dev/null +++ b/plugins/action/flexible_report_schedule_info.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + reportId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + report_id=params.get("reportId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + id = self._task.args.get("reportId") + if id: + response = dnac.exec( + family="reports", + function='get_flexible_report_schedule_by_report_id', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result + if not id: + # NOTE: Does not have a get all method or it is in another action + response = None + dnac.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/flexible_report_schedules_info.py b/plugins/action/flexible_report_schedules_info.py new file mode 100644 index 0000000000..15565a03ac --- /dev/null +++ b/plugins/action/flexible_report_schedules_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="reports", + function='get_all_flexible_report_schedules', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/global_pool_info.py b/plugins/action/global_pool_info.py index 56c0161a08..3045942814 100644 --- a/plugins/action/global_pool_info.py +++ b/plugins/action/global_pool_info.py @@ -25,8 +25,8 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/http_read_credential.py b/plugins/action/http_read_credential.py index c73050be86..1d1ac0acd2 100644 --- a/plugins/action/http_read_credential.py +++ b/plugins/action/http_read_credential.py @@ -130,7 +130,7 @@ def exists(self): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("username") or self.new_object.get("description") + name = self.new_object.get("description") or self.new_object.get("username") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) diff --git a/plugins/action/http_write_credential.py b/plugins/action/http_write_credential.py index 7ae396a1b7..5a63c0d5e5 100644 --- a/plugins/action/http_write_credential.py +++ b/plugins/action/http_write_credential.py @@ -130,7 +130,7 @@ def exists(self): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("username") or self.new_object.get("description") + name = self.new_object.get("description") or self.new_object.get("username") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) diff --git a/plugins/action/integration_settings_instances_itsm.py b/plugins/action/integration_settings_instances_itsm.py index 1b12af772f..0575dc457d 100644 --- a/plugins/action/integration_settings_instances_itsm.py +++ b/plugins/action/integration_settings_instances_itsm.py @@ -77,6 +77,7 @@ def update_by_id_params(self): new_object_params['description'] = self.new_object.get('description') new_object_params['data'] = self.new_object.get('data') new_object_params['dypName'] = self.new_object.get('dypName') + new_object_params['instanceId'] = self.new_object.get('instanceId') return new_object_params def get_object_by_name(self, name): diff --git a/plugins/action/integration_settings_itsm_instances_info.py b/plugins/action/integration_settings_itsm_instances_info.py new file mode 100644 index 0000000000..f8360f9c79 --- /dev/null +++ b/plugins/action/integration_settings_itsm_instances_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="itsm_integration", + function='get_all_itsm_integration_settings', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/integration_settings_status_info.py b/plugins/action/integration_settings_status_info.py new file mode 100644 index 0000000000..2673531b9e --- /dev/null +++ b/plugins/action/integration_settings_status_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="itsm_integration", + function='get_itsm_integration_status', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/ise_integration_status_info.py b/plugins/action/ise_integration_status_info.py new file mode 100644 index 0000000000..40bb9e2f79 --- /dev/null +++ b/plugins/action/ise_integration_status_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="system_settings", + function='cisco_ise_server_integration_status', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/issues_info.py b/plugins/action/issues_info.py index ab158f9e7e..288681100d 100644 --- a/plugins/action/issues_info.py +++ b/plugins/action/issues_info.py @@ -25,14 +25,14 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), siteId=dict(type="str"), deviceId=dict(type="str"), macAddress=dict(type="str"), priority=dict(type="str"), - aiDriven=dict(type="str"), issueStatus=dict(type="str"), + aiDriven=dict(type="str"), headers=dict(type="dict"), )) @@ -77,8 +77,8 @@ def get_object(self, params): device_id=params.get("deviceId"), mac_address=params.get("macAddress"), priority=params.get("priority"), - ai_driven=params.get("aiDriven"), issue_status=params.get("issueStatus"), + ai_driven=params.get("aiDriven"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/lan_automation_log_info.py b/plugins/action/lan_automation_log_info.py index dfa702581c..dc9caf604f 100644 --- a/plugins/action/lan_automation_log_info.py +++ b/plugins/action/lan_automation_log_info.py @@ -25,8 +25,8 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), id=dict(type="str"), headers=dict(type="dict"), )) diff --git a/plugins/action/lan_automation_sessions_info.py b/plugins/action/lan_automation_sessions_info.py new file mode 100644 index 0000000000..5a9a7119d4 --- /dev/null +++ b/plugins/action/lan_automation_sessions_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="lan_automation", + function='lan_automation_active_sessions', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/lan_automation_status_info.py b/plugins/action/lan_automation_status_info.py index 073cfb275f..e380bd5fbc 100644 --- a/plugins/action/lan_automation_status_info.py +++ b/plugins/action/lan_automation_status_info.py @@ -25,8 +25,8 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), id=dict(type="str"), headers=dict(type="dict"), )) diff --git a/plugins/action/lan_automation_update.py b/plugins/action/lan_automation_update.py new file mode 100644 index 0000000000..0a30414e1e --- /dev/null +++ b/plugins/action/lan_automation_update.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="lan_automation", + function='lan_automation_stop_and_update_devices', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/lan_automation_update_device.py b/plugins/action/lan_automation_update_device.py new file mode 100644 index 0000000000..30ec6ef880 --- /dev/null +++ b/plugins/action/lan_automation_update_device.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + loopbackUpdateDeviceList=dict(type="list"), + linkUpdate=dict(type="dict"), + hostnameUpdateDevices=dict(type="list"), + feature=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + loopbackUpdateDeviceList=params.get("loopbackUpdateDeviceList"), + linkUpdate=params.get("linkUpdate"), + hostnameUpdateDevices=params.get("hostnameUpdateDevices"), + feature=params.get("feature"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="lan_automation", + function='lan_automation_device_update', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/lan_automation_update_v2.py b/plugins/action/lan_automation_update_v2.py new file mode 100644 index 0000000000..acd4c98120 --- /dev/null +++ b/plugins/action/lan_automation_update_v2.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="lan_automation", + function='lan_automation_stop_and_update_devices_v2', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/lan_automation_v2.py b/plugins/action/lan_automation_v2.py new file mode 100644 index 0000000000..2c538a873b --- /dev/null +++ b/plugins/action/lan_automation_v2.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + payload=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + payload=params.get("payload"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="lan_automation", + function='lan_automation_start_v2', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/license_device_license_summary_info.py b/plugins/action/license_device_license_summary_info.py index af82708cae..03544a2bf2 100644 --- a/plugins/action/license_device_license_summary_info.py +++ b/plugins/action/license_device_license_summary_info.py @@ -25,15 +25,15 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - page_number=dict(type="int"), + page_number=dict(type="float"), order=dict(type="str"), sort_by=dict(type="str"), dna_level=dict(type="str"), device_type=dict(type="str"), - limit=dict(type="int"), + limit=dict(type="float"), registration_status=dict(type="str"), virtual_account_name=dict(type="str"), - smart_account_id=dict(type="int"), + smart_account_id=dict(type="str"), device_uuid=dict(type="str"), headers=dict(type="dict"), )) diff --git a/plugins/action/maps_export.py b/plugins/action/maps_export.py new file mode 100644 index 0000000000..108cfd5031 --- /dev/null +++ b/plugins/action/maps_export.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + siteHierarchyUuid=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + site_hierarchy_uuid=params.get("siteHierarchyUuid"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='export_map_archive', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/maps_import.py b/plugins/action/maps_import.py new file mode 100644 index 0000000000..de9e4dc2c2 --- /dev/null +++ b/plugins/action/maps_import.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + importContextUuid=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + import_context_uuid=params.get("importContextUuid"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function="import_map_archive_cancel_an_import", + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/maps_import_perform.py b/plugins/action/maps_import_perform.py new file mode 100644 index 0000000000..e6ab782a08 --- /dev/null +++ b/plugins/action/maps_import_perform.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + importContextUuid=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + import_context_uuid=params.get("importContextUuid"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='import_map_archive_perform_import', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/maps_import_start.py b/plugins/action/maps_import_start.py new file mode 100644 index 0000000000..5bc2a1c6c8 --- /dev/null +++ b/plugins/action/maps_import_start.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='import_map_archive_start_import', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/maps_import_status_info.py b/plugins/action/maps_import_status_info.py new file mode 100644 index 0000000000..bfb88e7d3d --- /dev/null +++ b/plugins/action/maps_import_status_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + importContextUuid=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + import_context_uuid=params.get("importContextUuid"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='import_map_archive_import_status', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/maps_supported_access_points_info.py b/plugins/action/maps_supported_access_points_info.py new file mode 100644 index 0000000000..d4d9913876 --- /dev/null +++ b/plugins/action/maps_supported_access_points_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='maps_supported_access_points', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/netconf_credential.py b/plugins/action/netconf_credential.py index 5ea30373d9..4312a58343 100644 --- a/plugins/action/netconf_credential.py +++ b/plugins/action/netconf_credential.py @@ -95,7 +95,7 @@ def get_object_by_name(self, name): if isinstance(items, dict): if 'response' in items: items = items.get('response') - result = get_dict_result(items, 'description', name) + result = get_dict_result(items, 'description', name) or get_dict_result(items, 'username', name) except Exception: result = None return result @@ -121,7 +121,7 @@ def exists(self): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("username") or self.new_object.get("description") + name = self.new_object.get("description") or self.new_object.get("username") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) diff --git a/plugins/action/network_device.py b/plugins/action/network_device.py index 650f0cc827..38a99c6b13 100644 --- a/plugins/action/network_device.py +++ b/plugins/action/network_device.py @@ -56,9 +56,9 @@ snmpUserName=dict(type="str"), snmpVersion=dict(type="str"), type=dict(type="str"), - updateMgmtIPaddressList=dict(type="list"), userName=dict(type="str"), id=dict(type="str"), + updateMgmtIPaddressList=dict(type="list"), cleanConfig=dict(type="bool"), )) @@ -100,9 +100,9 @@ def __init__(self, params, dnac): snmpUserName=params.get("snmpUserName"), snmpVersion=params.get("snmpVersion"), type=params.get("type"), - updateMgmtIPaddressList=params.get("updateMgmtIPaddressList"), userName=params.get("userName"), id=params.get("id"), + updateMgmtIPaddressList=params.get("updateMgmtIPaddressList"), clean_config=params.get("cleanConfig"), managementIpAddress=params.get("managementIpAddress"), ) @@ -188,7 +188,6 @@ def create_params(self): new_object_params['snmpUserName'] = self.new_object.get('snmpUserName') new_object_params['snmpVersion'] = self.new_object.get('snmpVersion') new_object_params['type'] = self.new_object.get('type') - new_object_params['updateMgmtIPaddressList'] = self.new_object.get('updateMgmtIPaddressList') new_object_params['userName'] = self.new_object.get('userName') return new_object_params @@ -316,9 +315,9 @@ def requires_update(self, current_obj): ("snmpUserName", "snmpUserName"), ("snmpVersion", "snmpVersion"), ("type", "type"), - ("updateMgmtIPaddressList", "updateMgmtIPaddressList"), ("userName", "userName"), ("id", "id"), + ("updateMgmtIPaddressList", "updateMgmtIPaddressList"), ("cleanConfig", "clean_config"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params diff --git a/plugins/action/network_device_config__info.py b/plugins/action/network_device_config__info.py new file mode 100644 index 0000000000..52a1b32534 --- /dev/null +++ b/plugins/action/network_device_config__info.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + deviceId=dict(type="str"), + fileType=dict(type="str"), + createdTime=dict(type="str"), + createdBy=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + device_id=params.get("deviceId"), + file_type=params.get("fileType"), + created_time=params.get("createdTime"), + created_by=params.get("createdBy"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="configuration_archive", + function='get_configuration_archive_details', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_device_config_task_info.py b/plugins/action/network_device_config_task_info.py new file mode 100644 index 0000000000..d9231ba352 --- /dev/null +++ b/plugins/action/network_device_config_task_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + parentTaskId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + parent_task_id=params.get("parentTaskId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="configuration_archive", + function='get_config_task_details', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_device_config_write_memory.py b/plugins/action/network_device_config_write_memory.py new file mode 100644 index 0000000000..1f145f04f4 --- /dev/null +++ b/plugins/action/network_device_config_write_memory.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + deviceId=dict(type="list"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + deviceId=params.get("deviceId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="configuration_archive", + function='commit_device_configuration', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_device_count_info.py b/plugins/action/network_device_count_info.py index b2e2ad364e..79424c86a8 100644 --- a/plugins/action/network_device_count_info.py +++ b/plugins/action/network_device_count_info.py @@ -26,6 +26,10 @@ # Add arguments specific for this module argument_spec.update(dict( deviceId=dict(type="str"), + hostname=dict(type="list"), + managementIpAddress=dict(type="list"), + macAddress=dict(type="list"), + locationName=dict(type="list"), headers=dict(type="dict"), )) @@ -65,6 +69,10 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( device_id=params.get("deviceId"), + hostname=params.get("hostname"), + management_ip_address=params.get("managementIpAddress"), + mac_address=params.get("macAddress"), + location_name=params.get("locationName"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/network_device_equipment_info.py b/plugins/action/network_device_equipment_info.py index 2365b8a116..96235401fd 100644 --- a/plugins/action/network_device_equipment_info.py +++ b/plugins/action/network_device_equipment_info.py @@ -83,7 +83,7 @@ def run(self, tmp=None, task_vars=None): response = dnac.exec( family="devices", - function='return_power_supply_fan_details_for_the_given_device', + function='get_the_details_of_physical_components_of_the_given_device', params=self.get_object(self._task.args), ) self._result.update(dict(dnac_response=response)) diff --git a/plugins/action/network_device_export.py b/plugins/action/network_device_export.py index ed7447eec7..d130203a2d 100644 --- a/plugins/action/network_device_export.py +++ b/plugins/action/network_device_export.py @@ -26,7 +26,6 @@ # Add arguments specific for this module argument_spec.update(dict( deviceUuids=dict(type="list"), - id=dict(type="str"), operationEnum=dict(type="str"), parameters=dict(type="list"), password=dict(type="str", no_log=True), @@ -68,7 +67,6 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( deviceUuids=params.get("deviceUuids"), - id=params.get("id"), operationEnum=params.get("operationEnum"), parameters=params.get("parameters"), password=params.get("password"), diff --git a/plugins/action/network_device_insight_device_link_info.py b/plugins/action/network_device_insight_device_link_info.py new file mode 100644 index 0000000000..63cdcd94bd --- /dev/null +++ b/plugins/action/network_device_insight_device_link_info.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + siteId=dict(type="str"), + offset=dict(type="int"), + limit=dict(type="int"), + category=dict(type="str"), + sortBy=dict(type="str"), + order=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + site_id=params.get("siteId"), + offset=params.get("offset"), + limit=params.get("limit"), + category=params.get("category"), + sort_by=params.get("sortBy"), + order=params.get("order"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="devices", + function='inventory_insight_device_link_mismatch', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_device_ip_address_info.py b/plugins/action/network_device_ip_address_info.py new file mode 100644 index 0000000000..a766c17dc3 --- /dev/null +++ b/plugins/action/network_device_ip_address_info.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + ipAddress=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + ip_address=params.get("ipAddress"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + id = self._task.args.get("ipAddress") + if id: + response = dnac.exec( + family="devices", + function='get_network_device_by_ip', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result + if not id: + # NOTE: Does not have a get all method or it is in another action + response = None + dnac.object_modify_result(changed=False, result="Module does not have get all, check arguments of module") + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_device_management_address_update.py b/plugins/action/network_device_management_address_update.py new file mode 100644 index 0000000000..ab9d7c6704 --- /dev/null +++ b/plugins/action/network_device_management_address_update.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + newIP=dict(type="str"), + deviceid=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + newIP=params.get("newIP"), + deviceid=params.get("deviceid"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="devices", + function='update_device_management_address', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_device_user_defined_field.py b/plugins/action/network_device_user_defined_field.py index 724221ee90..9f1c83f14c 100644 --- a/plugins/action/network_device_user_defined_field.py +++ b/plugins/action/network_device_user_defined_field.py @@ -75,6 +75,7 @@ def update_by_id_params(self): new_object_params = {} new_object_params['name'] = self.new_object.get('name') new_object_params['description'] = self.new_object.get('description') + new_object_params['id'] = self.new_object.get('id') return new_object_params def get_object_by_name(self, name): diff --git a/plugins/action/network_device_user_defined_field_delete.py b/plugins/action/network_device_user_defined_field_delete.py new file mode 100644 index 0000000000..b1ac8e643f --- /dev/null +++ b/plugins/action/network_device_user_defined_field_delete.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + name=dict(type="str"), + deviceId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + name=params.get("name"), + device_id=params.get("deviceId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="devices", + function="remove_user_defined_field_from_device", + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_device_user_defined_field_update.py b/plugins/action/network_device_user_defined_field_update.py new file mode 100644 index 0000000000..81ffddaaf8 --- /dev/null +++ b/plugins/action/network_device_user_defined_field_update.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + payload=dict(type="list"), + deviceId=dict(type="str"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + payload=params.get("payload"), + device_id=params.get("deviceId"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="devices", + function='add_user_defined_field_to_device', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/network_v2.py b/plugins/action/network_v2.py index c1d4d0c1c2..f9087cbf00 100644 --- a/plugins/action/network_v2.py +++ b/plugins/action/network_v2.py @@ -60,11 +60,13 @@ def get_all_params(self, name=None, id=None): def create_params(self): new_object_params = {} new_object_params['settings'] = self.new_object.get('settings') + new_object_params['siteId'] = self.new_object.get('siteId') return new_object_params def update_by_id_params(self): new_object_params = {} new_object_params['settings'] = self.new_object.get('settings') + new_object_params['siteId'] = self.new_object.get('siteId') return new_object_params def get_object_by_name(self, name): diff --git a/plugins/action/path_trace.py b/plugins/action/path_trace.py index 133122616a..d494172555 100644 --- a/plugins/action/path_trace.py +++ b/plugins/action/path_trace.py @@ -117,7 +117,7 @@ def get_object_by_name(self, name): try: items = self.dnac.exec( family="path_trace", - function="retrives_all_previous_pathtraces_summary", + function="retrieves_all_previous_pathtraces_summary", params=self.get_all_params(name=name), ) if isinstance(items, dict): diff --git a/plugins/action/path_trace_info.py b/plugins/action/path_trace_info.py index be9d0dbc26..079046eeb4 100644 --- a/plugins/action/path_trace_info.py +++ b/plugins/action/path_trace_info.py @@ -28,16 +28,16 @@ periodicRefresh=dict(type="bool"), sourceIP=dict(type="str"), destIP=dict(type="str"), - sourcePort=dict(type="str"), - destPort=dict(type="str"), - gtCreateTime=dict(type="str"), - ltCreateTime=dict(type="str"), + sourcePort=dict(type="float"), + destPort=dict(type="float"), + gtCreateTime=dict(type="float"), + ltCreateTime=dict(type="float"), protocol=dict(type="str"), status=dict(type="str"), taskId=dict(type="str"), - lastUpdateTime=dict(type="str"), - limit=dict(type="int"), - offset=dict(type="int"), + lastUpdateTime=dict(type="float"), + limit=dict(type="float"), + offset=dict(type="float"), order=dict(type="str"), sortBy=dict(type="str"), flowAnalysisId=dict(type="str"), @@ -122,7 +122,7 @@ def run(self, tmp=None, task_vars=None): if not id: response = dnac.exec( family="path_trace", - function='retrives_all_previous_pathtraces_summary', + function='retrieves_all_previous_pathtraces_summary', params=self.get_object(self._task.args), ) self._result.update(dict(dnac_response=response)) diff --git a/plugins/action/planned_access_points.py b/plugins/action/planned_access_points.py new file mode 100644 index 0000000000..180b2fea3b --- /dev/null +++ b/plugins/action/planned_access_points.py @@ -0,0 +1,286 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + attributes=dict(type="dict"), + isSensor=dict(type="bool"), + location=dict(type="dict"), + position=dict(type="dict"), + radioCount=dict(type="int"), + radios=dict(type="list"), + floorId=dict(type="str"), + plannedAccessPointUuid=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["floorId", "plannedAccessPointUuid"], True), + ("state", "absent", ["floorId", "plannedAccessPointUuid"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class PlannedAccessPoints(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + attributes=params.get("attributes"), + isSensor=params.get("isSensor"), + location=params.get("location"), + position=params.get("position"), + radioCount=params.get("radioCount"), + radios=params.get("radios"), + floor_id=params.get("floorId"), + planned_access_point_uuid=params.get("plannedAccessPointUuid"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['limit'] = self.new_object.get('limit') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['radios'] = self.new_object.get('radios') + new_object_params['floor_id'] = self.new_object.get('floorId') or \ + self.new_object.get('floor_id') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['attributes'] = self.new_object.get('attributes') + new_object_params['isSensor'] = self.new_object.get('isSensor') + new_object_params['location'] = self.new_object.get('location') + new_object_params['position'] = self.new_object.get('position') + new_object_params['radioCount'] = self.new_object.get('radioCount') + new_object_params['radios'] = self.new_object.get('radios') + new_object_params['floorId'] = self.new_object.get('floorId') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['floor_id'] = self.new_object.get('floor_id') + new_object_params['planned_access_point_uuid'] = self.new_object.get('planned_access_point_uuid') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['attributes'] = self.new_object.get('attributes') + new_object_params['isSensor'] = self.new_object.get('isSensor') + new_object_params['location'] = self.new_object.get('location') + new_object_params['position'] = self.new_object.get('position') + new_object_params['radioCount'] = self.new_object.get('radioCount') + new_object_params['radios'] = self.new_object.get('radios') + new_object_params['floorId'] = self.new_object.get('floorId') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="devices", + function="get_planned_access_points_for_floor", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="devices", + function="get_planned_access_points_for_floor", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self): + id_exists = False + name_exists = False + prev_obj = None + o_id = self.new_object.get("id") + o_id = o_id or self.new_object.get("planned_access_point_uuid") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + _id = _id or prev_obj.get("plannedAccessPointUuid") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + self.new_object.update(dict(planned_access_point_uuid=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("attributes", "attributes"), + ("isSensor", "isSensor"), + ("location", "location"), + ("position", "position"), + ("radioCount", "radioCount"), + ("radios", "radios"), + ("floorId", "floor_id"), + ("plannedAccessPointUuid", "planned_access_point_uuid"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="devices", + function="create_planned_access_point_for_floor", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + result = self.dnac.exec( + family="devices", + function="update_planned_access_point_for_floor", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + id = self.new_object.get("id") + id = id or self.new_object.get("planned_access_point_uuid") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + id_ = id_ or prev_obj_name.get("plannedAccessPointUuid") + if id_: + self.new_object.update(dict(planned_access_point_uuid=id_)) + result = self.dnac.exec( + family="devices", + function="delete_planned_access_point_for_floor", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = PlannedAccessPoints(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/planned_access_points_info.py b/plugins/action/planned_access_points_info.py index 86cd1a87b4..328bd1c63a 100644 --- a/plugins/action/planned_access_points_info.py +++ b/plugins/action/planned_access_points_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( floorId=dict(type="str"), - limit=dict(type="int"), - offset=dict(type="int"), + limit=dict(type="float"), + offset=dict(type="float"), radios=dict(type="bool"), headers=dict(type="dict"), )) diff --git a/plugins/action/pnp_device.py b/plugins/action/pnp_device.py index ec9c0f36ae..5acf0f3c7c 100644 --- a/plugins/action/pnp_device.py +++ b/plugins/action/pnp_device.py @@ -31,15 +31,7 @@ # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - _id=dict(type="str"), deviceInfo=dict(type="dict"), - runSummaryList=dict(type="list"), - systemResetWorkflow=dict(type="dict"), - systemWorkflow=dict(type="dict"), - tenantId=dict(type="str"), - version=dict(type="int"), - workflow=dict(type="dict"), - workflowParameters=dict(type="dict"), id=dict(type="str"), )) @@ -56,15 +48,7 @@ class PnpDevice(object): def __init__(self, params, dnac): self.dnac = dnac self.new_object = dict( - _id=params.get("_id"), deviceInfo=params.get("deviceInfo"), - runSummaryList=params.get("runSummaryList"), - systemResetWorkflow=params.get("systemResetWorkflow"), - systemWorkflow=params.get("systemWorkflow"), - tenantId=params.get("tenantId"), - version=params.get("version"), - workflow=params.get("workflow"), - workflowParameters=params.get("workflowParameters"), id=params.get("id"), ) @@ -81,17 +65,11 @@ def get_all_params(self, name=None, id=None): self.new_object.get('state') new_object_params['onb_state'] = self.new_object.get('onbState') or \ self.new_object.get('onb_state') - new_object_params['cm_state'] = self.new_object.get('cmState') or \ - self.new_object.get('cm_state') new_object_params['name'] = name or self.new_object.get('name') new_object_params['pid'] = self.new_object.get('pid') new_object_params['source'] = self.new_object.get('source') - new_object_params['project_id'] = self.new_object.get('projectId') or \ - self.new_object.get('project_id') new_object_params['workflow_id'] = self.new_object.get('workflowId') or \ self.new_object.get('workflow_id') - new_object_params['project_name'] = self.new_object.get('projectName') or \ - self.new_object.get('project_name') new_object_params['workflow_name'] = self.new_object.get('workflowName') or \ self.new_object.get('workflow_name') new_object_params['smart_account_id'] = self.new_object.get('smartAccountId') or \ @@ -109,15 +87,7 @@ def get_all_params(self, name=None, id=None): def create_params(self): new_object_params = {} - new_object_params['_id'] = self.new_object.get('_id') new_object_params['deviceInfo'] = self.new_object.get('deviceInfo') - new_object_params['runSummaryList'] = self.new_object.get('runSummaryList') - new_object_params['systemResetWorkflow'] = self.new_object.get('systemResetWorkflow') - new_object_params['systemWorkflow'] = self.new_object.get('systemWorkflow') - new_object_params['tenantId'] = self.new_object.get('tenantId') - new_object_params['version'] = self.new_object.get('version') - new_object_params['workflow'] = self.new_object.get('workflow') - new_object_params['workflowParameters'] = self.new_object.get('workflowParameters') return new_object_params def delete_by_id_params(self): @@ -127,15 +97,8 @@ def delete_by_id_params(self): def update_by_id_params(self): new_object_params = {} - new_object_params['_id'] = self.new_object.get('_id') + new_object_params['id'] = self.new_object.get('id') new_object_params['deviceInfo'] = self.new_object.get('deviceInfo') - new_object_params['runSummaryList'] = self.new_object.get('runSummaryList') - new_object_params['systemResetWorkflow'] = self.new_object.get('systemResetWorkflow') - new_object_params['systemWorkflow'] = self.new_object.get('systemWorkflow') - new_object_params['tenantId'] = self.new_object.get('tenantId') - new_object_params['version'] = self.new_object.get('version') - new_object_params['workflow'] = self.new_object.get('workflow') - new_object_params['workflowParameters'] = self.new_object.get('workflowParameters') new_object_params['id'] = self.new_object.get('id') return new_object_params @@ -206,15 +169,7 @@ def requires_update(self, current_obj): requested_obj = self.new_object obj_params = [ - ("_id", "_id"), ("deviceInfo", "deviceInfo"), - ("runSummaryList", "runSummaryList"), - ("systemResetWorkflow", "systemResetWorkflow"), - ("systemWorkflow", "systemWorkflow"), - ("tenantId", "tenantId"), - ("version", "version"), - ("workflow", "workflow"), - ("workflowParameters", "workflowParameters"), ("id", "id"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params diff --git a/plugins/action/pnp_device_authorize.py b/plugins/action/pnp_device_authorize.py index 2e6f18aca4..140b06bf8f 100644 --- a/plugins/action/pnp_device_authorize.py +++ b/plugins/action/pnp_device_authorize.py @@ -76,7 +76,7 @@ def run(self, tmp=None, task_vars=None): dnac = DNACSDK(params=self._task.args) response = dnac.exec( - family="cisco_dna_center_system", + family="device_onboarding_pnp", function='authorize_device', op_modifies=True, params=self.get_object(self._task.args), diff --git a/plugins/action/pnp_device_claim_to_site.py b/plugins/action/pnp_device_claim_to_site.py index 6bceab4a17..33e1ccb034 100644 --- a/plugins/action/pnp_device_claim_to_site.py +++ b/plugins/action/pnp_device_claim_to_site.py @@ -34,8 +34,8 @@ staticIP=dict(type="str"), subnetMask=dict(type="str"), gateway=dict(type="str"), - vlanID=dict(type="str"), - interfaceName=dict(type="str"), + vlanId=dict(type="str"), + ipInterfaceName=dict(type="str"), sensorProfile=dict(type="str"), )) @@ -83,8 +83,8 @@ def get_object(self, params): staticIP=params.get("staticIP"), subnetMask=params.get("subnetMask"), gateway=params.get("gateway"), - vlanID=params.get("vlanID"), - interfaceName=params.get("interfaceName"), + vlanId=params.get("vlanId"), + ipInterfaceName=params.get("ipInterfaceName"), sensorProfile=params.get("sensorProfile"), ) return new_object diff --git a/plugins/action/pnp_device_count_info.py b/plugins/action/pnp_device_count_info.py index 933b8bd0ca..a43bf56827 100644 --- a/plugins/action/pnp_device_count_info.py +++ b/plugins/action/pnp_device_count_info.py @@ -28,13 +28,10 @@ serialNumber=dict(type="list"), state_=dict(type="list"), onbState=dict(type="list"), - cmState=dict(type="list"), name=dict(type="list"), pid=dict(type="list"), source=dict(type="list"), - projectId=dict(type="list"), workflowId=dict(type="list"), - projectName=dict(type="list"), workflowName=dict(type="list"), smartAccountId=dict(type="list"), virtualAccountId=dict(type="list"), @@ -80,13 +77,10 @@ def get_object(self, params): serial_number=params.get("serialNumber"), state=params.get("state_"), onb_state=params.get("onbState"), - cm_state=params.get("cmState"), name=params.get("name"), pid=params.get("pid"), source=params.get("source"), - project_id=params.get("projectId"), workflow_id=params.get("workflowId"), - project_name=params.get("projectName"), workflow_name=params.get("workflowName"), smart_account_id=params.get("smartAccountId"), virtual_account_id=params.get("virtualAccountId"), diff --git a/plugins/action/pnp_device_info.py b/plugins/action/pnp_device_info.py index 529736179f..b0d567c208 100644 --- a/plugins/action/pnp_device_info.py +++ b/plugins/action/pnp_device_info.py @@ -32,13 +32,10 @@ serialNumber=dict(type="list"), state_=dict(type="list"), onbState=dict(type="list"), - cmState=dict(type="list"), name=dict(type="list"), pid=dict(type="list"), source=dict(type="list"), - projectId=dict(type="list"), workflowId=dict(type="list"), - projectName=dict(type="list"), workflowName=dict(type="list"), smartAccountId=dict(type="list"), virtualAccountId=dict(type="list"), @@ -92,13 +89,10 @@ def get_object(self, params): serial_number=params.get("serialNumber"), state=params.get("state_"), onb_state=params.get("onbState"), - cm_state=params.get("cmState"), name=params.get("name"), pid=params.get("pid"), source=params.get("source"), - project_id=params.get("projectId"), workflow_id=params.get("workflowId"), - project_name=params.get("projectName"), workflow_name=params.get("workflowName"), smart_account_id=params.get("smartAccountId"), virtual_account_id=params.get("virtualAccountId"), diff --git a/plugins/action/pnp_server_profile_update.py b/plugins/action/pnp_server_profile_update.py index 209812d6db..2414b69b8c 100644 --- a/plugins/action/pnp_server_profile_update.py +++ b/plugins/action/pnp_server_profile_update.py @@ -25,19 +25,10 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - autoSyncPeriod=dict(type="int"), - ccoUser=dict(type="str"), - expiry=dict(type="int"), - lastSync=dict(type="int"), - profile=dict(type="dict"), smartAccountId=dict(type="str"), - syncResult=dict(type="dict"), - syncResultStr=dict(type="str"), - syncStartTime=dict(type="int"), - syncStatus=dict(type="str"), - tenantId=dict(type="str"), - token=dict(type="str"), virtualAccountId=dict(type="str"), + profile=dict(type="dict"), + ccoUser=dict(type="str"), )) required_if = [] @@ -75,19 +66,10 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( - autoSyncPeriod=params.get("autoSyncPeriod"), - ccoUser=params.get("ccoUser"), - expiry=params.get("expiry"), - lastSync=params.get("lastSync"), - profile=params.get("profile"), smartAccountId=params.get("smartAccountId"), - syncResult=params.get("syncResult"), - syncResultStr=params.get("syncResultStr"), - syncStartTime=params.get("syncStartTime"), - syncStatus=params.get("syncStatus"), - tenantId=params.get("tenantId"), - token=params.get("token"), virtualAccountId=params.get("virtualAccountId"), + profile=params.get("profile"), + ccoUser=params.get("ccoUser"), ) return new_object diff --git a/plugins/action/pnp_workflow.py b/plugins/action/pnp_workflow.py index 7a42ea0d9e..868106c710 100644 --- a/plugins/action/pnp_workflow.py +++ b/plugins/action/pnp_workflow.py @@ -149,6 +149,7 @@ def update_by_id_params(self): new_object_params['useState'] = self.new_object.get('useState') new_object_params['version'] = self.new_object.get('version') new_object_params['id'] = self.new_object.get('id') + new_object_params['id'] = self.new_object.get('id') return new_object_params def get_object_by_name(self, name): diff --git a/plugins/action/reports.py b/plugins/action/reports.py index 28f656870e..decf205458 100644 --- a/plugins/action/reports.py +++ b/plugins/action/reports.py @@ -38,6 +38,7 @@ view=dict(type="dict"), viewGroupId=dict(type="str"), viewGroupVersion=dict(type="str"), + dataCategory=dict(type="str"), reportId=dict(type="str"), )) @@ -61,6 +62,7 @@ def __init__(self, params, dnac): view=params.get("view"), viewGroupId=params.get("viewGroupId"), viewGroupVersion=params.get("viewGroupVersion"), + dataCategory=params.get("dataCategory"), report_id=params.get("reportId"), ) @@ -80,6 +82,7 @@ def create_params(self): new_object_params['view'] = self.new_object.get('view') new_object_params['viewGroupId'] = self.new_object.get('viewGroupId') new_object_params['viewGroupVersion'] = self.new_object.get('viewGroupVersion') + new_object_params['dataCategory'] = self.new_object.get('dataCategory') return new_object_params def delete_by_id_params(self): @@ -157,6 +160,7 @@ def requires_update(self, current_obj): ("view", "view"), ("viewGroupId", "viewGroupId"), ("viewGroupVersion", "viewGroupVersion"), + ("dataCategory", "dataCategory"), ("reportId", "report_id"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/plugins/action/reserve_ip_subpool.py b/plugins/action/reserve_ip_subpool.py index 22ea8edae3..152438824c 100644 --- a/plugins/action/reserve_ip_subpool.py +++ b/plugins/action/reserve_ip_subpool.py @@ -98,6 +98,12 @@ def get_all_params(self, name=None, id=None): self.new_object.get('site_id') new_object_params['offset'] = self.new_object.get('offset') new_object_params['limit'] = self.new_object.get('limit') + new_object_params['ignore_inherited_groups'] = self.new_object.get('ignoreInheritedGroups') or \ + self.new_object.get('ignore_inherited_groups') + new_object_params['pool_usage'] = self.new_object.get('poolUsage') or \ + self.new_object.get('pool_usage') + new_object_params['group_name'] = self.new_object.get('groupName') or \ + self.new_object.get('group_name') return new_object_params def create_params(self): @@ -122,6 +128,7 @@ def create_params(self): new_object_params['ipv4TotalHost'] = self.new_object.get('ipv4TotalHost') new_object_params['ipv6TotalHost'] = self.new_object.get('ipv6TotalHost') new_object_params['slaacSupport'] = self.new_object.get('slaacSupport') + new_object_params['siteId'] = self.new_object.get('siteId') new_object_params['site_id'] = self.new_object.get('site_id') return new_object_params @@ -140,12 +147,13 @@ def update_by_id_params(self): new_object_params['ipv6Prefix'] = self.new_object.get('ipv6Prefix') new_object_params['ipv6PrefixLength'] = self.new_object.get('ipv6PrefixLength') new_object_params['ipv6Subnet'] = self.new_object.get('ipv6Subnet') + new_object_params['ipv6TotalHost'] = self.new_object.get('ipv6TotalHost') new_object_params['ipv6GateWay'] = self.new_object.get('ipv6GateWay') new_object_params['ipv6DhcpServers'] = self.new_object.get('ipv6DhcpServers') new_object_params['ipv6DnsServers'] = self.new_object.get('ipv6DnsServers') - new_object_params['ipv6TotalHost'] = self.new_object.get('ipv6TotalHost') new_object_params['slaacSupport'] = self.new_object.get('slaacSupport') new_object_params['ipv4GateWay'] = self.new_object.get('ipv4GateWay') + new_object_params['siteId'] = self.new_object.get('siteId') new_object_params['id'] = self.new_object.get('id') new_object_params['site_id'] = self.new_object.get('site_id') return new_object_params diff --git a/plugins/action/reserve_ip_subpool_info.py b/plugins/action/reserve_ip_subpool_info.py index c704db1ef9..bcf946a930 100644 --- a/plugins/action/reserve_ip_subpool_info.py +++ b/plugins/action/reserve_ip_subpool_info.py @@ -26,8 +26,11 @@ # Add arguments specific for this module argument_spec.update(dict( siteId=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), + ignoreInheritedGroups=dict(type="str"), + poolUsage=dict(type="str"), + groupName=dict(type="str"), headers=dict(type="dict"), )) @@ -69,6 +72,9 @@ def get_object(self, params): site_id=params.get("siteId"), offset=params.get("offset"), limit=params.get("limit"), + ignore_inherited_groups=params.get("ignoreInheritedGroups"), + pool_usage=params.get("poolUsage"), + group_name=params.get("groupName"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/reserve_ip_subpool_update.py b/plugins/action/reserve_ip_subpool_update.py index 4d2f8bf582..c3ef0accc3 100644 --- a/plugins/action/reserve_ip_subpool_update.py +++ b/plugins/action/reserve_ip_subpool_update.py @@ -33,10 +33,10 @@ ipv6Prefix=dict(type="bool"), ipv6PrefixLength=dict(type="int"), ipv6Subnet=dict(type="str"), + ipv6TotalHost=dict(type="int"), ipv6GateWay=dict(type="str"), ipv6DhcpServers=dict(type="list"), ipv6DnsServers=dict(type="list"), - ipv6TotalHost=dict(type="int"), slaacSupport=dict(type="bool"), ipv4GateWay=dict(type="str"), siteId=dict(type="str"), @@ -86,10 +86,10 @@ def get_object(self, params): ipv6Prefix=params.get("ipv6Prefix"), ipv6PrefixLength=params.get("ipv6PrefixLength"), ipv6Subnet=params.get("ipv6Subnet"), + ipv6TotalHost=params.get("ipv6TotalHost"), ipv6GateWay=params.get("ipv6GateWay"), ipv6DhcpServers=params.get("ipv6DhcpServers"), ipv6DnsServers=params.get("ipv6DnsServers"), - ipv6TotalHost=params.get("ipv6TotalHost"), slaacSupport=params.get("slaacSupport"), ipv4GateWay=params.get("ipv4GateWay"), site_id=params.get("siteId"), diff --git a/plugins/action/roles.py b/plugins/action/roles.py new file mode 100644 index 0000000000..38b6ba42ae --- /dev/null +++ b/plugins/action/roles.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + role=dict(type="str"), + description=dict(type="str"), + resourceTypes=dict(type="list"), + roleId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["role", "roleId"], True), + ("state", "absent", ["role", "roleId"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class Roles(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + role=params.get("role"), + description=params.get("description"), + resourceTypes=params.get("resourceTypes"), + roleId=params.get("roleId"), + role_id=params.get("roleId"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['role'] = self.new_object.get('role') + new_object_params['description'] = self.new_object.get('description') + new_object_params['resourceTypes'] = self.new_object.get('resourceTypes') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['role_id'] = self.new_object.get('role_id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['roleId'] = self.new_object.get('roleId') + new_object_params['description'] = self.new_object.get('description') + new_object_params['resourceTypes'] = self.new_object.get('resourceTypes') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="userand_roles", + function="get_roles_api", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="userand_roles", + function="get_roles_api", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self): + id_exists = False + name_exists = False + prev_obj = None + o_id = self.new_object.get("id") + o_id = o_id or self.new_object.get("role_id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + _id = _id or prev_obj.get("roleId") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + self.new_object.update(dict(role_id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("role", "role"), + ("description", "description"), + ("resourceTypes", "resourceTypes"), + ("roleId", "roleId"), + ("roleId", "role_id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="userand_roles", + function="add_role_api", + params=self.create_params(), + op_modifies=True, + ) + return result + + def update(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + result = self.dnac.exec( + family="userand_roles", + function="update_role_api", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + id = self.new_object.get("id") + id = id or self.new_object.get("role_id") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + id_ = id_ or prev_obj_name.get("roleId") + if id_: + self.new_object.update(dict(role_id=id_)) + result = self.dnac.exec( + family="userand_roles", + function="delete_role_api", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = Roles(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_anycast_gateways.py b/plugins/action/sda_anycast_gateways.py new file mode 100644 index 0000000000..0fe26ddfb3 --- /dev/null +++ b/plugins/action/sda_anycast_gateways.py @@ -0,0 +1,284 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaAnycastGateways(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['id'] = id or self.new_object.get('id') + new_object_params['fabric_id'] = self.new_object.get('fabricId') or \ + self.new_object.get('fabric_id') + new_object_params['virtual_network_name'] = self.new_object.get('virtualNetworkName') or \ + self.new_object.get('virtual_network_name') + new_object_params['ip_pool_name'] = self.new_object.get('ipPoolName') or \ + self.new_object.get('ip_pool_name') + new_object_params['vlan_name'] = self.new_object.get('vlanName') or \ + self.new_object.get('vlan_name') + new_object_params['vlan_id'] = self.new_object.get('vlanId') or \ + self.new_object.get('vlan_id') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_anycast_gateways", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_anycast_gateways", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("fabricId", "fabricId"), + ("virtualNetworkName", "virtualNetworkName"), + ("ipPoolName", "ipPoolName"), + ("tcpMssAdjustment", "tcpMssAdjustment"), + ("vlanName", "vlanName"), + ("vlanId", "vlanId"), + ("trafficType", "trafficType"), + ("poolType", "poolType"), + ("securityGroupName", "securityGroupName"), + ("isCriticalPool", "isCriticalPool"), + ("isLayer2FloodingEnabled", "isLayer2FloodingEnabled"), + ("isWirelessPool", "isWirelessPool"), + ("isIpDirectedBroadcast", "isIpDirectedBroadcast"), + ("isIntraSubnetRoutingEnabled", "isIntraSubnetRoutingEnabled"), + ("isMultipleIpToMacAddresses", "isMultipleIpToMacAddresses"), + ("isSupplicantBasedExtendedNodeOnboarding", "isSupplicantBasedExtendedNodeOnboarding"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_anycast_gateways", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_anycast_gateways", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_anycast_gateway_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaAnycastGateways(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_anycast_gateways_count_info.py b/plugins/action/sda_anycast_gateways_count_info.py new file mode 100644 index 0000000000..f33187d702 --- /dev/null +++ b/plugins/action/sda_anycast_gateways_count_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + virtualNetworkName=dict(type="str"), + ipPoolName=dict(type="str"), + vlanName=dict(type="str"), + vlanId=dict(type="int"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + virtual_network_name=params.get("virtualNetworkName"), + ip_pool_name=params.get("ipPoolName"), + vlan_name=params.get("vlanName"), + vlan_id=params.get("vlanId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_anycast_gateway_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_anycast_gateways_info.py b/plugins/action/sda_anycast_gateways_info.py new file mode 100644 index 0000000000..7e13dde41f --- /dev/null +++ b/plugins/action/sda_anycast_gateways_info.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + id=dict(type="str"), + fabricId=dict(type="str"), + virtualNetworkName=dict(type="str"), + ipPoolName=dict(type="str"), + vlanName=dict(type="str"), + vlanId=dict(type="int"), + offset=dict(type="int"), + limit=dict(type="int"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + id=params.get("id"), + fabric_id=params.get("fabricId"), + virtual_network_name=params.get("virtualNetworkName"), + ip_pool_name=params.get("ipPoolName"), + vlan_name=params.get("vlanName"), + vlan_id=params.get("vlanId"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_anycast_gateways', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_authentication_profiles.py b/plugins/action/sda_authentication_profiles.py new file mode 100644 index 0000000000..fde4c48cc1 --- /dev/null +++ b/plugins/action/sda_authentication_profiles.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + payload=dict(type="list"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaAuthenticationProfiles(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['fabric_id'] = self.new_object.get('fabricId') or \ + self.new_object.get('fabric_id') + new_object_params['authentication_profile_name'] = self.new_object.get('authenticationProfileName') or \ + self.new_object.get('authentication_profile_name') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method, using get all + try: + items = self.dnac.exec( + family="sda", + function="get_authentication_profiles", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("fabricId", "fabricId"), + ("authenticationProfileName", "authenticationProfileName"), + ("authenticationOrder", "authenticationOrder"), + ("dot1xToMabFallbackTimeout", "dot1xToMabFallbackTimeout"), + ("wakeOnLan", "wakeOnLan"), + ("numberOfHosts", "numberOfHosts"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_authentication_profile", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaAuthenticationProfiles(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + dnac.fail_json("Object does not exists, plugin only has update") + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_authentication_profiles_info.py b/plugins/action/sda_authentication_profiles_info.py new file mode 100644 index 0000000000..cb7a4a143a --- /dev/null +++ b/plugins/action/sda_authentication_profiles_info.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + authenticationProfileName=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + authentication_profile_name=params.get("authenticationProfileName"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_authentication_profiles', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_extranet_policies.py b/plugins/action/sda_extranet_policies.py new file mode 100644 index 0000000000..265d7c34b0 --- /dev/null +++ b/plugins/action/sda_extranet_policies.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaExtranetPolicies(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['extranet_policy_name'] = self.new_object.get('extranetPolicyName') or \ + self.new_object.get('extranet_policy_name') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_extranet_policies", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_extranet_policies", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("extranetPolicyName", "extranetPolicyName"), + ("fabricIds", "fabricIds"), + ("providerVirtualNetworkName", "providerVirtualNetworkName"), + ("subscriberVirtualNetworkNames", "subscriberVirtualNetworkNames"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_extranet_policy", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_extranet_policy", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_extranet_policy_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaExtranetPolicies(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_extranet_policies_count_info.py b/plugins/action/sda_extranet_policies_count_info.py new file mode 100644 index 0000000000..b880f0edda --- /dev/null +++ b/plugins/action/sda_extranet_policies_count_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_extranet_policy_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_extranet_policies_info.py b/plugins/action/sda_extranet_policies_info.py new file mode 100644 index 0000000000..ebb3b4e121 --- /dev/null +++ b/plugins/action/sda_extranet_policies_info.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + extranetPolicyName=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + extranet_policy_name=params.get("extranetPolicyName"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_extranet_policies', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_authentication_profile.py b/plugins/action/sda_fabric_authentication_profile.py index 91a1f3ae5a..d546eed18d 100644 --- a/plugins/action/sda_fabric_authentication_profile.py +++ b/plugins/action/sda_fabric_authentication_profile.py @@ -159,8 +159,11 @@ def update(self): return result def delete(self): - id = self.new_object.get("id") - name = self.new_object.get("name") + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") result = None result = self.dnac.exec( family="sda", diff --git a/plugins/action/sda_fabric_border_device.py b/plugins/action/sda_fabric_border_device.py index ab907f8088..1088414d9d 100644 --- a/plugins/action/sda_fabric_border_device.py +++ b/plugins/action/sda_fabric_border_device.py @@ -144,8 +144,11 @@ def create(self): return result def delete(self): - id = self.new_object.get("id") - name = self.new_object.get("name") + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") result = None result = self.dnac.exec( family="sda", diff --git a/plugins/action/sda_fabric_devices.py b/plugins/action/sda_fabric_devices.py new file mode 100644 index 0000000000..e1dfa3e566 --- /dev/null +++ b/plugins/action/sda_fabric_devices.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + deviceRoles=dict(type="str"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["id"], True), + ("state", "present", ["payload"], True), + ("state", "absent", ["id"], True), + ("state", "absent", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaFabricDevices(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + device_roles=params.get("deviceRoles"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['fabric_id'] = self.new_object.get('fabricId') or \ + self.new_object.get('fabric_id') + new_object_params['network_device_id'] = self.new_object.get('networkDeviceId') or \ + self.new_object.get('network_device_id') + new_object_params['device_roles'] = self.new_object.get('deviceRoles') or \ + self.new_object.get('device_roles') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("networkDeviceId", "networkDeviceId"), + ("fabricId", "fabricId"), + ("deviceRoles", "deviceRoles"), + ("borderDeviceSettings", "borderDeviceSettings"), + ("fabricId", "fabric_id"), + ("networkDeviceId", "network_device_id"), + ("deviceRoles", "device_roles"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_fabric_devices", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_fabric_devices", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_a_fabric_device_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaFabricDevices(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_count_info.py b/plugins/action/sda_fabric_devices_count_info.py new file mode 100644 index 0000000000..f61f179faf --- /dev/null +++ b/plugins/action/sda_fabric_devices_count_info.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + deviceRoles=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + device_roles=params.get("deviceRoles"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_info.py b/plugins/action/sda_fabric_devices_info.py new file mode 100644 index 0000000000..503be554a2 --- /dev/null +++ b/plugins/action/sda_fabric_devices_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + deviceRoles=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + device_roles=params.get("deviceRoles"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs.py b/plugins/action/sda_fabric_devices_layer2_handoffs.py new file mode 100644 index 0000000000..6655e5b6a2 --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaFabricDevicesLayer2Handoffs(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['fabric_id'] = self.new_object.get('fabricId') or \ + self.new_object.get('fabric_id') + new_object_params['network_device_id'] = self.new_object.get('networkDeviceId') or \ + self.new_object.get('network_device_id') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices_layer2_handoffs", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices_layer2_handoffs", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("networkDeviceId", "networkDeviceId"), + ("fabricId", "fabricId"), + ("interfaceName", "interfaceName"), + ("internalVlanId", "internalVlanId"), + ("externalVlanId", "externalVlanId"), + ("fabricId", "fabric_id"), + ("networkDeviceId", "network_device_id"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_fabric_devices_layer2_handoffs", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + # NOTE: Does not have update method. What do we do? + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_fabric_device_layer2_handoff_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaFabricDevicesLayer2Handoffs(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_count_info.py b/plugins/action/sda_fabric_devices_layer2_handoffs_count_info.py new file mode 100644 index 0000000000..60d88025bd --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_count_info.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices_layer2_handoffs_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_info.py b/plugins/action/sda_fabric_devices_layer2_handoffs_info.py new file mode 100644 index 0000000000..fd3e8f8f81 --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_info.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices_layer2_handoffs', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits.py b/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits.py new file mode 100644 index 0000000000..7135b248e3 --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits.py @@ -0,0 +1,279 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaFabricDevicesLayer2HandoffsIpTransits(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['fabric_id'] = self.new_object.get('fabricId') or \ + self.new_object.get('fabric_id') + new_object_params['network_device_id'] = self.new_object.get('networkDeviceId') or \ + self.new_object.get('network_device_id') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices_layer3_handoffs_with_ip_transit", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices_layer3_handoffs_with_ip_transit", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("networkDeviceId", "networkDeviceId"), + ("fabricId", "fabricId"), + ("transitNetworkId", "transitNetworkId"), + ("interfaceName", "interfaceName"), + ("externalConnectivityIpPoolName", "externalConnectivityIpPoolName"), + ("virtualNetworkName", "virtualNetworkName"), + ("vlanId", "vlanId"), + ("tcpMssAdjustment", "tcpMssAdjustment"), + ("localIpAddress", "localIpAddress"), + ("remoteIpAddress", "remoteIpAddress"), + ("localIpv6Address", "localIpv6Address"), + ("remoteIpv6Address", "remoteIpv6Address"), + ("fabricId", "fabric_id"), + ("networkDeviceId", "network_device_id"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_fabric_devices_layer3_handoffs_with_ip_transit", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_fabric_devices_layer3_handoffs_with_ip_transit", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_fabric_device_layer3_handoff_with_ip_transit_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaFabricDevicesLayer2HandoffsIpTransits(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits_count_info.py b/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits_count_info.py new file mode 100644 index 0000000000..bab5146752 --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits_count_info.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices_layer3_handoffs_with_ip_transit_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits_info.py b/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits_info.py new file mode 100644 index 0000000000..dd843a5001 --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_ip_transits_info.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices_layer3_handoffs_with_ip_transit', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits.py b/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits.py new file mode 100644 index 0000000000..5353e6183f --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits.py @@ -0,0 +1,264 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaFabricDevicesLayer2HandoffsSdaTransits(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['fabric_id'] = self.new_object.get('fabricId') or \ + self.new_object.get('fabric_id') + new_object_params['network_device_id'] = self.new_object.get('networkDeviceId') or \ + self.new_object.get('network_device_id') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_all_params(self): + new_object_params = {} + new_object_params['fabric_id'] = self.new_object.get('fabric_id') + new_object_params['network_device_id'] = self.new_object.get('network_device_id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices_layer3_handoffs_with_sda_transit", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_devices_layer3_handoffs_with_sda_transit", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("networkDeviceId", "networkDeviceId"), + ("fabricId", "fabricId"), + ("transitNetworkId", "transitNetworkId"), + ("affinityIdPrime", "affinityIdPrime"), + ("affinityIdDecider", "affinityIdDecider"), + ("connectedToInternet", "connectedToInternet"), + ("isMulticastOverTransitEnabled", "isMulticastOverTransitEnabled"), + ("fabricId", "fabric_id"), + ("networkDeviceId", "network_device_id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_fabric_devices_layer3_handoffs_with_sda_transit", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_fabric_devices_layer3_handoffs_with_sda_transit", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="delete_fabric_device_layer3_handoffs_with_sda_transit", + params=self.delete_all_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaFabricDevicesLayer2HandoffsSdaTransits(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits_count_info.py b/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits_count_info.py new file mode 100644 index 0000000000..4a46b53b5d --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits_count_info.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices_layer3_handoffs_with_sda_transit_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits_info.py b/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits_info.py new file mode 100644 index 0000000000..556e656c6d --- /dev/null +++ b/plugins/action/sda_fabric_devices_layer2_handoffs_sda_transits_info.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_devices_layer3_handoffs_with_sda_transit', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_sites.py b/plugins/action/sda_fabric_sites.py new file mode 100644 index 0000000000..c9f4a4378b --- /dev/null +++ b/plugins/action/sda_fabric_sites.py @@ -0,0 +1,263 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaFabricSites(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['id'] = id or self.new_object.get('id') + new_object_params['site_id'] = self.new_object.get('siteId') or \ + self.new_object.get('site_id') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_sites", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_sites", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("siteId", "siteId"), + ("authenticationProfileName", "authenticationProfileName"), + ("isPubSubEnabled", "isPubSubEnabled"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_fabric_site", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_fabric_site", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_fabric_site_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaFabricSites(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_sites_count_info.py b/plugins/action/sda_fabric_sites_count_info.py new file mode 100644 index 0000000000..28d6845717 --- /dev/null +++ b/plugins/action/sda_fabric_sites_count_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_site_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_sites_info.py b/plugins/action/sda_fabric_sites_info.py new file mode 100644 index 0000000000..9bea361ed8 --- /dev/null +++ b/plugins/action/sda_fabric_sites_info.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + id=dict(type="str"), + siteId=dict(type="str"), + offset=dict(type="int"), + limit=dict(type="int"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + id=params.get("id"), + site_id=params.get("siteId"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_sites', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_zones.py b/plugins/action/sda_fabric_zones.py new file mode 100644 index 0000000000..f441b88900 --- /dev/null +++ b/plugins/action/sda_fabric_zones.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaFabricZones(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['id'] = id or self.new_object.get('id') + new_object_params['site_id'] = self.new_object.get('siteId') or \ + self.new_object.get('site_id') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_zones", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_fabric_zones", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("siteId", "siteId"), + ("authenticationProfileName", "authenticationProfileName"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_fabric_zone", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_fabric_zone", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_fabric_zone_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaFabricZones(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_zones_count_info.py b/plugins/action/sda_fabric_zones_count_info.py new file mode 100644 index 0000000000..28b84a9c08 --- /dev/null +++ b/plugins/action/sda_fabric_zones_count_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_zone_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_fabric_zones_info.py b/plugins/action/sda_fabric_zones_info.py new file mode 100644 index 0000000000..c1e5a10165 --- /dev/null +++ b/plugins/action/sda_fabric_zones_info.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + id=dict(type="str"), + siteId=dict(type="str"), + offset=dict(type="int"), + limit=dict(type="int"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + id=params.get("id"), + site_id=params.get("siteId"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_fabric_zones', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_port_assignments.py b/plugins/action/sda_port_assignments.py new file mode 100644 index 0000000000..2c2158103f --- /dev/null +++ b/plugins/action/sda_port_assignments.py @@ -0,0 +1,291 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + interfaceName=dict(type="str"), + dataVlanName=dict(type="str"), + voiceVlanName=dict(type="str"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaPortAssignments(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + interface_name=params.get("interfaceName"), + data_vlan_name=params.get("dataVlanName"), + voice_vlan_name=params.get("voiceVlanName"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['fabric_id'] = self.new_object.get('fabricId') or \ + self.new_object.get('fabric_id') + new_object_params['network_device_id'] = self.new_object.get('networkDeviceId') or \ + self.new_object.get('network_device_id') + new_object_params['interface_name'] = self.new_object.get('interfaceName') or \ + self.new_object.get('interface_name') + new_object_params['data_vlan_name'] = self.new_object.get('dataVlanName') or \ + self.new_object.get('data_vlan_name') + new_object_params['voice_vlan_name'] = self.new_object.get('voiceVlanName') or \ + self.new_object.get('voice_vlan_name') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_port_assignments", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_port_assignments", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("fabricId", "fabricId"), + ("networkDeviceId", "networkDeviceId"), + ("interfaceName", "interfaceName"), + ("connectedDeviceType", "connectedDeviceType"), + ("dataVlanName", "dataVlanName"), + ("voiceVlanName", "voiceVlanName"), + ("authenticateTemplateName", "authenticateTemplateName"), + ("scalableGroupName", "scalableGroupName"), + ("interfaceDescription", "interfaceDescription"), + ("fabricId", "fabric_id"), + ("networkDeviceId", "network_device_id"), + ("interfaceName", "interface_name"), + ("dataVlanName", "data_vlan_name"), + ("voiceVlanName", "voice_vlan_name"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="add_port_assignments", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="update_port_assignments", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_port_assignment_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaPortAssignments(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_port_assignments_count_info.py b/plugins/action/sda_port_assignments_count_info.py new file mode 100644 index 0000000000..1552d0b04b --- /dev/null +++ b/plugins/action/sda_port_assignments_count_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + interfaceName=dict(type="str"), + dataVlanName=dict(type="str"), + voiceVlanName=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + interface_name=params.get("interfaceName"), + data_vlan_name=params.get("dataVlanName"), + voice_vlan_name=params.get("voiceVlanName"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_port_assignment_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_port_assignments_info.py b/plugins/action/sda_port_assignments_info.py new file mode 100644 index 0000000000..58d5080e60 --- /dev/null +++ b/plugins/action/sda_port_assignments_info.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + fabricId=dict(type="str"), + networkDeviceId=dict(type="str"), + interfaceName=dict(type="str"), + dataVlanName=dict(type="str"), + voiceVlanName=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + fabric_id=params.get("fabricId"), + network_device_id=params.get("networkDeviceId"), + interface_name=params.get("interfaceName"), + data_vlan_name=params.get("dataVlanName"), + voice_vlan_name=params.get("voiceVlanName"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_port_assignments', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_provision_devices.py b/plugins/action/sda_provision_devices.py new file mode 100644 index 0000000000..836c8d928e --- /dev/null +++ b/plugins/action/sda_provision_devices.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + AnsibleSDAException, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + payload=dict(type="list"), + networkDeviceId=dict(type="str"), + siteId=dict(type="str"), + id=dict(type="str"), +)) + +required_if = [ + ("state", "present", ["payload"], True), +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class SdaProvisionDevices(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + payload=params.get("payload"), + network_device_id=params.get("networkDeviceId"), + site_id=params.get("siteId"), + id=params.get("id"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + new_object_params['id'] = id or self.new_object.get('id') + new_object_params['network_device_id'] = self.new_object.get('networkDeviceId') or \ + self.new_object.get('network_device_id') + new_object_params['site_id'] = self.new_object.get('siteId') or \ + self.new_object.get('site_id') + new_object_params['offset'] = self.new_object.get('offset') + new_object_params['limit'] = self.new_object.get('limit') + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def delete_by_id_params(self): + new_object_params = {} + new_object_params['id'] = self.new_object.get('id') + return new_object_params + + def update_all_params(self): + new_object_params = {} + new_object_params['payload'] = self.new_object.get('payload') + return new_object_params + + def get_object_by_name(self, name, is_absent=False): + result = None + # NOTE: Does not have a get by name method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_provisioned_devices", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + if isinstance(items, dict) and items.get("status") == "failed": + if is_absent: + raise AnsibleSDAException(response=items) + result = None + return result + result = get_dict_result(items, 'name', name) + except Exception: + if is_absent: + raise + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="sda", + function="get_provisioned_devices", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None + return result + + def exists(self, is_absent=False): + name = self.new_object.get("name") + prev_obj = self.get_object_by_name(name, is_absent=is_absent) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + + obj_params = [ + ("id", "id"), + ("siteId", "siteId"), + ("networkDeviceId", "networkDeviceId"), + ("networkDeviceId", "network_device_id"), + ("siteId", "site_id"), + ("id", "id"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="sda", + function="provision_devices", + params=self.create_params(), + op_modifies=True, + ) + if isinstance(result, dict): + if 'response' in result: + result = result.get('response') + if isinstance(result, dict) and result.get("status") == "failed": + raise AnsibleSDAException(response=result) + return result + + def update(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + result = self.dnac.exec( + family="sda", + function="re_provision_devices", + params=self.update_all_params(), + op_modifies=True, + ) + return result + + def delete(self): + requested_obj = self.new_object.get('payload') + if requested_obj and len(requested_obj) > 0: + requested_obj = requested_obj[0] + id = self.new_object.get("id") or requested_obj.get("id") + name = self.new_object.get("name") or requested_obj.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + if id_: + self.new_object.update(dict(id=id_)) + result = self.dnac.exec( + family="sda", + function="delete_provisioned_device_by_id", + params=self.delete_by_id_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = SdaProvisionDevices(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = obj.update() + dnac.object_updated() + else: + response = prev_obj + dnac.object_already_present() + else: + try: + response = obj.create() + dnac.object_created() + except AnsibleSDAException as e: + dnac.fail_json("Could not create object {e}".format(e=e._response)) + + elif state == "absent": + try: + (obj_exists, prev_obj) = obj.exists(is_absent=True) + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + except AnsibleSDAException as e: + dnac.fail_json("Could not get object to be delete {e}".format(e=e._response)) + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_provision_devices_count_info.py b/plugins/action/sda_provision_devices_count_info.py new file mode 100644 index 0000000000..3e36f931db --- /dev/null +++ b/plugins/action/sda_provision_devices_count_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + siteId=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + site_id=params.get("siteId"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_provisioned_devices_count', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_provision_devices_info.py b/plugins/action/sda_provision_devices_info.py new file mode 100644 index 0000000000..b06f1252e7 --- /dev/null +++ b/plugins/action/sda_provision_devices_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + id=dict(type="str"), + networkDeviceId=dict(type="str"), + siteId=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + id=params.get("id"), + network_device_id=params.get("networkDeviceId"), + site_id=params.get("siteId"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sda", + function='get_provisioned_devices', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_site_member_member_info.py b/plugins/action/sda_site_member_member_info.py new file mode 100644 index 0000000000..cc1bca386e --- /dev/null +++ b/plugins/action/sda_site_member_member_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + id=dict(type="str"), + offset=dict(type="str"), + limit=dict(type="str"), + memberType=dict(type="str"), + level=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + id=params.get("id"), + offset=params.get("offset"), + limit=params.get("limit"), + member_type=params.get("memberType"), + level=params.get("level"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='get_devices_that_are_assigned_to_a_site', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/sda_virtual_network_ip_pool.py b/plugins/action/sda_virtual_network_ip_pool.py index 674f550183..b5128268b2 100644 --- a/plugins/action/sda_virtual_network_ip_pool.py +++ b/plugins/action/sda_virtual_network_ip_pool.py @@ -83,8 +83,7 @@ def __init__(self, params, dnac): def get_all_params(self, name=None, id=None): new_object_params = {} - new_object_params['site_name_hierarchy'] = self.new_object.get('site_name_hierarchy') or \ - self.new_object.get('siteNameHierarchy') + new_object_params['siteNameHierarchy'] = self.new_object.get('site_name_hierarchy') new_object_params['virtual_network_name'] = self.new_object.get('virtualNetworkName') or \ self.new_object.get('virtual_network_name') new_object_params['ip_pool_name'] = self.new_object.get('ipPoolName') or \ diff --git a/plugins/action/security_advisories_ids_per_device_info.py b/plugins/action/security_advisories_ids_per_device_info.py index eebfa56275..c298066b8f 100644 --- a/plugins/action/security_advisories_ids_per_device_info.py +++ b/plugins/action/security_advisories_ids_per_device_info.py @@ -83,7 +83,7 @@ def run(self, tmp=None, task_vars=None): if id: response = dnac.exec( family="security_advisories", - function='get_advisory_ids_per_device', + function='get_advisory_device_detail', params=self.get_object(self._task.args), ) self._result.update(dict(dnac_response=response)) diff --git a/plugins/action/sensor.py b/plugins/action/sensor.py index 7972398347..7d2df435d0 100644 --- a/plugins/action/sensor.py +++ b/plugins/action/sensor.py @@ -31,11 +31,17 @@ # Add arguments specific for this module argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), - ssids=dict(type="list"), name=dict(type="str"), + version=dict(type="int"), + modelVersion=dict(type="int"), connection=dict(type="str"), + ssids=dict(type="list"), + profiles=dict(type="list"), + encryptionMode=dict(type="str"), + runNow=dict(type="str"), + locationInfoList=dict(type="list"), + sensors=dict(type="list"), apCoverage=dict(type="list"), - modelVersion=dict(type="int"), templateName=dict(type="str"), )) @@ -52,11 +58,17 @@ class Sensor(object): def __init__(self, params, dnac): self.dnac = dnac self.new_object = dict( - ssids=params.get("ssids"), name=params.get("name"), + version=params.get("version"), + modelVersion=params.get("modelVersion"), connection=params.get("connection"), + ssids=params.get("ssids"), + profiles=params.get("profiles"), + encryptionMode=params.get("encryptionMode"), + runNow=params.get("runNow"), + locationInfoList=params.get("locationInfoList"), + sensors=params.get("sensors"), apCoverage=params.get("apCoverage"), - modelVersion=params.get("modelVersion"), template_name=params.get("templateName"), ) @@ -68,11 +80,17 @@ def get_all_params(self, name=None, id=None): def create_params(self): new_object_params = {} - new_object_params['ssids'] = self.new_object.get('ssids') new_object_params['name'] = self.new_object.get('name') + new_object_params['version'] = self.new_object.get('version') + new_object_params['modelVersion'] = self.new_object.get('modelVersion') new_object_params['connection'] = self.new_object.get('connection') + new_object_params['ssids'] = self.new_object.get('ssids') + new_object_params['profiles'] = self.new_object.get('profiles') + new_object_params['encryptionMode'] = self.new_object.get('encryptionMode') + new_object_params['runNow'] = self.new_object.get('runNow') + new_object_params['locationInfoList'] = self.new_object.get('locationInfoList') + new_object_params['sensors'] = self.new_object.get('sensors') new_object_params['apCoverage'] = self.new_object.get('apCoverage') - new_object_params['modelVersion'] = self.new_object.get('modelVersion') return new_object_params def delete_all_params(self): @@ -127,11 +145,17 @@ def requires_update(self, current_obj): requested_obj = self.new_object obj_params = [ - ("ssids", "ssids"), ("name", "name"), + ("version", "version"), + ("modelVersion", "modelVersion"), ("connection", "connection"), + ("ssids", "ssids"), + ("profiles", "profiles"), + ("encryptionMode", "encryptionMode"), + ("runNow", "runNow"), + ("locationInfoList", "locationInfoList"), + ("sensors", "sensors"), ("apCoverage", "apCoverage"), - ("modelVersion", "modelVersion"), ("templateName", "template_name"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params diff --git a/plugins/action/sensor_test_template_edit.py b/plugins/action/sensor_test_template_edit.py index 5e75c953b1..9b3a8d200f 100644 --- a/plugins/action/sensor_test_template_edit.py +++ b/plugins/action/sensor_test_template_edit.py @@ -26,8 +26,33 @@ # Add arguments specific for this module argument_spec.update(dict( templateName=dict(type="str"), + name=dict(type="str"), + _id=dict(type="str"), + version=dict(type="int"), + modelVersion=dict(type="int"), + startTime=dict(type="int"), + lastModifiedTime=dict(type="int"), + numAssociatedSensor=dict(type="int"), + location=dict(type="str"), + siteHierarchy=dict(type="str"), + status=dict(type="str"), + connection=dict(type="str"), + actionInProgress=dict(type="str"), + frequency=dict(type="dict"), + rssiThreshold=dict(type="int"), + numNeighborAPThreshold=dict(type="int"), + scheduleInDays=dict(type="int"), + wlans=dict(type="list"), + ssids=dict(type="list"), + profiles=dict(type="list"), + testScheduleMode=dict(type="str"), + showWlcUpgradeBanner=dict(type="bool"), + radioAsSensorRemoved=dict(type="bool"), + encryptionMode=dict(type="str"), + runNow=dict(type="str"), locationInfoList=dict(type="list"), - schedule=dict(type="dict"), + sensors=dict(type="list"), + apCoverage=dict(type="list"), )) required_if = [] @@ -66,8 +91,33 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( templateName=params.get("templateName"), + name=params.get("name"), + _id=params.get("_id"), + version=params.get("version"), + modelVersion=params.get("modelVersion"), + startTime=params.get("startTime"), + lastModifiedTime=params.get("lastModifiedTime"), + numAssociatedSensor=params.get("numAssociatedSensor"), + location=params.get("location"), + siteHierarchy=params.get("siteHierarchy"), + status=params.get("status"), + connection=params.get("connection"), + actionInProgress=params.get("actionInProgress"), + frequency=params.get("frequency"), + rssiThreshold=params.get("rssiThreshold"), + numNeighborAPThreshold=params.get("numNeighborAPThreshold"), + scheduleInDays=params.get("scheduleInDays"), + wlans=params.get("wlans"), + ssids=params.get("ssids"), + profiles=params.get("profiles"), + testScheduleMode=params.get("testScheduleMode"), + showWlcUpgradeBanner=params.get("showWlcUpgradeBanner"), + radioAsSensorRemoved=params.get("radioAsSensorRemoved"), + encryptionMode=params.get("encryptionMode"), + runNow=params.get("runNow"), locationInfoList=params.get("locationInfoList"), - schedule=params.get("schedule"), + sensors=params.get("sensors"), + apCoverage=params.get("apCoverage"), ) return new_object diff --git a/plugins/action/site_assign_device.py b/plugins/action/site_assign_device.py index dec7df437c..d905f21e7d 100644 --- a/plugins/action/site_assign_device.py +++ b/plugins/action/site_assign_device.py @@ -78,7 +78,7 @@ def run(self, tmp=None, task_vars=None): Display().warning("This module is currently unmaintained " "and will be removed in future releases." "New module is assign_device_to_site " - "for 2.3.5.3 or higher") + "for 2.3.7.6 or higher") dnac = DNACSDK(params=self._task.args) diff --git a/plugins/action/site_count_v2_info.py b/plugins/action/site_count_v2_info.py new file mode 100644 index 0000000000..8f74ffe04e --- /dev/null +++ b/plugins/action/site_count_v2_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + id=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + id=params.get("id"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='get_site_count_v2', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/site_health_info.py b/plugins/action/site_health_info.py index 7a38d07db8..adf65e0821 100644 --- a/plugins/action/site_health_info.py +++ b/plugins/action/site_health_info.py @@ -25,10 +25,10 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - timestamp=dict(type="str"), siteType=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), + timestamp=dict(type="float"), headers=dict(type="dict"), )) @@ -67,10 +67,10 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( - timestamp=params.get("timestamp"), site_type=params.get("siteType"), offset=params.get("offset"), limit=params.get("limit"), + timestamp=params.get("timestamp"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/site_membership_info.py b/plugins/action/site_membership_info.py index 7c5ec8467f..445783fac6 100644 --- a/plugins/action/site_membership_info.py +++ b/plugins/action/site_membership_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( siteId=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), deviceFamily=dict(type="str"), serialNumber=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/site_v2_info.py b/plugins/action/site_v2_info.py new file mode 100644 index 0000000000..de6f8d2504 --- /dev/null +++ b/plugins/action/site_v2_info.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + groupNameHierarchy=dict(type="str"), + id=dict(type="str"), + type=dict(type="str"), + offset=dict(type="str"), + limit=dict(type="str"), + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + group_name_hierarchy=params.get("groupNameHierarchy"), + id=params.get("id"), + type=params.get("type"), + offset=params.get("offset"), + limit=params.get("limit"), + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="sites", + function='get_site_v2', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/snmpv2_read_community_credential.py b/plugins/action/snmpv2_read_community_credential.py index cda2e0c06e..917e96d3ee 100644 --- a/plugins/action/snmpv2_read_community_credential.py +++ b/plugins/action/snmpv2_read_community_credential.py @@ -89,7 +89,7 @@ def get_object_by_name(self, name): if isinstance(items, dict): if 'response' in items: items = items.get('response') - result = get_dict_result(items, 'description', name) + result = get_dict_result(items, 'description', name) or get_dict_result(items, 'username', name) except Exception: result = None return result @@ -115,7 +115,7 @@ def exists(self): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("username") or self.new_object.get("description") + name = self.new_object.get("description") or self.new_object.get("username") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) diff --git a/plugins/action/snmpv2_write_community_credential.py b/plugins/action/snmpv2_write_community_credential.py index 2ff190d75a..e1244b8689 100644 --- a/plugins/action/snmpv2_write_community_credential.py +++ b/plugins/action/snmpv2_write_community_credential.py @@ -89,7 +89,7 @@ def get_object_by_name(self, name): if isinstance(items, dict): if 'response' in items: items = items.get('response') - result = get_dict_result(items, 'description', name) + result = get_dict_result(items, 'description', name) or get_dict_result(items, 'username', name) except Exception: result = None return result @@ -115,7 +115,7 @@ def exists(self): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("username") or self.new_object.get("description") + name = self.new_object.get("description") or self.new_object.get("username") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) diff --git a/plugins/action/snmpv3_credential.py b/plugins/action/snmpv3_credential.py index 3130877154..480c82e66d 100644 --- a/plugins/action/snmpv3_credential.py +++ b/plugins/action/snmpv3_credential.py @@ -137,7 +137,7 @@ def exists(self): id_exists = False name_exists = False o_id = self.new_object.get("id") - name = self.new_object.get("username") or self.new_object.get("description") + name = self.new_object.get("description") or self.new_object.get("username") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) @@ -167,9 +167,6 @@ def requires_update(self, current_obj): ("snmpMode", "snmpMode"), ("username", "username"), ] - - print("requested_obj: ", requested_obj) - print("current_obj: ", current_obj) # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params # If any does not have eq params, it requires update return any(not dnac_compare_equality(current_obj.get(dnac_param), diff --git a/plugins/action/swim_import_local.py b/plugins/action/swim_import_local.py index b5e3b8a6c9..57946e44e0 100644 --- a/plugins/action/swim_import_local.py +++ b/plugins/action/swim_import_local.py @@ -20,7 +20,6 @@ DNACSDK, dnac_argument_spec, ) -import os # Get common arguements specification argument_spec = dnac_argument_spec() @@ -42,8 +41,7 @@ class ActionModule(ActionBase): def __init__(self, *args, **kwargs): if not ANSIBLE_UTILS_IS_INSTALLED: - raise AnsibleActionFail( - "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") super(ActionModule, self).__init__(*args, **kwargs) self._supports_async = False self._supports_check_mode = False @@ -72,12 +70,8 @@ def get_object(self, params): is_third_party=params.get("isThirdParty"), third_party_vendor=params.get("thirdPartyVendor"), third_party_image_family=params.get("thirdPartyImageFamily"), - third_party_application_type=params.get( - "thirdPartyApplicationType"), + third_party_application_type=params.get("thirdPartyApplicationType"), file_path=params.get("filePath"), - multipart_fields={'file': (os.path.basename(params.get( - "filePath")), open(params.get("filePath"), 'rb'))}, - multipart_monitor_callback=None ) return new_object diff --git a/plugins/action/system_health_info.py b/plugins/action/system_health_info.py index 28683d23b0..6c97265c28 100644 --- a/plugins/action/system_health_info.py +++ b/plugins/action/system_health_info.py @@ -28,8 +28,8 @@ summary=dict(type="bool"), domain=dict(type="str"), subdomain=dict(type="str"), - limit=dict(type="int"), - offset=dict(type="int"), + limit=dict(type="float"), + offset=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/system_performance_historical_info.py b/plugins/action/system_performance_historical_info.py index 287c72245c..27eab29637 100644 --- a/plugins/action/system_performance_historical_info.py +++ b/plugins/action/system_performance_historical_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( kpi=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/system_performance_info.py b/plugins/action/system_performance_info.py index b05406cbf6..3535f9fb6b 100644 --- a/plugins/action/system_performance_info.py +++ b/plugins/action/system_performance_info.py @@ -27,8 +27,8 @@ argument_spec.update(dict( kpi=dict(type="str"), function=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/tag_count_info.py b/plugins/action/tag_count_info.py index 03827a43d8..6766d9a9ed 100644 --- a/plugins/action/tag_count_info.py +++ b/plugins/action/tag_count_info.py @@ -28,7 +28,6 @@ name=dict(type="str"), nameSpace=dict(type="str"), attributeName=dict(type="str"), - level=dict(type="str"), size=dict(type="str"), systemTag=dict(type="str"), headers=dict(type="dict"), @@ -72,7 +71,6 @@ def get_object(self, params): name=params.get("name"), name_space=params.get("nameSpace"), attribute_name=params.get("attributeName"), - level=params.get("level"), size=params.get("size"), system_tag=params.get("systemTag"), headers=params.get("headers"), diff --git a/plugins/action/tag_info.py b/plugins/action/tag_info.py index 773cc8858b..acd9b93b4a 100644 --- a/plugins/action/tag_info.py +++ b/plugins/action/tag_info.py @@ -29,8 +29,8 @@ additionalInfo_nameSpace=dict(type="str"), additionalInfo_attributes=dict(type="str"), level=dict(type="str"), - offset=dict(type="int"), - limit=dict(type="int"), + offset=dict(type="float"), + limit=dict(type="float"), size=dict(type="str"), field=dict(type="str"), sortBy=dict(type="str"), diff --git a/plugins/action/tag_member.py b/plugins/action/tag_member.py index 54ae99e177..54682fc7fc 100644 --- a/plugins/action/tag_member.py +++ b/plugins/action/tag_member.py @@ -32,7 +32,7 @@ argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), payload=dict(type="dict"), - object=dict(type="str"), + memberType=dict(type="list"), id=dict(type="str"), memberId=dict(type="str"), )) @@ -51,17 +51,17 @@ def __init__(self, params, dnac): self.dnac = dnac self.new_object = dict( payload=params.get("payload"), - object=params.get("object"), + memberType=params.get("memberType"), id=params.get("id"), member_id=params.get("memberId"), - member_type=params.get("memberType"), ) def create_params(self): new_object_params = {} new_object_params['payload'] = self.new_object.get('payload') new_object_params['id'] = self.new_object.get('id') - new_object_params['object'] = self.new_object.get('object') + new_object_params['memberType'] = self.new_object.get('memberType') + new_object_params['id'] = self.new_object.get('id') return new_object_params def delete_by_id_params(self): @@ -82,8 +82,7 @@ def get_object_by_id(self, id): items = self.dnac.exec( family="tag", function="get_tag_members_by_id", - params={"id": id, "memberType": self.new_object.get( - 'member_type'), } + params={"id": id} ) if isinstance(items, dict): if 'response' in items: @@ -110,8 +109,7 @@ def exists(self): _id = prev_obj.get("id") _id = _id or prev_obj.get("memberId") if id_exists and name_exists and o_id != _id: - raise InconsistentParameters( - "The 'id' and 'name' params don't refer to the same object") + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") if _id: self.new_object.update(dict(id=_id)) self.new_object.update(dict(member_id=_id)) @@ -124,7 +122,7 @@ def requires_update(self, current_obj): requested_obj = self.new_object obj_params = [ - ("object", "object"), + ("memberType", "memberType"), ("id", "id"), ("memberId", "member_id"), ] @@ -167,8 +165,7 @@ def delete(self): class ActionModule(ActionBase): def __init__(self, *args, **kwargs): if not ANSIBLE_UTILS_IS_INSTALLED: - raise AnsibleActionFail( - "ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") super(ActionModule, self).__init__(*args, **kwargs) self._supports_async = False self._supports_check_mode = False diff --git a/plugins/action/tag_member_count_info.py b/plugins/action/tag_member_count_info.py index f3457c0676..93287adc65 100644 --- a/plugins/action/tag_member_count_info.py +++ b/plugins/action/tag_member_count_info.py @@ -28,7 +28,6 @@ id=dict(type="str"), memberType=dict(type="str"), memberAssociationType=dict(type="str"), - level=dict(type="str"), headers=dict(type="dict"), )) @@ -70,7 +69,6 @@ def get_object(self, params): id=params.get("id"), member_type=params.get("memberType"), member_association_type=params.get("memberAssociationType"), - level=params.get("level"), headers=params.get("headers"), ) return new_object diff --git a/plugins/action/tag_member_info.py b/plugins/action/tag_member_info.py index e90f5551ec..36c3640864 100644 --- a/plugins/action/tag_member_info.py +++ b/plugins/action/tag_member_info.py @@ -27,8 +27,8 @@ argument_spec.update(dict( id=dict(type="str"), memberType=dict(type="str"), - offset=dict(type="str"), - limit=dict(type="str"), + offset=dict(type="float"), + limit=dict(type="float"), memberAssociationType=dict(type="str"), level=dict(type="str"), headers=dict(type="dict"), diff --git a/plugins/action/tag_membership.py b/plugins/action/tag_membership.py index 451501f948..bb7b8a8b74 100644 --- a/plugins/action/tag_membership.py +++ b/plugins/action/tag_membership.py @@ -25,7 +25,7 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - memberToTags=dict(type="list"), + memberToTags=dict(type="dict"), memberType=dict(type="str"), )) @@ -79,7 +79,7 @@ def run(self, tmp=None, task_vars=None): response = dnac.exec( family="tag", - function='updates_tag_membership', + function='update_tag_membership', op_modifies=True, params=self.get_object(self._task.args), ) diff --git a/plugins/action/topology_network_health_info.py b/plugins/action/topology_network_health_info.py index d8a8e75da3..5b64f0398e 100644 --- a/plugins/action/topology_network_health_info.py +++ b/plugins/action/topology_network_health_info.py @@ -25,7 +25,7 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - timestamp=dict(type="str"), + timestamp=dict(type="float"), headers=dict(type="dict"), )) diff --git a/plugins/action/transit_peer_network.py b/plugins/action/transit_peer_network.py index a15848230a..cbcfe89103 100644 --- a/plugins/action/transit_peer_network.py +++ b/plugins/action/transit_peer_network.py @@ -23,7 +23,7 @@ get_dict_result, ) from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( - AnsibleSDAException, + InconsistentParameters, ) # Get common arguments specification @@ -74,7 +74,7 @@ def delete_all_params(self): new_object_params['transit_peer_network_name'] = self.new_object.get('transit_peer_network_name') return new_object_params - def get_object_by_name(self, name, is_absent=False): + def get_object_by_name(self, name): result = None # NOTE: Does not have a get by name method, using get all try: @@ -86,15 +86,8 @@ def get_object_by_name(self, name, is_absent=False): if isinstance(items, dict): if 'response' in items: items = items.get('response') - if isinstance(items, dict) and items.get("status") == "failed": - if is_absent: - raise AnsibleSDAException(response=items) - result = None - return result result = get_dict_result(items, 'name', name) except Exception: - if is_absent: - raise result = None return result @@ -103,10 +96,25 @@ def get_object_by_id(self, id): # NOTE: Does not have a get by id method or it is in another action return result - def exists(self, is_absent=False): - name = self.new_object.get("transitPeerNetworkName") - prev_obj = self.get_object_by_name(name, is_absent=is_absent) - it_exists = prev_obj is not None and isinstance(prev_obj, dict) and prev_obj.get("status") != "failed" + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) return (it_exists, prev_obj) def requires_update(self, current_obj): @@ -198,7 +206,7 @@ def run(self, tmp=None, task_vars=None): response = obj.create() dnac.object_created() elif state == "absent": - (obj_exists, prev_obj) = obj.exists(is_absent=True) + (obj_exists, prev_obj) = obj.exists() if obj_exists: response = obj.delete() dnac.object_deleted() diff --git a/plugins/action/user.py b/plugins/action/user.py index 1896e57ffb..ea9b6930d5 100644 --- a/plugins/action/user.py +++ b/plugins/action/user.py @@ -30,7 +30,7 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - state=dict(type="str", default="present", choices=["present"]), + state=dict(type="str", default="present", choices=["present", "absent"]), firstName=dict(type="str"), lastName=dict(type="str"), username=dict(type="str"), @@ -41,6 +41,8 @@ )) required_if = [ + ("state", "present", ["userId"], True), + ("state", "absent", ["userId"], True), ] required_one_of = [] mutually_exclusive = [] @@ -58,12 +60,15 @@ def __init__(self, params, dnac): email=params.get("email"), roleList=params.get("roleList"), userId=params.get("userId"), + user_id=params.get("userId"), ) def get_all_params(self, name=None, id=None): new_object_params = {} new_object_params['invoke_source'] = self.new_object.get('invokeSource') or \ self.new_object.get('invoke_source') + new_object_params['auth_source'] = self.new_object.get('authSource') or \ + self.new_object.get('auth_source') return new_object_params def create_params(self): @@ -76,6 +81,11 @@ def create_params(self): new_object_params['roleList'] = self.new_object.get('roleList') return new_object_params + def delete_by_id_params(self): + new_object_params = {} + new_object_params['user_id'] = self.new_object.get('user_id') + return new_object_params + def update_all_params(self): new_object_params = {} new_object_params['firstName'] = self.new_object.get('firstName') @@ -88,10 +98,10 @@ def update_all_params(self): def get_object_by_name(self, name): result = None - # NOTE: Does not have a get by name method, using get all + # NOTE: Does not have a get by name method or it is in another action try: items = self.dnac.exec( - family="user_and_roles", + family="userand_roles", function="get_users_api", params=self.get_all_params(name=name), ) @@ -106,13 +116,26 @@ def get_object_by_name(self, name): def get_object_by_id(self, id): result = None # NOTE: Does not have a get by id method or it is in another action + try: + items = self.dnac.exec( + family="userand_roles", + function="get_users_api", + params=self.get_all_params(id=id), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'id', id) + except Exception: + result = None return result def exists(self): - prev_obj = None id_exists = False name_exists = False + prev_obj = None o_id = self.new_object.get("id") + o_id = o_id or self.new_object.get("user_id") name = self.new_object.get("name") if o_id: prev_obj = self.get_object_by_id(o_id) @@ -122,10 +145,12 @@ def exists(self): name_exists = prev_obj is not None and isinstance(prev_obj, dict) if name_exists: _id = prev_obj.get("id") + _id = _id or prev_obj.get("userId") if id_exists and name_exists and o_id != _id: raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") if _id: self.new_object.update(dict(id=_id)) + self.new_object.update(dict(user_id=_id)) it_exists = prev_obj is not None and isinstance(prev_obj, dict) return (it_exists, prev_obj) @@ -139,8 +164,9 @@ def requires_update(self, current_obj): ("email", "email"), ("roleList", "roleList"), ("userId", "userId"), + ("userId", "user_id"), ] - # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params # If any does not have eq params, it requires update return any(not dnac_compare_equality(current_obj.get(dnac_param), requested_obj.get(ansible_param)) @@ -148,7 +174,7 @@ def requires_update(self, current_obj): def create(self): result = self.dnac.exec( - family="user_and_roles", + family="userand_roles", function="add_user_api", params=self.create_params(), op_modifies=True, @@ -160,13 +186,33 @@ def update(self): name = self.new_object.get("name") result = None result = self.dnac.exec( - family="user_and_roles", + family="userand_roles", function="update_user_api", params=self.update_all_params(), op_modifies=True, ) return result + def delete(self): + id = self.new_object.get("id") + id = id or self.new_object.get("user_id") + name = self.new_object.get("name") + result = None + if not id: + prev_obj_name = self.get_object_by_name(name) + id_ = None + if prev_obj_name: + id_ = prev_obj_name.get("id") + id_ = id_ or prev_obj_name.get("userId") + if id_: + self.new_object.update(dict(user_id=id_)) + result = self.dnac.exec( + family="userand_roles", + function="delete_user_api", + params=self.delete_by_id_params(), + ) + return result + class ActionModule(ActionBase): def __init__(self, *args, **kwargs): @@ -207,6 +253,7 @@ def run(self, tmp=None, task_vars=None): state = self._task.args.get("state") response = None + if state == "present": (obj_exists, prev_obj) = obj.exists() if obj_exists: @@ -220,6 +267,14 @@ def run(self, tmp=None, task_vars=None): response = obj.create() dnac.object_created() + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + self._result.update(dict(dnac_response=response)) self._result.update(dnac.exit_json()) return self._result diff --git a/plugins/action/user_info.py b/plugins/action/user_info.py index 7a5906fcce..f923914062 100644 --- a/plugins/action/user_info.py +++ b/plugins/action/user_info.py @@ -26,6 +26,7 @@ # Add arguments specific for this module argument_spec.update(dict( invokeSource=dict(type="str"), + authSource=dict(type="str"), headers=dict(type="dict"), )) @@ -65,6 +66,7 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( invoke_source=params.get("invokeSource"), + auth_source=params.get("authSource"), headers=params.get("headers"), ) return new_object @@ -80,7 +82,7 @@ def run(self, tmp=None, task_vars=None): dnac = DNACSDK(params=self._task.args) response = dnac.exec( - family="user_and_roles", + family="userand_roles", function='get_users_api', params=self.get_object(self._task.args), ) diff --git a/plugins/action/users_external_authentication.py b/plugins/action/users_external_authentication.py new file mode 100644 index 0000000000..2c5ab3af7c --- /dev/null +++ b/plugins/action/users_external_authentication.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present"]), + enable=dict(type="bool"), +)) + +required_if = [ +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class UsersExternalAuthentication(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + enable=params.get("enable"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['enable'] = self.new_object.get('enable') + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method, using get all + try: + items = self.dnac.exec( + family="userand_roles", + function="get_external_authentication_setting_api", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("enable", "enable"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="userand_roles", + function="manage_external_authentication_setting_api", + params=self.create_params(), + op_modifies=True, + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = UsersExternalAuthentication(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + dnac.object_present_and_different() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/users_external_authentication_info.py b/plugins/action/users_external_authentication_info.py new file mode 100644 index 0000000000..7332d1681a --- /dev/null +++ b/plugins/action/users_external_authentication_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="userand_roles", + function='get_external_authentication_setting_api', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/users_external_servers_aaa_attribute.py b/plugins/action/users_external_servers_aaa_attribute.py new file mode 100644 index 0000000000..ef9c3aceb2 --- /dev/null +++ b/plugins/action/users_external_servers_aaa_attribute.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, + dnac_compare_equality, + get_dict_result, +) +from ansible_collections.cisco.dnac.plugins.plugin_utils.exceptions import ( + InconsistentParameters, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + state=dict(type="str", default="present", choices=["present", "absent"]), + attributeName=dict(type="str"), +)) + +required_if = [ +] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class UsersExternalServersAaaAttribute(object): + def __init__(self, params, dnac): + self.dnac = dnac + self.new_object = dict( + attributeName=params.get("attributeName"), + ) + + def get_all_params(self, name=None, id=None): + new_object_params = {} + return new_object_params + + def create_params(self): + new_object_params = {} + new_object_params['attributeName'] = self.new_object.get('attributeName') + return new_object_params + + def delete_all_params(self): + new_object_params = {} + return new_object_params + + def get_object_by_name(self, name): + result = None + # NOTE: Does not have a get by name method, using get all + try: + items = self.dnac.exec( + family="userand_roles", + function="get_a_a_a_attribute_api", + params=self.get_all_params(name=name), + ) + if isinstance(items, dict): + if 'response' in items: + items = items.get('response') + result = get_dict_result(items, 'name', name) + except Exception: + result = None + return result + + def get_object_by_id(self, id): + result = None + # NOTE: Does not have a get by id method or it is in another action + return result + + def exists(self): + prev_obj = None + id_exists = False + name_exists = False + o_id = self.new_object.get("id") + name = self.new_object.get("name") + if o_id: + prev_obj = self.get_object_by_id(o_id) + id_exists = prev_obj is not None and isinstance(prev_obj, dict) + if not id_exists and name: + prev_obj = self.get_object_by_name(name) + name_exists = prev_obj is not None and isinstance(prev_obj, dict) + if name_exists: + _id = prev_obj.get("id") + if id_exists and name_exists and o_id != _id: + raise InconsistentParameters("The 'id' and 'name' params don't refer to the same object") + if _id: + self.new_object.update(dict(id=_id)) + it_exists = prev_obj is not None and isinstance(prev_obj, dict) + return (it_exists, prev_obj) + + def requires_update(self, current_obj): + requested_obj = self.new_object + + obj_params = [ + ("attributeName", "attributeName"), + ] + # Method 1. Params present in request (Ansible) obj are the same as the current (ISE) params + # If any does not have eq params, it requires update + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def create(self): + result = self.dnac.exec( + family="userand_roles", + function="add_and_update_a_a_a_attribute_api", + params=self.create_params(), + op_modifies=True, + ) + return result + + def delete(self): + id = self.new_object.get("id") + name = self.new_object.get("name") + result = None + result = self.dnac.exec( + family="userand_roles", + function="delete_a_a_a_attribute_api", + params=self.delete_all_params(), + ) + return result + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(self._task.args) + obj = UsersExternalServersAaaAttribute(self._task.args, dnac) + + state = self._task.args.get("state") + + response = None + if state == "present": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + if obj.requires_update(prev_obj): + response = prev_obj + dnac.object_present_and_different() + else: + response = prev_obj + dnac.object_already_present() + else: + response = obj.create() + dnac.object_created() + elif state == "absent": + (obj_exists, prev_obj) = obj.exists() + if obj_exists: + response = obj.delete() + dnac.object_deleted() + else: + dnac.object_already_absent() + + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/users_external_servers_aaa_attribute_info.py b/plugins/action/users_external_servers_aaa_attribute_info.py new file mode 100644 index 0000000000..d0cc29d0a5 --- /dev/null +++ b/plugins/action/users_external_servers_aaa_attribute_info.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguments specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + headers=dict(type="dict"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = True + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + headers=params.get("headers"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + self._result.update(dict(dnac_response={})) + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="userand_roles", + function='get_a_a_a_attribute_api', + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/wireless_accespoint_configuration.py b/plugins/action/wireless_accespoint_configuration.py index f99e312edb..45b2e78225 100644 --- a/plugins/action/wireless_accespoint_configuration.py +++ b/plugins/action/wireless_accespoint_configuration.py @@ -30,8 +30,6 @@ adminStatus=dict(type="bool"), configureApMode=dict(type="bool"), apMode=dict(type="int"), - configureApHeight=dict(type="bool"), - apHeight=dict(type="int"), configureFailoverPriority=dict(type="bool"), failoverPriority=dict(type="int"), configureLedStatus=dict(type="bool"), @@ -48,6 +46,7 @@ tertiaryControllerName=dict(type="str"), tertiaryIpAddress=dict(type="dict"), radioConfigurations=dict(type="list"), + isAssignedSiteAsLocation=dict(type="bool"), )) required_if = [] @@ -90,8 +89,6 @@ def get_object(self, params): adminStatus=params.get("adminStatus"), configureApMode=params.get("configureApMode"), apMode=params.get("apMode"), - configureApHeight=params.get("configureApHeight"), - apHeight=params.get("apHeight"), configureFailoverPriority=params.get("configureFailoverPriority"), failoverPriority=params.get("failoverPriority"), configureLedStatus=params.get("configureLedStatus"), @@ -108,6 +105,7 @@ def get_object(self, params): tertiaryControllerName=params.get("tertiaryControllerName"), tertiaryIpAddress=params.get("tertiaryIpAddress"), radioConfigurations=params.get("radioConfigurations"), + isAssignedSiteAsLocation=params.get("isAssignedSiteAsLocation"), ) return new_object @@ -121,7 +119,7 @@ def run(self, tmp=None, task_vars=None): response = dnac.exec( family="wireless", - function='configure_access_points', + function='configure_access_points_v1', op_modifies=True, params=self.get_object(self._task.args), ) diff --git a/plugins/action/wireless_accesspoint_configuration_create.py b/plugins/action/wireless_accesspoint_configuration_create.py new file mode 100644 index 0000000000..8778b67576 --- /dev/null +++ b/plugins/action/wireless_accesspoint_configuration_create.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import (absolute_import, division, print_function) +__metaclass__ = type +from ansible.plugins.action import ActionBase +try: + from ansible_collections.ansible.utils.plugins.module_utils.common.argspec_validate import ( + AnsibleArgSpecValidator, + ) +except ImportError: + ANSIBLE_UTILS_IS_INSTALLED = False +else: + ANSIBLE_UTILS_IS_INSTALLED = True +from ansible.errors import AnsibleActionFail +from ansible_collections.cisco.dnac.plugins.plugin_utils.dnac import ( + DNACSDK, + dnac_argument_spec, +) + +# Get common arguements specification +argument_spec = dnac_argument_spec() +# Add arguments specific for this module +argument_spec.update(dict( + apList=dict(type="list"), + configureAdminStatus=dict(type="bool"), + adminStatus=dict(type="bool"), + configureApMode=dict(type="bool"), + apMode=dict(type="int"), + configureFailoverPriority=dict(type="bool"), + failoverPriority=dict(type="int"), + configureLedStatus=dict(type="bool"), + ledStatus=dict(type="bool"), + configureLedBrightnessLevel=dict(type="bool"), + ledBrightnessLevel=dict(type="int"), + configureLocation=dict(type="bool"), + location=dict(type="str"), + configureHAController=dict(type="bool"), + primaryControllerName=dict(type="str"), + primaryIpAddress=dict(type="dict"), + secondaryControllerName=dict(type="str"), + secondaryIpAddress=dict(type="dict"), + tertiaryControllerName=dict(type="str"), + tertiaryIpAddress=dict(type="dict"), + radioConfigurations=dict(type="list"), + configureCleanAirSI24Ghz=dict(type="bool"), + cleanAirSI24=dict(type="bool"), + configureCleanAirSI5Ghz=dict(type="bool"), + cleanAirSI5=dict(type="bool"), + configureCleanAirSI6Ghz=dict(type="bool"), + cleanAirSI6=dict(type="bool"), + isAssignedSiteAsLocation=dict(type="bool"), +)) + +required_if = [] +required_one_of = [] +mutually_exclusive = [] +required_together = [] + + +class ActionModule(ActionBase): + def __init__(self, *args, **kwargs): + if not ANSIBLE_UTILS_IS_INSTALLED: + raise AnsibleActionFail("ansible.utils is not installed. Execute 'ansible-galaxy collection install ansible.utils'") + super(ActionModule, self).__init__(*args, **kwargs) + self._supports_async = False + self._supports_check_mode = False + self._result = None + + # Checks the supplied parameters against the argument spec for this module + def _check_argspec(self): + aav = AnsibleArgSpecValidator( + data=self._task.args, + schema=dict(argument_spec=argument_spec), + schema_format="argspec", + schema_conditionals=dict( + required_if=required_if, + required_one_of=required_one_of, + mutually_exclusive=mutually_exclusive, + required_together=required_together, + ), + name=self._task.action, + ) + valid, errors, self._task.args = aav.validate() + if not valid: + raise AnsibleActionFail(errors) + + def get_object(self, params): + new_object = dict( + apList=params.get("apList"), + configureAdminStatus=params.get("configureAdminStatus"), + adminStatus=params.get("adminStatus"), + configureApMode=params.get("configureApMode"), + apMode=params.get("apMode"), + configureFailoverPriority=params.get("configureFailoverPriority"), + failoverPriority=params.get("failoverPriority"), + configureLedStatus=params.get("configureLedStatus"), + ledStatus=params.get("ledStatus"), + configureLedBrightnessLevel=params.get("configureLedBrightnessLevel"), + ledBrightnessLevel=params.get("ledBrightnessLevel"), + configureLocation=params.get("configureLocation"), + location=params.get("location"), + configureHAController=params.get("configureHAController"), + primaryControllerName=params.get("primaryControllerName"), + primaryIpAddress=params.get("primaryIpAddress"), + secondaryControllerName=params.get("secondaryControllerName"), + secondaryIpAddress=params.get("secondaryIpAddress"), + tertiaryControllerName=params.get("tertiaryControllerName"), + tertiaryIpAddress=params.get("tertiaryIpAddress"), + radioConfigurations=params.get("radioConfigurations"), + configureCleanAirSI24Ghz=params.get("configureCleanAirSI24Ghz"), + cleanAirSI24=params.get("cleanAirSI24"), + configureCleanAirSI5Ghz=params.get("configureCleanAirSI5Ghz"), + cleanAirSI5=params.get("cleanAirSI5"), + configureCleanAirSI6Ghz=params.get("configureCleanAirSI6Ghz"), + cleanAirSI6=params.get("cleanAirSI6"), + isAssignedSiteAsLocation=params.get("isAssignedSiteAsLocation"), + ) + return new_object + + def run(self, tmp=None, task_vars=None): + self._task.diff = False + self._result = super(ActionModule, self).run(tmp, task_vars) + self._result["changed"] = False + self._check_argspec() + + dnac = DNACSDK(params=self._task.args) + + response = dnac.exec( + family="wireless", + function='configure_access_points_v2', + op_modifies=True, + params=self.get_object(self._task.args), + ) + self._result.update(dict(dnac_response=response)) + self._result.update(dnac.exit_json()) + return self._result diff --git a/plugins/action/wireless_dynamic_interface.py b/plugins/action/wireless_dynamic_interface.py index 51f458f572..416d665a0b 100644 --- a/plugins/action/wireless_dynamic_interface.py +++ b/plugins/action/wireless_dynamic_interface.py @@ -32,13 +32,10 @@ argument_spec.update(dict( state=dict(type="str", default="present", choices=["present", "absent"]), interfaceName=dict(type="str"), - vlanId=dict(type="int"), - headers=dict(type="dict"), + vlanId=dict(type="float"), )) required_if = [ - ("state", "present", ["interfaceName"], True), - ("state", "absent", ["interfaceName"], True), ] required_one_of = [] mutually_exclusive = [] @@ -51,7 +48,6 @@ def __init__(self, params, dnac): self.new_object = dict( interfaceName=params.get("interfaceName"), vlanId=params.get("vlanId"), - headers=params.get("headers"), interface_name=params.get("interfaceName"), ) @@ -66,7 +62,7 @@ def create_params(self): new_object_params['vlanId'] = self.new_object.get('vlanId') return new_object_params - def delete_by_name_params(self): + def delete_all_params(self): new_object_params = {} new_object_params['interface_name'] = self.new_object.get('interface_name') new_object_params['headers'] = self.new_object.get('headers') @@ -100,18 +96,12 @@ def exists(self): name_exists = False o_id = self.new_object.get("id") name = self.new_object.get("name") - name = name or self.new_object.get("interface_name") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) if not id_exists and name: prev_obj = self.get_object_by_name(name) name_exists = prev_obj is not None and isinstance(prev_obj, dict) - if id_exists: - _name = prev_obj.get("name") - _name = _name or prev_obj.get("interfaceName") - if _name: - self.new_object.update(dict(interface_name=_name)) if name_exists: _id = prev_obj.get("id") if id_exists and name_exists and o_id != _id: @@ -147,20 +137,11 @@ def create(self): def delete(self): id = self.new_object.get("id") name = self.new_object.get("name") - name = name or self.new_object.get("interface_name") result = None - if not name: - prev_obj_id = self.get_object_by_id(id) - name_ = None - if prev_obj_id: - name_ = prev_obj_id.get("name") - name_ = name_ or prev_obj_id.get("interfaceName") - if name_: - self.new_object.update(dict(interface_name=name_)) result = self.dnac.exec( family="wireless", function="delete_dynamic_interface", - params=self.delete_by_name_params(), + params=self.delete_all_params(), ) return result diff --git a/plugins/action/wireless_enterprise_ssid.py b/plugins/action/wireless_enterprise_ssid.py index 7e2d129c06..4773b9bcca 100644 --- a/plugins/action/wireless_enterprise_ssid.py +++ b/plugins/action/wireless_enterprise_ssid.py @@ -50,6 +50,19 @@ enableNeighborList=dict(type="bool"), mfpClientProtection=dict(type="str"), nasOptions=dict(type="list"), + profileName=dict(type="str"), + policyProfileName=dict(type="str"), + aaaOverride=dict(type="bool"), + coverageHoleDetectionEnable=dict(type="bool"), + protectedManagementFrame=dict(type="str"), + multiPSKSettings=dict(type="list"), + clientRateLimit=dict(type="float"), + authKeyMgmt=dict(type="list"), + rsnCipherSuiteGcmp256=dict(type="bool"), + rsnCipherSuiteCcmp256=dict(type="bool"), + rsnCipherSuiteGcmp128=dict(type="bool"), + ghz6PolicyClientSteering=dict(type="bool"), + ghz24Policy=dict(type="str"), ssidName=dict(type="str"), )) @@ -85,6 +98,19 @@ def __init__(self, params, dnac): enableNeighborList=params.get("enableNeighborList"), mfpClientProtection=params.get("mfpClientProtection"), nasOptions=params.get("nasOptions"), + profileName=params.get("profileName"), + policyProfileName=params.get("policyProfileName"), + aaaOverride=params.get("aaaOverride"), + coverageHoleDetectionEnable=params.get("coverageHoleDetectionEnable"), + protectedManagementFrame=params.get("protectedManagementFrame"), + multiPSKSettings=params.get("multiPSKSettings"), + clientRateLimit=params.get("clientRateLimit"), + authKeyMgmt=params.get("authKeyMgmt"), + rsnCipherSuiteGcmp256=params.get("rsnCipherSuiteGcmp256"), + rsnCipherSuiteCcmp256=params.get("rsnCipherSuiteCcmp256"), + rsnCipherSuiteGcmp128=params.get("rsnCipherSuiteGcmp128"), + ghz6PolicyClientSteering=params.get("ghz6PolicyClientSteering"), + ghz24Policy=params.get("ghz24Policy"), ssid_name=params.get("ssidName"), ) @@ -115,6 +141,19 @@ def create_params(self): new_object_params['enableNeighborList'] = self.new_object.get('enableNeighborList') new_object_params['mfpClientProtection'] = self.new_object.get('mfpClientProtection') new_object_params['nasOptions'] = self.new_object.get('nasOptions') + new_object_params['profileName'] = self.new_object.get('profileName') + new_object_params['policyProfileName'] = self.new_object.get('policyProfileName') + new_object_params['aaaOverride'] = self.new_object.get('aaaOverride') + new_object_params['coverageHoleDetectionEnable'] = self.new_object.get('coverageHoleDetectionEnable') + new_object_params['protectedManagementFrame'] = self.new_object.get('protectedManagementFrame') + new_object_params['multiPSKSettings'] = self.new_object.get('multiPSKSettings') + new_object_params['clientRateLimit'] = self.new_object.get('clientRateLimit') + new_object_params['authKeyMgmt'] = self.new_object.get('authKeyMgmt') + new_object_params['rsnCipherSuiteGcmp256'] = self.new_object.get('rsnCipherSuiteGcmp256') + new_object_params['rsnCipherSuiteCcmp256'] = self.new_object.get('rsnCipherSuiteCcmp256') + new_object_params['rsnCipherSuiteGcmp128'] = self.new_object.get('rsnCipherSuiteGcmp128') + new_object_params['ghz6PolicyClientSteering'] = self.new_object.get('ghz6PolicyClientSteering') + new_object_params['ghz24Policy'] = self.new_object.get('ghz24Policy') return new_object_params def delete_by_name_params(self): @@ -143,6 +182,19 @@ def update_all_params(self): new_object_params['enableNeighborList'] = self.new_object.get('enableNeighborList') new_object_params['mfpClientProtection'] = self.new_object.get('mfpClientProtection') new_object_params['nasOptions'] = self.new_object.get('nasOptions') + new_object_params['profileName'] = self.new_object.get('profileName') + new_object_params['policyProfileName'] = self.new_object.get('policyProfileName') + new_object_params['aaaOverride'] = self.new_object.get('aaaOverride') + new_object_params['coverageHoleDetectionEnable'] = self.new_object.get('coverageHoleDetectionEnable') + new_object_params['protectedManagementFrame'] = self.new_object.get('protectedManagementFrame') + new_object_params['multiPSKSettings'] = self.new_object.get('multiPSKSettings') + new_object_params['clientRateLimit'] = self.new_object.get('clientRateLimit') + new_object_params['authKeyMgmt'] = self.new_object.get('authKeyMgmt') + new_object_params['rsnCipherSuiteGcmp256'] = self.new_object.get('rsnCipherSuiteGcmp256') + new_object_params['rsnCipherSuiteCcmp256'] = self.new_object.get('rsnCipherSuiteCcmp256') + new_object_params['rsnCipherSuiteGcmp128'] = self.new_object.get('rsnCipherSuiteGcmp128') + new_object_params['ghz6PolicyClientSteering'] = self.new_object.get('ghz6PolicyClientSteering') + new_object_params['ghz24Policy'] = self.new_object.get('ghz24Policy') return new_object_params def get_object_by_name(self, name): @@ -231,6 +283,19 @@ def requires_update(self, current_obj): ("enableNeighborList", "enableNeighborList"), ("mfpClientProtection", "mfpClientProtection"), ("nasOptions", "nasOptions"), + ("profileName", "profileName"), + ("policyProfileName", "policyProfileName"), + ("aaaOverride", "aaaOverride"), + ("coverageHoleDetectionEnable", "coverageHoleDetectionEnable"), + ("protectedManagementFrame", "protectedManagementFrame"), + ("multiPSKSettings", "multiPSKSettings"), + ("clientRateLimit", "clientRateLimit"), + ("authKeyMgmt", "authKeyMgmt"), + ("rsnCipherSuiteGcmp256", "rsnCipherSuiteGcmp256"), + ("rsnCipherSuiteCcmp256", "rsnCipherSuiteCcmp256"), + ("rsnCipherSuiteGcmp128", "rsnCipherSuiteGcmp128"), + ("ghz6PolicyClientSteering", "ghz6PolicyClientSteering"), + ("ghz24Policy", "ghz24Policy"), ("ssidName", "ssid_name"), ] # Method 1. Params present in request (Ansible) obj are the same as the current (DNAC) params diff --git a/plugins/action/wireless_profile.py b/plugins/action/wireless_profile.py index b2b22fb8e4..acf011b1ea 100644 --- a/plugins/action/wireless_profile.py +++ b/plugins/action/wireless_profile.py @@ -53,7 +53,7 @@ def __init__(self, params, dnac): def get_all_params(self, name=None, id=None): new_object_params = {} - new_object_params['profile_name'] = name or self.new_object.get('wireless_profile_name') + new_object_params['profile_name'] = self.new_object.get('wireless_profile_name') return new_object_params def create_params(self): @@ -103,9 +103,6 @@ def exists(self): o_id = self.new_object.get("id") name = self.new_object.get("name") name = name or self.new_object.get("wireless_profile_name") - profile_details = self.new_object.get("profileDetails") - if profile_details and profile_details.get("name"): - name = name or profile_details.get("name") if o_id: prev_obj = self.get_object_by_id(o_id) id_exists = prev_obj is not None and isinstance(prev_obj, dict) diff --git a/plugins/action/wireless_psk_override.py b/plugins/action/wireless_psk_override.py index 6fe372d58b..1bf29f6e69 100644 --- a/plugins/action/wireless_psk_override.py +++ b/plugins/action/wireless_psk_override.py @@ -25,7 +25,10 @@ argument_spec = dnac_argument_spec() # Add arguments specific for this module argument_spec.update(dict( - payload=dict(type="list"), + ssidName=dict(type="str"), + site=dict(type="str"), + passPhrase=dict(type="str"), + wlanProfileName=dict(type="str"), )) required_if = [] @@ -63,7 +66,10 @@ def _check_argspec(self): def get_object(self, params): new_object = dict( - payload=params.get("payload"), + ssidName=params.get("ssidName"), + site=params.get("site"), + passPhrase=params.get("passPhrase"), + wlanProfileName=params.get("wlanProfileName"), ) return new_object diff --git a/plugins/action/wireless_sensor_test_results_info.py b/plugins/action/wireless_sensor_test_results_info.py index 5948fad3cb..26ff29cd87 100644 --- a/plugins/action/wireless_sensor_test_results_info.py +++ b/plugins/action/wireless_sensor_test_results_info.py @@ -26,8 +26,8 @@ # Add arguments specific for this module argument_spec.update(dict( siteId=dict(type="str"), - startTime=dict(type="int"), - endTime=dict(type="int"), + startTime=dict(type="float"), + endTime=dict(type="float"), testFailureBy=dict(type="str"), headers=dict(type="dict"), )) diff --git a/plugins/doc_fragments/module.py b/plugins/doc_fragments/module.py index 6c92fb75fc..01286a6227 100644 --- a/plugins/doc_fragments/module.py +++ b/plugins/doc_fragments/module.py @@ -43,7 +43,7 @@ class ModuleDocFragment(object): description: - Informs the SDK which version of Cisco DNA Center to use. type: str - default: 2.3.5.3 + default: 2.3.7.6 dnac_debug: description: - Flag for Cisco DNA Center SDK to enable debugging. diff --git a/plugins/doc_fragments/module_info.py b/plugins/doc_fragments/module_info.py index 7ac68f449e..507ef06082 100644 --- a/plugins/doc_fragments/module_info.py +++ b/plugins/doc_fragments/module_info.py @@ -43,7 +43,7 @@ class ModuleDocFragment(object): description: - Informs the SDK which version of Cisco DNA Center to use. type: str - default: 2.3.5.3 + default: 2.3.7.6 dnac_debug: description: - Flag for Cisco DNA Center SDK to enable debugging. diff --git a/plugins/module_utils/dnac.py b/plugins/module_utils/dnac.py index 1d4b804cd0..2ec0d2ce0a 100644 --- a/plugins/module_utils/dnac.py +++ b/plugins/module_utils/dnac.py @@ -521,7 +521,11 @@ def is_path_exists(self, file_path): True/False (bool) - True if the file path exists, else False. """ - if not os.path.exists(file_path): + current_working_directory = os.getcwd() + final_file_path = os.path.join(current_working_directory, file_path) + self.log(str(final_file_path)) + if not os.path.exists(final_file_path): + self.log("The specified path '{0}' is not valid. Please provide a valid path.".format(final_file_path), "ERROR") return False return True diff --git a/plugins/modules/accesspoint_configuration_details_by_task_id_info.py b/plugins/modules/accesspoint_configuration_details_by_task_id_info.py index 642034e5ca..165f9596dd 100644 --- a/plugins/modules/accesspoint_configuration_details_by_task_id_info.py +++ b/plugins/modules/accesspoint_configuration_details_by_task_id_info.py @@ -11,7 +11,7 @@ description: - Get Accesspoint Configuration Details By Task Id by id. - Users can query the access point configuration result using this intent API. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -24,8 +24,8 @@ - Task_id path parameter. Task id information of ap config. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless GetAccessPointConfigurationTaskResult description: Complete reference of the GetAccessPointConfigurationTaskResult API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/app_policy_default_info.py b/plugins/modules/app_policy_default_info.py index 921f7a095f..c14daa7e42 100644 --- a/plugins/modules/app_policy_default_info.py +++ b/plugins/modules/app_policy_default_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicyDefault description: Complete reference of the GetApplicationPolicyDefault API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/app_policy_info.py b/plugins/modules/app_policy_info.py index 3479d1edee..27bc0c30b2 100644 --- a/plugins/modules/app_policy_info.py +++ b/plugins/modules/app_policy_info.py @@ -24,8 +24,8 @@ - PolicyScope query parameter. Policy scope name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicy description: Complete reference of the GetApplicationPolicy API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/app_policy_intent_create.py b/plugins/modules/app_policy_intent_create.py index fd487ca0c4..09074c41d6 100644 --- a/plugins/modules/app_policy_intent_create.py +++ b/plugins/modules/app_policy_intent_create.py @@ -28,7 +28,8 @@ elements: dict suboptions: groupId: - description: Group id. + description: The site(s) ID where the Application QoS Policy will be + deployed. elements: str type: list ssid: @@ -124,7 +125,8 @@ elements: dict suboptions: groupId: - description: Group id. + description: The site(s) ID where the Application QoS Policy will be + deployed. elements: str type: list id: @@ -226,8 +228,8 @@ type: dict type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy ApplicationPolicyIntent description: Complete reference of the ApplicationPolicyIntent API. @@ -314,7 +316,6 @@ - idRef: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/app_policy_queuing_profile.py b/plugins/modules/app_policy_queuing_profile.py index 9260ffbf52..893e799ce5 100644 --- a/plugins/modules/app_policy_queuing_profile.py +++ b/plugins/modules/app_policy_queuing_profile.py @@ -75,7 +75,7 @@ type: str type: list type: - description: Type. + description: The allowed clause types are BANDWIDTH, DSCP_CUSTOMIZATION. type: str type: list description: @@ -89,8 +89,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy CreateApplicationPolicyQueuingProfile description: Complete reference of the CreateApplicationPolicyQueuingProfile API. @@ -183,7 +183,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/app_policy_queuing_profile_count_info.py b/plugins/modules/app_policy_queuing_profile_count_info.py index 2a3b2c4dff..ef68ca49b3 100644 --- a/plugins/modules/app_policy_queuing_profile_count_info.py +++ b/plugins/modules/app_policy_queuing_profile_count_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicyQueuingProfileCount description: Complete reference of the GetApplicationPolicyQueuingProfileCount API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/app_policy_queuing_profile_info.py b/plugins/modules/app_policy_queuing_profile_info.py index bb89873a67..ac351cc887 100644 --- a/plugins/modules/app_policy_queuing_profile_info.py +++ b/plugins/modules/app_policy_queuing_profile_info.py @@ -24,8 +24,8 @@ - Name query parameter. Queuing profile name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationPolicyQueuingProfile description: Complete reference of the GetApplicationPolicyQueuingProfile API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/application_policy_application_set.py b/plugins/modules/application_policy_application_set.py new file mode 100644 index 0000000000..512eebe307 --- /dev/null +++ b/plugins/modules/application_policy_application_set.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: application_policy_application_set +short_description: Resource module for Application Policy Application Set +description: +- Manage operations create and delete of the resource Application Policy Application Set. +- Create new custom application set/s. +- Delete existing custom application set by id. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. Id of custom application set to delete. + type: str + payload: + description: Application Policy Application Set's payload. + elements: dict + suboptions: + defaultBusinessRelevance: + description: Default business relevance. + type: str + name: + description: Application Set name. + type: str + namespace: + description: Namespace, should be set to scalablegroup application. + type: str + qualifier: + description: Qualifier, should be set to application. + type: str + scalableGroupExternalHandle: + description: Scalable group external handle, should be set to application set + name. + type: str + scalableGroupType: + description: Scalable group type, should be set to APPLICATION_GROUP. + type: str + type: + description: Type, should be set to scalablegroup. + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Application Policy CreateApplicationSets + description: Complete reference of the CreateApplicationSets API. + link: https://developer.cisco.com/docs/dna-center/#!create-application-sets +- name: Cisco DNA Center documentation for Application Policy DeleteApplicationSet + description: Complete reference of the DeleteApplicationSet API. + link: https://developer.cisco.com/docs/dna-center/#!delete-application-set +notes: + - SDK Method used are + application_policy.ApplicationPolicy.create_application_sets, + application_policy.ApplicationPolicy.delete_application_set, + + - Paths used are + post /dna/intent/api/v2/application-policy-application-set, + delete /dna/intent/api/v2/application-policy-application-set/{id}, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.application_policy_application_set: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - defaultBusinessRelevance: string + name: string + namespace: string + qualifier: string + scalableGroupExternalHandle: string + scalableGroupType: string + type: string + +- name: Delete by id + cisco.dnac.application_policy_application_set: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/application_policy_application_set_count_info.py b/plugins/modules/application_policy_application_set_count_info.py new file mode 100644 index 0000000000..5c4bed86f8 --- /dev/null +++ b/plugins/modules/application_policy_application_set_count_info.py @@ -0,0 +1,67 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: application_policy_application_set_count_info +short_description: Information module for Application Policy Application Set Count +description: +- Get all Application Policy Application Set Count. +- Get the number of all existing application sets. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + scalableGroupType: + description: + - ScalableGroupType query parameter. Scalable group type to retrieve, valid value APPLICATION_GROUP. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Application Policy GetApplicationSetCount + description: Complete reference of the GetApplicationSetCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-application-set-count +notes: + - SDK Method used are + application_policy.ApplicationPolicy.get_application_set_count, + + - Paths used are + get /dna/intent/api/v2/application-policy-application-set-count, + +""" + +EXAMPLES = r""" +- name: Get all Application Policy Application Set Count + cisco.dnac.application_policy_application_set_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + scalableGroupType: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": 0, + "version": "string" + } +""" diff --git a/plugins/modules/application_policy_application_set_info.py b/plugins/modules/application_policy_application_set_info.py new file mode 100644 index 0000000000..8a2e7efa2b --- /dev/null +++ b/plugins/modules/application_policy_application_set_info.py @@ -0,0 +1,101 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: application_policy_application_set_info +short_description: Information module for Application Policy Application Set +description: +- Get all Application Policy Application Set. +- Get application set/s by offset/limit or by name. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + attributes: + description: + - Attributes query parameter. Attributes to retrieve, valid value applicationSet. + type: str + name: + description: + - Name query parameter. Application set name. + type: str + offset: + description: + - Offset query parameter. The starting point or index from where the paginated results should begin. + type: float + limit: + description: + - > + Limit query parameter. The limit which is the maximum number of items to include in a single page of + results, max value 500. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Application Policy GetApplicationSets2 + description: Complete reference of the GetApplicationSets2 API. + link: https://developer.cisco.com/docs/dna-center/#!get-application-sets-2 +notes: + - SDK Method used are + application_policy.ApplicationPolicy.get_application_sets2, + + - Paths used are + get /dna/intent/api/v2/application-policy-application-set, + +""" + +EXAMPLES = r""" +- name: Get all Application Policy Application Set + cisco.dnac.application_policy_application_set_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + attributes: string + name: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "instanceId": 0, + "displayName": "string", + "instanceVersion": 0, + "defaultBusinessRelevance": "string", + "identitySource": { + "id": "string", + "type": "string" + }, + "name": "string", + "namespace": "string", + "scalableGroupExternalHandle": "string", + "scalableGroupType": "string", + "type": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/application_sets.py b/plugins/modules/application_sets.py index b4c5dd14c3..2955c40ef3 100644 --- a/plugins/modules/application_sets.py +++ b/plugins/modules/application_sets.py @@ -29,19 +29,19 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy CreateApplicationSet description: Complete reference of the CreateApplicationSet API. link: https://developer.cisco.com/docs/dna-center/#!create-application-set -- name: Cisco DNA Center documentation for Application Policy DeleteApplicationSet - description: Complete reference of the DeleteApplicationSet API. - link: https://developer.cisco.com/docs/dna-center/#!delete-application-set +- name: Cisco DNA Center documentation for Application Policy DeleteApplicationSet2 + description: Complete reference of the DeleteApplicationSet2 API. + link: https://developer.cisco.com/docs/dna-center/#!delete-application-set-2 notes: - SDK Method used are application_policy.ApplicationPolicy.create_application_set, - application_policy.ApplicationPolicy.delete_application_set, + application_policy.ApplicationPolicy.delete_application_set2, - Paths used are post /dna/intent/api/v1/application-policy-application-set, @@ -76,7 +76,6 @@ - name: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/application_sets_count_info.py b/plugins/modules/application_sets_count_info.py index bd6336fb7c..97b87f7dc6 100644 --- a/plugins/modules/application_sets_count_info.py +++ b/plugins/modules/application_sets_count_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationSetsCount description: Complete reference of the GetApplicationSetsCount API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/application_sets_info.py b/plugins/modules/application_sets_info.py index 168674c87f..fd0870bd20 100644 --- a/plugins/modules/application_sets_info.py +++ b/plugins/modules/application_sets_info.py @@ -22,18 +22,18 @@ offset: description: - Offset query parameter. - type: int + type: float limit: description: - Limit query parameter. - type: int + type: float name: description: - Name query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationSets description: Complete reference of the GetApplicationSets API. @@ -64,7 +64,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/applications.py b/plugins/modules/applications.py index 43c18a12bf..616a9c70b9 100644 --- a/plugins/modules/applications.py +++ b/plugins/modules/applications.py @@ -32,29 +32,6 @@ description: Id Ref. type: str type: dict - indicativeNetworkIdentity: - description: Applications's indicativeNetworkIdentity. - elements: dict - suboptions: - displayName: - description: DisplayName. - type: str - id: - description: Id. - type: str - lowerPort: - description: LowerPort. - type: int - ports: - description: Ports. - type: str - protocol: - description: Protocol. - type: str - upperPort: - description: UpperPort. - type: int - type: list name: description: Name. type: str @@ -133,22 +110,22 @@ type: list type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy CreateApplication description: Complete reference of the CreateApplication API. link: https://developer.cisco.com/docs/dna-center/#!create-application -- name: Cisco DNA Center documentation for Application Policy DeleteApplication - description: Complete reference of the DeleteApplication API. - link: https://developer.cisco.com/docs/dna-center/#!delete-application +- name: Cisco DNA Center documentation for Application Policy DeleteApplication2 + description: Complete reference of the DeleteApplication2 API. + link: https://developer.cisco.com/docs/dna-center/#!delete-application-2 - name: Cisco DNA Center documentation for Application Policy EditApplication description: Complete reference of the EditApplication API. link: https://developer.cisco.com/docs/dna-center/#!edit-application notes: - SDK Method used are application_policy.ApplicationPolicy.create_application, - application_policy.ApplicationPolicy.delete_application, + application_policy.ApplicationPolicy.delete_application2, application_policy.ApplicationPolicy.edit_application, - Paths used are @@ -172,13 +149,6 @@ payload: - applicationSet: idRef: string - indicativeNetworkIdentity: - - displayName: string - id: string - lowerPort: 0 - ports: string - protocol: string - upperPort: 0 name: string networkApplications: - appProtocol: string @@ -258,7 +228,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -266,7 +235,10 @@ type: dict sample: > { - "taskId": "string", - "url": "string" + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" } """ diff --git a/plugins/modules/applications_count_info.py b/plugins/modules/applications_count_info.py index cf4eb7d8de..dd6056ba1c 100644 --- a/plugins/modules/applications_count_info.py +++ b/plugins/modules/applications_count_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetApplicationsCount description: Complete reference of the GetApplicationsCount API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -57,7 +56,7 @@ type: dict sample: > { - "response": 0, + "response": "string", "version": "string" } """ diff --git a/plugins/modules/applications_count_v2_info.py b/plugins/modules/applications_count_v2_info.py new file mode 100644 index 0000000000..32cbe8554e --- /dev/null +++ b/plugins/modules/applications_count_v2_info.py @@ -0,0 +1,67 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: applications_count_v2_info +short_description: Information module for Applications Count V2 +description: +- Get all Applications Count V2. +- Get the number of all existing applications. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + scalableGroupType: + description: + - ScalableGroupType query parameter. Scalable group type to retrieve, valid value APPLICATION. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Application Policy GetApplicationCount + description: Complete reference of the GetApplicationCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-application-count +notes: + - SDK Method used are + application_policy.ApplicationPolicy.get_application_count, + + - Paths used are + get /dna/intent/api/v2/applications-count, + +""" + +EXAMPLES = r""" +- name: Get all Applications Count V2 + cisco.dnac.applications_count_v2_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + scalableGroupType: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": 0, + "version": "string" + } +""" diff --git a/plugins/modules/applications_health_info.py b/plugins/modules/applications_health_info.py index 883fd5398b..b136b346ba 100644 --- a/plugins/modules/applications_health_info.py +++ b/plugins/modules/applications_health_info.py @@ -36,11 +36,11 @@ startTime: description: - StartTime query parameter. Starting epoch time in milliseconds of time window. - type: int + type: float endTime: description: - EndTime query parameter. Ending epoch time in milliseconds of time window. - type: int + type: float applicationHealth: description: - > @@ -52,20 +52,20 @@ - > Offset query parameter. The offset of the first application in the returned data (optionally used with siteId only). - type: int + type: float limit: description: - > Limit query parameter. The max number of application entries in returned data 1, 1000 (optionally used with siteId only). - type: int + type: float applicationName: description: - ApplicationName query parameter. The name of the application to get information on. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Applications Applications description: Complete reference of the Applications API. @@ -102,7 +102,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/applications_info.py b/plugins/modules/applications_info.py index 6570ca75d4..5bedfcba9a 100644 --- a/plugins/modules/applications_info.py +++ b/plugins/modules/applications_info.py @@ -22,25 +22,25 @@ offset: description: - Offset query parameter. The offset of the first application to be returned. - type: int + type: float limit: description: - Limit query parameter. The maximum number of applications to be returned. - type: int + type: float name: description: - Name query parameter. Application's name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Application Policy GetApplications - description: Complete reference of the GetApplications API. - link: https://developer.cisco.com/docs/dna-center/#!get-applications +- name: Cisco DNA Center documentation for Application Policy GetApplications2 + description: Complete reference of the GetApplications2 API. + link: https://developer.cisco.com/docs/dna-center/#!get-applications-2 notes: - SDK Method used are - application_policy.ApplicationPolicy.get_applications, + application_policy.ApplicationPolicy.get_applications2, - Paths used are get /dna/intent/api/v1/applications, @@ -64,7 +64,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -76,16 +75,6 @@ { "id": "string", "name": "string", - "indicativeNetworkIdentity": [ - { - "id": "string", - "displayName": "string", - "lowerPort": 0, - "ports": "string", - "protocol": "string", - "upperPort": 0 - } - ], "networkApplications": [ { "id": "string", @@ -98,8 +87,8 @@ "helpString": "string", "longDescription": "string", "name": "string", - "popularity": 0, - "rank": 0, + "popularity": "string", + "rank": "string", "trafficClass": "string", "serverName": "string", "url": "string", @@ -111,10 +100,10 @@ { "id": "string", "displayName": "string", - "lowerPort": 0, + "lowerPort": "string", "ports": "string", "protocol": "string", - "upperPort": 0 + "upperPort": "string" } ], "applicationSet": { diff --git a/plugins/modules/applications_v2.py b/plugins/modules/applications_v2.py new file mode 100644 index 0000000000..262db5ab04 --- /dev/null +++ b/plugins/modules/applications_v2.py @@ -0,0 +1,342 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: applications_v2 +short_description: Resource module for Applications V2 +description: +- Manage operations create, update and delete of the resource Applications V2. +- Create new custom application/s. +- Delete existing custom application by id. +- Edit the attributes of an existing application. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. Id of custom application to delete. + type: str + payload: + description: Applications V2's payload. + elements: dict + suboptions: + displayName: + description: Display name. + type: str + id: + description: Application id. + type: str + indicativeNetworkIdentity: + description: Applications V2's indicativeNetworkIdentity. + elements: dict + suboptions: + displayName: + description: Display name. + type: str + id: + description: Id. + type: str + lowerPort: + description: Lower port. + type: float + ports: + description: Ports. + type: str + protocol: + description: Protocol. + type: str + upperPort: + description: Upper port. + type: float + type: list + instanceId: + description: Instance id. + type: int + instanceVersion: + description: Instance version. + type: float + name: + description: Application name. + type: str + namespace: + description: Namespace. + type: str + networkApplications: + description: Applications V2's networkApplications. + elements: dict + suboptions: + appProtocol: + description: App protocol. + type: str + applicationSubType: + description: Application sub type, LEARNED discovered application, NONE + nbar and custom application. + type: str + applicationType: + description: Application type, DEFAULT nbar application, DEFAULT_MODIFIED + nbar modified application, CUSTOM custom application. + type: str + categoryId: + description: Category id. + type: str + displayName: + description: Display name. + type: str + dscp: + description: Dscp. + type: str + engineId: + description: Engine id. + type: str + helpString: + description: Help string. + type: str + id: + description: Id. + type: str + ignoreConflict: + description: Ignore conflict, true or false. + type: bool + longDescription: + description: Long description. + type: str + name: + description: Application name. + type: str + popularity: + description: Popularity. + type: float + rank: + description: Rank, any value between 1 to 65535. + type: int + selectorId: + description: Selector id. + type: str + serverName: + description: Server name. + type: str + trafficClass: + description: Traffic class. + type: str + url: + description: Url. + type: str + type: list + networkIdentity: + description: Applications V2's networkIdentity. + elements: dict + suboptions: + displayName: + description: Display name. + type: str + id: + description: Id. + type: str + ipv4Subnet: + description: Ipv4 subnet. + elements: str + type: list + ipv6Subnet: + description: Ipv6 subnet. + elements: dict + type: list + lowerPort: + description: Lower port. + type: float + ports: + description: Ports. + type: str + protocol: + description: Protocol. + type: str + upperPort: + description: Upper port. + type: float + type: list + parentScalableGroup: + description: Applications V2's parentScalableGroup. + suboptions: + idRef: + description: Id reference to parent application set. + type: str + type: dict + qualifier: + description: Qualifier, valid value application. + type: str + scalableGroupExternalHandle: + description: Scalable group external handle, should be equal to Application + name. + type: str + scalableGroupType: + description: Scalable group type, valid value APPLICATION. + type: str + type: + description: Type, valid value scalablegroup. + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Application Policy CreateApplications + description: Complete reference of the CreateApplications API. + link: https://developer.cisco.com/docs/dna-center/#!create-applications +- name: Cisco DNA Center documentation for Application Policy DeleteApplication + description: Complete reference of the DeleteApplication API. + link: https://developer.cisco.com/docs/dna-center/#!delete-application +- name: Cisco DNA Center documentation for Application Policy EditApplications + description: Complete reference of the EditApplications API. + link: https://developer.cisco.com/docs/dna-center/#!edit-applications +notes: + - SDK Method used are + application_policy.ApplicationPolicy.create_applications, + application_policy.ApplicationPolicy.delete_application, + application_policy.ApplicationPolicy.edit_applications, + + - Paths used are + post /dna/intent/api/v2/applications, + delete /dna/intent/api/v2/applications/{id}, + put /dna/intent/api/v2/applications, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.applications_v2: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - displayName: string + id: string + indicativeNetworkIdentity: + - displayName: string + id: string + lowerPort: 0 + ports: string + protocol: string + upperPort: 0 + instanceId: 0 + instanceVersion: 0 + name: string + namespace: string + networkApplications: + - appProtocol: string + applicationSubType: string + applicationType: string + categoryId: string + displayName: string + dscp: string + engineId: string + helpString: string + id: string + ignoreConflict: true + longDescription: string + name: string + popularity: 0 + rank: 0 + selectorId: string + serverName: string + trafficClass: string + url: string + networkIdentity: + - displayName: string + id: string + ipv4Subnet: + - string + ipv6Subnet: + - {} + lowerPort: 0 + ports: string + protocol: string + upperPort: 0 + parentScalableGroup: + idRef: string + qualifier: string + scalableGroupExternalHandle: string + scalableGroupType: string + type: string + +- name: Create + cisco.dnac.applications_v2: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - indicativeNetworkIdentity: + - ipv4Subnet: + - string + ipv6Subnet: + - string + lowerPort: 0 + ports: string + protocol: string + upperPort: 0 + name: string + networkApplications: + - appProtocol: string + applicationType: string + categoryId: string + dscp: string + engineId: 0 + helpString: string + ignoreConflict: true + rank: 0 + serverName: string + trafficClass: string + type: string + url: string + networkIdentity: + - ipv4Subnet: + - string + lowerPort: 0 + ports: string + protocol: string + upperPort: 0 + parentScalableGroup: + idRef: string + scalableGroupType: string + type: string + +- name: Delete by id + cisco.dnac.applications_v2: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/applications_v2_info.py b/plugins/modules/applications_v2_info.py new file mode 100644 index 0000000000..63cf3ad192 --- /dev/null +++ b/plugins/modules/applications_v2_info.py @@ -0,0 +1,152 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: applications_v2_info +short_description: Information module for Applications V2 +description: +- Get all Applications V2. +- Get application/s by offset/limit or by name. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + attributes: + description: + - Attributes query parameter. Attributes to retrieve, valid value application. + type: str + name: + description: + - Name query parameter. The application name. + type: str + offset: + description: + - Offset query parameter. The starting point or index from where the paginated results should begin. + type: float + limit: + description: + - > + Limit query parameter. The limit which is the maximum number of items to include in a single page of + results, max value 500. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Application Policy GetApplications + description: Complete reference of the GetApplications API. + link: https://developer.cisco.com/docs/dna-center/#!get-applications +notes: + - SDK Method used are + application_policy.ApplicationPolicy.get_applications, + + - Paths used are + get /dna/intent/api/v2/applications, + +""" + +EXAMPLES = r""" +- name: Get all Applications V2 + cisco.dnac.applications_v2_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + attributes: string + name: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "instanceId": 0, + "displayName": "string", + "instanceVersion": 0, + "identitySource": { + "id": "string", + "type": "string" + }, + "indicativeNetworkIdentity": [ + { + "id": "string", + "displayName": "string", + "lowerPort": 0, + "ports": "string", + "protocol": "string", + "upperPort": 0 + } + ], + "name": "string", + "namespace": "string", + "networkApplications": [ + { + "id": "string", + "appProtocol": "string", + "applicationSubType": "string", + "applicationType": "string", + "categoryId": "string", + "displayName": "string", + "dscp": "string", + "engineId": "string", + "helpString": "string", + "longDescription": "string", + "name": "string", + "popularity": 0, + "rank": 0, + "selectorId": "string", + "serverName": "string", + "url": "string", + "trafficClass": "string" + } + ], + "networkIdentity": [ + { + "id": "string", + "displayName": "string", + "ipv4Subnet": [ + "string" + ], + "ipv6Subnet": [ + {} + ], + "lowerPort": 0, + "ports": "string", + "protocol": "string", + "upperPort": 0 + } + ], + "parentScalableGroup": { + "id": "string", + "idRef": "string" + }, + "qualifier": "string", + "scalableGroupExternalHandle": "string", + "scalableGroupType": "string", + "type": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/assign_device_to_site.py b/plugins/modules/assign_device_to_site.py index c1da97fe91..4f7d74d449 100644 --- a/plugins/modules/assign_device_to_site.py +++ b/plugins/modules/assign_device_to_site.py @@ -11,7 +11,7 @@ description: - Manage operation create of the resource Assign Device To Site. - Assigns unassigned devices to a site. This API does not move assigned devices to other sites. -version_added: '6.5.0' +version_added: '6.0.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -21,25 +21,26 @@ elements: dict suboptions: ip: - description: Device ip (eg 10.104.240.64). + description: Device IP. It can be either IPv4 or IPv6. IPV4 e.g., 10.104.240.64. + IPV6 e.g., 2001 420 284 2004 4 181 500 183. type: str type: list headers: description: Additional headers. type: dict siteId: - description: SiteId path parameter. Site id to which site the device to assign. + description: SiteId path parameter. Site Id where device(s) needs to be assigned. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for AssignDevicesToSite +- name: Cisco DNA Center documentation for Sites AssignDevicesToSite description: Complete reference of the AssignDevicesToSite API. link: https://developer.cisco.com/docs/dna-center/#!assign-devices-to-site notes: - SDK Method used are - ..assign_devices_to_site, + sites.Sites.assign_devices_to_site, - Paths used are post /dna/intent/api/v1/assign-device-to-site/{siteId}/device, @@ -62,7 +63,6 @@ siteId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/associate_site_to_network_profile.py b/plugins/modules/associate_site_to_network_profile.py index b018515566..41da5cbc87 100644 --- a/plugins/modules/associate_site_to_network_profile.py +++ b/plugins/modules/associate_site_to_network_profile.py @@ -23,8 +23,8 @@ description: SiteId path parameter. Site Id to be associated. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Site Design Associate description: Complete reference of the Associate API. @@ -52,7 +52,6 @@ siteId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/auth_token_create.py b/plugins/modules/auth_token_create.py new file mode 100644 index 0000000000..2b6d6ac1fd --- /dev/null +++ b/plugins/modules/auth_token_create.py @@ -0,0 +1,58 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: auth_token_create +short_description: Resource module for Auth Token Create +description: +- Manage operation create of the resource Auth Token Create. +- > + API to obtain an access token, which remains valid for 1 hour. The token obtained using this API is required to be + set as value to the X-Auth-Token HTTP Header for all API calls to Cisco DNA Center. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: {} +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Authentication AuthenticationAPI + description: Complete reference of the AuthenticationAPI API. + link: https://developer.cisco.com/docs/dna-center/#!authentication-api +notes: + - SDK Method used are + authentication.Authentication.authentication_api, + + - Paths used are + post /dna/system/api/v1/auth/token, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.auth_token_create: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "Token": "string" + } +""" diff --git a/plugins/modules/authentication_import_certificate.py b/plugins/modules/authentication_import_certificate.py index 15cb6d2b61..33cac61f14 100644 --- a/plugins/modules/authentication_import_certificate.py +++ b/plugins/modules/authentication_import_certificate.py @@ -30,8 +30,8 @@ description: PkPassword query parameter. Private Key Passsword. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Authentication Management ImportCertificate description: Complete reference of the ImportCertificate API. @@ -61,7 +61,6 @@ pkPassword: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/authentication_import_certificate_p12.py b/plugins/modules/authentication_import_certificate_p12.py index 23d98d2775..1fcfea2a1c 100644 --- a/plugins/modules/authentication_import_certificate_p12.py +++ b/plugins/modules/authentication_import_certificate_p12.py @@ -30,8 +30,8 @@ description: PkPassword query parameter. Private Key Passsword. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Authentication Management ImportCertificateP12 description: Complete reference of the ImportCertificateP12 API. @@ -61,7 +61,6 @@ pkPassword: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/authentication_policy_servers.py b/plugins/modules/authentication_policy_servers.py new file mode 100644 index 0000000000..2b1337b6fb --- /dev/null +++ b/plugins/modules/authentication_policy_servers.py @@ -0,0 +1,255 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: authentication_policy_servers +short_description: Resource module for Authentication Policy Servers +description: +- Manage operations create, update and delete of the resource Authentication Policy Servers. +- > + API to add AAA/ISE server access configuration. Protocol can be configured as either RADIUS OR TACACS OR + RADIUS_TACACS. If configuring Cisco ISE server, after configuration, use 'Cisco ISE Server Integration Status' + Intent API to check the integration status. Based on integration status, if require use 'Accept Cisco ISE Server + Certificate for Cisco ISE Server Integration' Intent API to accept the Cisco ISE certificate for Cisco ISE server + integration, then use again 'Cisco ISE Server Integration Status' Intent API to check the integration status. +- API to delete AAA/ISE server access configuration. +- > + API to edit AAA/ISE server access configuration. After edit, use 'Cisco ISE Server Integration Status' Intent API + to check the integration status. +version_added: '3.1.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + accountingPort: + description: Accounting port of RADIUS server (readonly). The range is from 1 to + 65535. E.g. 1813. + type: int + authenticationPort: + description: Authentication port of RADIUS server (readonly). The range is from + 1 to 65535. E.g. 1812. + type: int + ciscoIseDtos: + description: Authentication Policy Servers's ciscoIseDtos. + elements: dict + suboptions: + description: + description: Description about the Cisco ISE server. + type: str + fqdn: + description: Fully-qualified domain name of the Cisco ISE server (readonly). + E.g. Xi-62.my.com. + type: str + ipAddress: + description: IP Address of the Cisco ISE Server (readonly). + type: str + password: + description: Password of the Cisco ISE server. + type: str + sshkey: + description: SSH key of the Cisco ISE server. + type: str + subscriberName: + description: Subscriber name of the Cisco ISE server (readonly). E.g. Pxgrid_client_1662589467. + type: str + userName: + description: User name of the Cisco ISE server. + type: str + type: list + encryptionKey: + description: Encryption key used to encrypt shared secret (readonly). + type: str + encryptionScheme: + description: Type of encryption scheme for additional security (readonly). + type: str + externalCiscoIseIpAddrDtos: + description: Authentication Policy Servers's externalCiscoIseIpAddrDtos. + elements: dict + suboptions: + externalCiscoIseIpAddresses: + description: Authentication Policy Servers's externalCiscoIseIpAddresses. + elements: dict + suboptions: + externalIpAddress: + description: External IP Address. + type: str + type: list + type: + description: Type. + type: str + type: list + id: + description: Id path parameter. Authentication and Policy Server Identifier. Use + 'Get Authentication and Policy Servers' intent API to find the identifier. + type: str + ipAddress: + description: IP address of authentication and policy server (readonly). + type: str + isIseEnabled: + description: Value true for Cisco ISE Server (readonly). Default value is false. + type: bool + messageKey: + description: Message key used to encrypt shared secret (readonly). + type: str + port: + description: Port of TACACS server (readonly). The range is from 1 to 65535. + type: int + protocol: + description: Type of protocol for authentication and policy server. If already saved + with RADIUS, can update to RADIUS_TACACS. If already saved with TACACS, can update + to RADIUS_TACACS. + type: str + pxgridEnabled: + description: Value true for enable, false for disable. Default value is true. + type: bool + retries: + description: Number of communication retries between devices and authentication + and policy server. The range is from 1 to 3. + type: str + role: + description: Role of authentication and policy server (readonly). E.g. Primary, + secondary. + type: str + sharedSecret: + description: Shared secret between devices and authentication and policy server + (readonly). + type: str + timeoutSeconds: + description: Number of seconds before timing out between devices and authentication + and policy server. The range is from 2 to 20. + type: str + useDnacCertForPxgrid: + description: Value true to use DNAC certificate for Pxgrid. Default value is false. + type: bool +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for System Settings AddAuthenticationAndPolicyServerAccessConfiguration + description: Complete reference of the AddAuthenticationAndPolicyServerAccessConfiguration API. + link: https://developer.cisco.com/docs/dna-center/#!add-authentication-and-policy-server-access-configuration +- name: Cisco DNA Center documentation for System Settings DeleteAuthenticationAndPolicyServerAccessConfiguration + description: Complete reference of the DeleteAuthenticationAndPolicyServerAccessConfiguration API. + link: https://developer.cisco.com/docs/dna-center/#!delete-authentication-and-policy-server-access-configuration +- name: Cisco DNA Center documentation for System Settings EditAuthenticationAndPolicyServerAccessConfiguration + description: Complete reference of the EditAuthenticationAndPolicyServerAccessConfiguration API. + link: https://developer.cisco.com/docs/dna-center/#!edit-authentication-and-policy-server-access-configuration +notes: + - SDK Method used are + system_settings.SystemSettings.add_authentication_and_policy_server_access_configuration, + system_settings.SystemSettings.delete_authentication_and_policy_server_access_configuration, + system_settings.SystemSettings.edit_authentication_and_policy_server_access_configuration, + + - Paths used are + post /dna/intent/api/v1/authentication-policy-servers, + delete /dna/intent/api/v1/authentication-policy-servers/{id}, + put /dna/intent/api/v1/authentication-policy-servers/{id}, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.authentication_policy_servers: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + accountingPort: 0 + authenticationPort: 0 + ciscoIseDtos: + - description: string + fqdn: string + ipAddress: string + password: string + sshkey: string + subscriberName: string + userName: string + encryptionKey: string + encryptionScheme: string + externalCiscoIseIpAddrDtos: + - externalCiscoIseIpAddresses: + - externalIpAddress: string + type: string + ipAddress: string + isIseEnabled: true + messageKey: string + port: 0 + protocol: string + pxgridEnabled: true + retries: string + role: string + sharedSecret: string + timeoutSeconds: string + useDnacCertForPxgrid: true + +- name: Delete by id + cisco.dnac.authentication_policy_servers: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +- name: Update by id + cisco.dnac.authentication_policy_servers: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + accountingPort: 0 + authenticationPort: 0 + ciscoIseDtos: + - description: string + fqdn: string + ipAddress: string + password: string + sshkey: string + subscriberName: string + userName: string + encryptionKey: string + encryptionScheme: string + externalCiscoIseIpAddrDtos: + - externalCiscoIseIpAddresses: + - externalIpAddress: string + type: string + id: string + ipAddress: string + isIseEnabled: true + messageKey: string + port: 0 + protocol: string + pxgridEnabled: true + retries: string + role: string + sharedSecret: string + timeoutSeconds: string + useDnacCertForPxgrid: true + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "taskId": "string", + "url": "string" + } +""" diff --git a/plugins/modules/authentication_policy_servers_info.py b/plugins/modules/authentication_policy_servers_info.py index d0366ecc2a..2f7f5a8307 100644 --- a/plugins/modules/authentication_policy_servers_info.py +++ b/plugins/modules/authentication_policy_servers_info.py @@ -11,7 +11,7 @@ description: - Get all Authentication Policy Servers. - API to get Authentication and Policy Servers. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -25,15 +25,15 @@ type: bool state_: description: - - State query parameter. Valid values are INPROGRESS, ACTIVE, DELETED, RBAC-FAILURE, FAILED. + - State query parameter. Valid values are ACTIVE, INACTIVE, RBAC_SUCCESS, RBAC_FAILURE, DELETED, FAILED, INPROGRESS. type: str role: description: - Role query parameter. Authentication and Policy Server Role (Example primary, secondary). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for System Settings GetAuthenticationAndPolicyServers description: Complete reference of the GetAuthenticationAndPolicyServers API. @@ -64,7 +64,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -79,8 +78,8 @@ "protocol": "string", "role": "string", "port": 0, - "authenticationPort": "string", - "accountingPort": "string", + "authenticationPort": 0, + "accountingPort": 0, "retries": 0, "timeoutSeconds": 0, "isIseEnabled": true, @@ -115,7 +114,9 @@ "encryptionKey": "string", "useDnacCertForPxgrid": true, "iseEnabled": true, - "pxgridEnabled": true + "pxgridEnabled": true, + "rbacUuid": "string", + "multiDnacEnabled": true } ] """ diff --git a/plugins/modules/buildings_planned_access_points_info.py b/plugins/modules/buildings_planned_access_points_info.py index 20aaae21a1..e8e6646030 100644 --- a/plugins/modules/buildings_planned_access_points_info.py +++ b/plugins/modules/buildings_planned_access_points_info.py @@ -26,18 +26,18 @@ limit: description: - Limit query parameter. - type: int + type: float offset: description: - Offset query parameter. - type: int + type: float radios: description: - Radios query parameter. Inlcude planned radio details. type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetPlannedAccessPointsForBuilding description: Complete reference of the GetPlannedAccessPointsForBuilding API. @@ -69,7 +69,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/business_sda_hostonboarding_ssid_ippool.py b/plugins/modules/business_sda_hostonboarding_ssid_ippool.py index 53a47bdc98..348fcdc32c 100644 --- a/plugins/modules/business_sda_hostonboarding_ssid_ippool.py +++ b/plugins/modules/business_sda_hostonboarding_ssid_ippool.py @@ -10,16 +10,17 @@ short_description: Resource module for Business Sda Hostonboarding Ssid Ippool description: - Manage operations create and update of the resource Business Sda Hostonboarding Ssid Ippool. -- Add SSID to IP Pool Mapping. -- Update SSID to IP Pool Mapping. +- > + Update SSID mapping to a VLAN. The request does not need to include all the SSIDs currently mapped to a VLAN; it + can include only the SSIDs that require update. Note ECA is not supported. +- > + Update SSID mapping to a VLAN. The request does not need to include all the SSIDs currently mapped to a VLAN; it + can include only the SSIDs that require update. Note ECA is not supported. version_added: '4.0.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) options: - headers: - description: Additional headers. - type: dict scalableGroupName: description: Scalable Group Name. type: str @@ -34,8 +35,8 @@ description: VLAN Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Fabric Wireless AddSSIDToIPPoolMapping description: Complete reference of the AddSSIDToIPPoolMapping API. @@ -65,7 +66,6 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" state: present - headers: '{{my_headers | from_json}}' scalableGroupName: string siteNameHierarchy: string ssidNames: @@ -89,18 +89,15 @@ vlanName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: list + type: dict sample: > - [ - { - "executionId": "string", - "executionStatusURL": "string", - "message": "string" - } - ] + { + "executionId": "string", + "executionStatusUrl": "string", + "message": "string" + } """ diff --git a/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py b/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py index 7de5bd47ff..6454d4d115 100644 --- a/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py +++ b/plugins/modules/business_sda_hostonboarding_ssid_ippool_info.py @@ -28,8 +28,8 @@ - SiteNameHierarchy query parameter. Site Name Heirarchy. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Fabric Wireless GetSSIDToIPPoolMapping description: Complete reference of the GetSSIDToIPPoolMapping API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/business_sda_virtual_network_summary_info.py b/plugins/modules/business_sda_virtual_network_summary_info.py index beb749da61..8846c2614d 100644 --- a/plugins/modules/business_sda_virtual_network_summary_info.py +++ b/plugins/modules/business_sda_virtual_network_summary_info.py @@ -11,7 +11,7 @@ description: - Get all Business Sda Virtual Network Summary. - Get Virtual Network Summary. -version_added: '6.5.0' +version_added: '6.0.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -24,15 +24,15 @@ - SiteNameHierarchy query parameter. Complete fabric siteNameHierarchy Path. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for GetVirtualNetworkSummary +- name: Cisco DNA Center documentation for SDA GetVirtualNetworkSummary description: Complete reference of the GetVirtualNetworkSummary API. link: https://developer.cisco.com/docs/dna-center/#!get-virtual-network-summary notes: - SDK Method used are - ..get_virtual_network_summary, + sda.Sda.get_virtual_network_summary, - Paths used are get /dna/intent/api/v1/business/sda/virtual-network/summary, @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -65,11 +64,16 @@ "virtualNetworkCount": 0, "virtualNetworkSummary": [ { + "virtualNetworkContextId": "string", + "virtualNetworkId": "string", "siteNameHierarchy": "string", - "virtualNetworkName": "string" + "virtualNetworkName": "string", + "layer3Instance": 0, + "virtualNetworkStatus": "string" } ], "status": "string", - "description": "string" + "description": "string", + "executionId": "string" } """ diff --git a/plugins/modules/business_sda_wireless_controller_create.py b/plugins/modules/business_sda_wireless_controller_create.py index 9b1619f907..22f5c24497 100644 --- a/plugins/modules/business_sda_wireless_controller_create.py +++ b/plugins/modules/business_sda_wireless_controller_create.py @@ -17,14 +17,14 @@ author: Rafael Campos (@racampos) options: deviceName: - description: EWLC Device Name. + description: WLC Device Name. type: str siteNameHierarchy: - description: Site Name Hierarchy. + description: Fabric Site Name Hierarchy. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Fabric Wireless AddWLCToFabricDomain description: Complete reference of the AddWLCToFabricDomain API. @@ -53,7 +53,6 @@ siteNameHierarchy: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -62,7 +61,7 @@ sample: > { "executionId": "string", - "executionStatusURL": "string", + "executionStatusUrl": "string", "message": "string" } """ diff --git a/plugins/modules/business_sda_wireless_controller_delete.py b/plugins/modules/business_sda_wireless_controller_delete.py index 3231a6e233..1b08223c21 100644 --- a/plugins/modules/business_sda_wireless_controller_delete.py +++ b/plugins/modules/business_sda_wireless_controller_delete.py @@ -23,8 +23,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Fabric Wireless RemoveWLCFromFabricDomain description: Complete reference of the RemoveWLCFromFabricDomain API. diff --git a/plugins/modules/cli_credential.py b/plugins/modules/cli_credential.py index 9a7c0e4890..af6b8f9ffa 100644 --- a/plugins/modules/cli_credential.py +++ b/plugins/modules/cli_credential.py @@ -18,35 +18,35 @@ author: Rafael Campos (@racampos) options: comments: - description: Cli Credential's comments. + description: Comments to identify the CLI credential. type: str credentialType: - description: Cli Credential's credentialType. + description: Credential type to identify the application that uses the CLI credential. type: str description: - description: Cli Credential's description. + description: Description for CLI Credentials. type: str enablePassword: - description: Cli Credential's enablePassword. + description: CLI Enable Password. type: str id: - description: Cli Credential's id. + description: Id of the CLI Credential in UUID format. type: str instanceTenantId: - description: Cli Credential's instanceTenantId. + description: Deprecated. type: str instanceUuid: - description: Cli Credential's instanceUuid. + description: Deprecated. type: str password: - description: Cli Credential's password. + description: CLI Password. type: str username: - description: Cli Credential's username. + description: CLI Username. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateCLICredentials description: Complete reference of the CreateCLICredentials API. @@ -107,7 +107,6 @@ username: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/client_detail_info.py b/plugins/modules/client_detail_info.py index 5cc6ca6d93..041b12d54c 100644 --- a/plugins/modules/client_detail_info.py +++ b/plugins/modules/client_detail_info.py @@ -19,17 +19,17 @@ headers: description: Additional headers. type: dict - timestamp: - description: - - Timestamp query parameter. Epoch time(in milliseconds) when the Client health data is required. - type: str macAddress: description: - MacAddress query parameter. MAC Address of the client. type: str + timestamp: + description: + - Timestamp query parameter. Epoch time(in milliseconds) when the Client health data is required. + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Clients GetClientDetail description: Complete reference of the GetClientDetail API. @@ -54,12 +54,11 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" - timestamp: string macAddress: string + timestamp: 0 register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -70,12 +69,20 @@ "detail": { "id": "string", "connectionStatus": "string", + "tracked": "string", "hostType": "string", - "userId": {}, + "userId": "string", + "duid": "string", + "identifier": "string", "hostName": "string", - "hostOs": {}, - "hostVersion": {}, + "hostOs": "string", + "hostVersion": "string", "subType": "string", + "firmwareVersion": "string", + "deviceVendor": "string", + "deviceForm": "string", + "salesCode": "string", + "countryCode": "string", "lastUpdated": 0, "healthScore": [ { @@ -91,57 +98,129 @@ ], "authType": "string", "vlanId": 0, + "l3VirtualNetwork": "string", + "l2VirtualNetwork": "string", "vnid": 0, + "upnId": "string", + "upnName": "string", "ssid": "string", "frequency": "string", "channel": "string", - "apGroup": {}, - "location": {}, + "apGroup": "string", + "sgt": "string", + "location": "string", "clientConnection": "string", "connectedDevice": [ - {} + { + "type": "string", + "name": "string", + "mac": "string", + "id": "string", + "ip address": "string", + "mgmtIp": "string", + "band": "string", + "mode": "string" + } ], "issueCount": 0, "rssi": "string", - "avgRssi": {}, + "rssiThreshold": "string", + "rssiIsInclude": "string", + "avgRssi": "string", "snr": "string", - "avgSnr": {}, + "snrThreshold": "string", + "snrIsInclude": "string", + "avgSnr": "string", "dataRate": "string", "txBytes": "string", "rxBytes": "string", - "dnsSuccess": {}, - "dnsFailure": {}, + "dnsResponse": "string", + "dnsRequest": "string", "onboarding": { - "averageRunDuration": {}, - "maxRunDuration": {}, - "averageAssocDuration": {}, - "maxAssocDuration": {}, - "averageAuthDuration": {}, - "maxAuthDuration": {}, - "averageDhcpDuration": {}, - "maxDhcpDuration": {}, + "averageRunDuration": "string", + "maxRunDuration": "string", + "averageAssocDuration": "string", + "maxAssocDuration": "string", + "averageAuthDuration": "string", + "maxAuthDuration": "string", + "averageDhcpDuration": "string", + "maxDhcpDuration": "string", "aaaServerIp": "string", - "dhcpServerIp": {}, - "authDoneTime": {}, - "assocDoneTime": {}, - "dhcpDoneTime": {}, + "dhcpServerIp": "string", + "authDoneTime": 0, + "assocDoneTime": 0, + "dhcpDoneTime": 0, "assocRootcauseList": [ - {} + "string" ], "aaaRootcauseList": [ - {} + "string" ], "dhcpRootcauseList": [ - {} + "string" ], "otherRootcauseList": [ - {} + "string" + ], + "latestRootCauseList": [ + "string" ] }, "clientType": "string", - "onboardingTime": {}, - "port": {}, - "iosCapable": true + "onboardingTime": 0, + "port": "string", + "iosCapable": true, + "usage": 0, + "linkSpeed": 0, + "linkThreshold": "string", + "remoteEndDuplexMode": "string", + "txLinkError": 0, + "rxLinkError": 0, + "txRate": 0, + "rxRate": 0, + "rxRetryPct": "string", + "versionTime": 0, + "dot11Protocol": "string", + "slotId": 0, + "dot11ProtocolCapability": "string", + "privateMac": true, + "dhcpServerIp": "string", + "aaaServerIp": "string", + "aaaServerTransaction": 0, + "aaaServerFailedTransaction": 0, + "aaaServerSuccessTransaction": 0, + "aaaServerLatency": 0, + "aaaServerMABLatency": 0, + "aaaServerEAPLatency": 0, + "dhcpServerTransaction": 0, + "dhcpServerFailedTransaction": 0, + "dhcpServerSuccessTransaction": 0, + "dhcpServerLatency": 0, + "dhcpServerDOLatency": 0, + "dhcpServerRALatency": 0, + "maxRoamingDuration": "string", + "upnOwner": "string", + "connectedUpn": "string", + "connectedUpnOwner": "string", + "connectedUpnId": "string", + "isGuestUPNEndpoint": true, + "wlcName": "string", + "wlcUuid": "string", + "sessionDuration": "string", + "intelCapable": true, + "hwModel": "string", + "powerType": "string", + "modelName": "string", + "bridgeVMMode": "string", + "dhcpNakIp": "string", + "dhcpDeclineIp": "string", + "portDescription": "string", + "latencyVoice": 0, + "latencyVideo": 0, + "latencyBg": 0, + "latencyBe": 0, + "trustScore": "string", + "trustDetails": "string" }, "connectionInfo": { "hostType": "string", @@ -164,31 +243,61 @@ "id": "string", "description": "string", "deviceType": "string", - "platformId": {}, - "family": {}, + "platformId": "string", + "family": "string", "ip": "string", - "softwareVersion": {}, - "userId": {}, + "ipv6": [ + "string" + ], + "softwareVersion": "string", + "userId": "string", "nodeType": "string", - "radioFrequency": {}, - "clients": {}, - "count": {}, + "radioFrequency": "string", + "clients": 0, + "count": 0, "healthScore": 0, "level": 0, - "fabricGroup": {}, - "connectedDevice": {} + "fabricGroup": "string", + "fabricRole": [ + "string" + ], + "connectedDevice": "string", + "stackType": "string" } ], "links": [ { "source": "string", "linkStatus": "string", + "sourceLinkStatus": "string", + "targetLinkStatus": "string", "label": [ "string" ], "target": "string", - "id": {}, - "portUtilization": {} + "id": "string", + "portUtilization": 0, + "sourceInterfaceName": "string", + "targetInterfaceName": "string", + "sourceDuplexInfo": "string", + "targetDuplexInfo": "string", + "sourcePortMode": "string", + "targetPortMode": "string", + "sourceAdminStatus": "string", + "targetAdminStatus": "string", + "apRadioAdminStatus": "string", + "apRadioOperStatus": "string", + "sourcePortVLANInfo": "string", + "targetPortVLANInfo": "string", + "interfaceDetails": [ + { + "clientMacAddress": "string", + "connectedDeviceIntName": "string", + "duplex": "string", + "portMode": "string", + "adminStatus": "string" + } + ] } ] } diff --git a/plugins/modules/client_enrichment_details_info.py b/plugins/modules/client_enrichment_details_info.py index 54be2389af..48946934f2 100644 --- a/plugins/modules/client_enrichment_details_info.py +++ b/plugins/modules/client_enrichment_details_info.py @@ -22,8 +22,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Clients GetClientEnrichmentDetails description: Complete reference of the GetClientEnrichmentDetails API. @@ -51,7 +51,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/client_health_info.py b/plugins/modules/client_health_info.py index f036bb5bdb..a9930dcdf0 100644 --- a/plugins/modules/client_health_info.py +++ b/plugins/modules/client_health_info.py @@ -22,10 +22,10 @@ timestamp: description: - Timestamp query parameter. Epoch time(in milliseconds) when the Client health data is required. - type: str + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Clients GetOverallClientHealth description: Complete reference of the GetOverallClientHealth API. @@ -50,60 +50,58 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" - timestamp: string + timestamp: 0 register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: list - elements: dict + type: dict sample: > - [ - { - "siteId": "string", - "scoreDetail": [ - { - "scoreCategory": { - "scoreCategory": "string", - "value": "string" - }, - "scoreValue": 0, - "clientCount": 0, - "clientUniqueCount": 0, - "starttime": 0, - "endtime": 0, - "scoreList": [ - { - "scoreCategory": { - "scoreCategory": "string", - "value": "string" - }, - "scoreValue": 0, - "clientCount": 0, - "clientUniqueCount": 0, - "starttime": 0, - "endtime": 0, - "scoreList": [ - { - "scoreCategory": { - "scoreCategory": "string", - "value": "string" - }, - "scoreValue": 0, - "clientCount": 0, - "clientUniqueCount": {}, - "starttime": 0, - "endtime": 0 - } - ] - } - ] - } - ] - } - ] + { + "version": "string", + "response": [ + { + "siteId": "string", + "scoreDetail": [ + { + "scoreCategory": { + "scoreCategory": "string", + "value": "string" + }, + "scoreValue": 0, + "clientCount": 0, + "clientUniqueCount": 0, + "maintenanceAffectedClientCount": 0, + "randomMacCount": 0, + "duidCount": 0, + "starttime": 0, + "endtime": 0, + "connectedToUdnCount": 0, + "unconnectedToUdnCount": 0, + "scoreList": [ + { + "scoreCategory": { + "scoreCategory": "string", + "value": "string" + }, + "scoreValue": 0, + "clientCount": 0, + "clientUniqueCount": 0, + "maintenanceAffectedClientCount": 0, + "randomMacCount": 0, + "duidCount": 0, + "starttime": 0, + "endtime": 0, + "connectedToUdnCount": 0, + "unconnectedToUdnCount": 0 + } + ] + } + ] + } + ] + } """ diff --git a/plugins/modules/client_proximity_info.py b/plugins/modules/client_proximity_info.py index 7d30d7542e..d87ad0cbbb 100644 --- a/plugins/modules/client_proximity_info.py +++ b/plugins/modules/client_proximity_info.py @@ -32,16 +32,16 @@ - > Number_days query parameter. Number of days to track proximity until current date. Defaults and maximum up to 14 days. - type: int + type: float time_resolution: description: - > Time_resolution query parameter. Time interval (in minutes) to measure proximity. Defaults to 15 minutes with a minimum 5 minutes. - type: int + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Clients ClientProximity description: Complete reference of the ClientProximity API. @@ -72,7 +72,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/command_runner_run_command.py b/plugins/modules/command_runner_run_command.py index 5b12002ede..2ae6b29f85 100644 --- a/plugins/modules/command_runner_run_command.py +++ b/plugins/modules/command_runner_run_command.py @@ -17,25 +17,26 @@ author: Rafael Campos (@racampos) options: commands: - description: Command Runner Run Command's commands. + description: Commands to be executed. elements: str type: list description: - description: Command Runner Run Command's description. + description: Describe the details about the command request. type: str deviceUuids: - description: Command Runner Run Command's deviceUuids. + description: Device Id of the device. elements: str type: list name: - description: Command Runner Run Command's name. + description: Name of the the request like getshowrun , deviceinterfacestatusCli. type: str timeout: - description: Command Runner Run Command's timeout. + description: The timeout value in unit of second. If no timeout provided wait till + 300sec. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Command Runner RunReadOnlyCommandsOnDevicesToGetTheirRealTimeConfiguration description: Complete reference of the RunReadOnlyCommandsOnDevicesToGetTheirRealTimeConfiguration API. @@ -68,7 +69,6 @@ timeout: 0 """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/compliance_check_run.py b/plugins/modules/compliance_check_run.py index c244f41f85..d676aeaee7 100644 --- a/plugins/modules/compliance_check_run.py +++ b/plugins/modules/compliance_check_run.py @@ -17,19 +17,23 @@ author: Rafael Campos (@racampos) options: categories: - description: Compliance Check Run's categories. + description: Category can have any value among 'INTENT'(mapped to compliance types + NETWORK_SETTINGS,NETWORK_PROFILE,WORKFLOW,FABRIC,APPLICATION_VISIBILITY), 'RUNNING_CONFIG' + , 'IMAGE' , 'PSIRT' , 'EOX' , 'NETWORK_SETTINGS'. elements: str type: list deviceUuids: - description: Compliance Check Run's deviceUuids. + description: UUID of the device. elements: str type: list triggerFull: - description: TriggerFull flag. + description: If it is true then compliance will be triggered for all categories. + If it is false then compliance will be triggered for categories mentioned in categories + section . type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Compliance RunCompliance description: Complete reference of the RunCompliance API. @@ -60,7 +64,6 @@ triggerFull: true """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/compliance_device_by_id_info.py b/plugins/modules/compliance_device_by_id_info.py index 99d967c02a..afe6d944b4 100644 --- a/plugins/modules/compliance_device_by_id_info.py +++ b/plugins/modules/compliance_device_by_id_info.py @@ -21,33 +21,28 @@ type: dict deviceUuid: description: - - DeviceUuid path parameter. + - DeviceUuid path parameter. Device Id. type: str category: description: - - Category query parameter. ComplianceCategory can have any value among 'INTENT', 'RUNNING_CONFIG'. + - > + Category query parameter. Category can have any value among 'INTENT', 'RUNNING_CONFIG' , 'IMAGE' , 'PSIRT' , + 'DESIGN_OOD' , 'EOX' , 'NETWORK_SETTINGS'. type: str complianceType: description: - > - ComplianceType query parameter. ComplianceType can have any value among 'NETWORK_DESIGN', 'NETWORK_PROFILE', - 'FABRIC', 'POLICY', 'RUNNING_CONFIG'. + ComplianceType query parameter. Specify "Compliance type(s)" separated by commas. The Compliance type can be + 'APPLICATION_VISIBILITY', 'EOX', 'FABRIC', 'IMAGE', 'NETWORK_PROFILE', 'NETWORK_SETTINGS', 'PSIRT', + 'RUNNING_CONFIG', 'WORKFLOW'. type: str diffList: description: - DiffList query parameter. Diff list pass true to fetch the diff list. type: bool - key: - description: - - Key query parameter. Extended attribute key. - type: str - value: - description: - - Value query parameter. Extended attribute value. - type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Compliance ComplianceDetailsOfDevice description: Complete reference of the ComplianceDetailsOfDevice API. @@ -75,13 +70,10 @@ category: string complianceType: string diffList: True - key: string - value: string deviceUuid: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -89,55 +81,63 @@ type: dict sample: > { - "deviceUuid": "string", - "version": "string", "response": [ { - "displayName": "string", + "deviceUuid": "string", "complianceType": "string", + "status": "string", + "state": "string", "lastSyncTime": 0, - "additionalDataURL": "string", + "lastUpdateTime": 0, "sourceInfoList": [ { + "name": "string", + "nameWithBusinessKey": "string", + "sourceEnum": "string", + "type": "string", + "appName": "string", "count": 0, - "displayName": "string", + "ackStatus": "string", + "businessKey": { + "resourceName": "string", + "businessKeyAttributes": {}, + "otherAttributes": { + "name": "string", + "cfsAttributes": { + "displayName": "string", + "appName": "string", + "description": "string", + "source": "string", + "type": "string" + } + } + }, "diffList": [ { - "displayName": "string", - "moveFromPath": "string", "op": "string", "configuredValue": "string", "intendedValue": "string", - "path": "string", + "moveFromPath": "string", "businessKey": "string", - "extendedAttributes": "string" + "path": "string", + "extendedAttributes": { + "attributeDisplayName": "string", + "path": "string", + "dataConverter": "string", + "type": "string" + }, + "ackStatus": "string", + "instanceUUID": "string", + "displayName": "string" } ], - "sourceEnum": "string", - "licenseAppName": "string", - "provisioningArea": "string", - "networkProfileName": "string", - "nameWithBusinessKey": "string", - "appName": "string", - "name": "string", - "type": "string", - "businessKey": { - "otherAttributes": { - "cfsAttributes": "string", - "name": "string" - }, - "resourceName": "string", - "businessKeyAttributes": "string" - } + "displayName": "string" } ], - "deviceUuid": "string", - "message": "string", - "state": "string", - "status": "string", - "category": "string", - "lastUpdateTime": 0 + "ackStatus": "string", + "version": "string" } - ] + ], + "deviceUuid": "string" } """ diff --git a/plugins/modules/compliance_device_details_count_info.py b/plugins/modules/compliance_device_details_count_info.py index a51939ed4d..30a7b590b6 100644 --- a/plugins/modules/compliance_device_details_count_info.py +++ b/plugins/modules/compliance_device_details_count_info.py @@ -22,18 +22,19 @@ complianceType: description: - > - ComplianceType query parameter. ComplianceType can have any value among 'NETWORK_PROFILE', 'IMAGE', - 'APPLICATION_VISIBILITY', 'FABRIC', 'PSIRT', 'RUNNING_CONFIG', 'WORKFLOW'. + ComplianceType query parameter. Specify "Compliance type(s)" separated by commas. The Compliance type can be + 'APPLICATION_VISIBILITY', 'EOX', 'FABRIC', 'IMAGE', 'NETWORK_PROFILE', 'NETWORK_SETTINGS', 'PSIRT', + 'RUNNING_CONFIG', 'WORKFLOW'. type: str complianceStatus: description: - > - ComplianceStatus query parameter. Compliance status can have value among 'COMPLIANT', 'NON_COMPLIANT', - 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. + ComplianceStatus query parameter. Specify "Compliance status(es)" separated by commas. The Compliance status + can be 'COMPLIANT', 'NON_COMPLIANT', 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Compliance GetComplianceDetailCount description: Complete reference of the GetComplianceDetailCount API. @@ -63,7 +64,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/compliance_device_details_info.py b/plugins/modules/compliance_device_details_info.py index bc06458f28..55980c744a 100644 --- a/plugins/modules/compliance_device_details_info.py +++ b/plugins/modules/compliance_device_details_info.py @@ -22,30 +22,31 @@ complianceType: description: - > - ComplianceType query parameter. ComplianceType can have any value among 'NETWORK_PROFILE', 'IMAGE', - 'APPLICATION_VISIBILITY', 'FABRIC', 'PSIRT', 'RUNNING_CONFIG', 'WORKFLOW'. + ComplianceType query parameter. Specify "Compliance type(s)" in commas. The Compliance type can be + 'NETWORK_PROFILE', 'IMAGE', 'FABRIC', 'APPLICATION_VISIBILITY', 'FABRIC', RUNNING_CONFIG', + 'NETWORK_SETTINGS', 'WORKFLOW' , 'EOX'. type: str complianceStatus: description: - > - ComplianceStatus query parameter. Compliance status can have value among 'COMPLIANT', 'NON_COMPLIANT', - 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. + ComplianceStatus query parameter. Specify "Compliance status(es)" in commas. The Compliance status can be + 'COMPLIANT', 'NON_COMPLIANT', 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. type: str deviceUuid: description: - - DeviceUuid query parameter. Comma separated deviceUuids. + - DeviceUuid query parameter. Comma separated "Device Id(s)". type: str offset: description: - Offset query parameter. Offset/starting row. - type: int + type: float limit: description: - Limit query parameter. Number of records to be retrieved. - type: int + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Compliance GetComplianceDetail description: Complete reference of the GetComplianceDetail API. @@ -78,7 +79,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/compliance_device_info.py b/plugins/modules/compliance_device_info.py index 38eaafb12c..60bdef0875 100644 --- a/plugins/modules/compliance_device_info.py +++ b/plugins/modules/compliance_device_info.py @@ -24,24 +24,16 @@ complianceStatus: description: - > - ComplianceStatus query parameter. Compliance status can be have value among - 'COMPLIANT','NON_COMPLIANT','IN_PROGRESS', 'ERROR'. + ComplianceStatus query parameter. Specify "Compliance status(es)" separated by commas. The Compliance status + can be 'COMPLIANT', 'NON_COMPLIANT', 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. type: str deviceUuid: description: - - DeviceUuid query parameter. Comma separated deviceUuids. + - DeviceUuid query parameter. Comma separated 'Device Ids'. type: str - offset: - description: - - Offset query parameter. Offset/starting row. - type: int - limit: - description: - - Limit query parameter. Number of records to be retrieved. - type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Compliance DeviceComplianceStatus description: Complete reference of the DeviceComplianceStatus API. @@ -73,8 +65,6 @@ headers: "{{my_headers | from_json}}" complianceStatus: string deviceUuid: string - offset: 0 - limit: 0 register: result - name: Get Compliance Device by id @@ -91,7 +81,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -99,13 +88,12 @@ type: dict sample: > { - "version": "string", "response": { "deviceUuid": "string", "complianceStatus": "string", - "message": "string", - "scheduleTime": 0, - "lastUpdateTime": 0 - } + "lastUpdateTime": 0, + "scheduleTime": "string" + }, + "version": "string" } """ diff --git a/plugins/modules/compliance_device_status_count_info.py b/plugins/modules/compliance_device_status_count_info.py index 6c7897f94d..2a96751cfc 100644 --- a/plugins/modules/compliance_device_status_count_info.py +++ b/plugins/modules/compliance_device_status_count_info.py @@ -22,12 +22,12 @@ complianceStatus: description: - > - ComplianceStatus query parameter. Compliance status can have value among 'COMPLIANT', 'NON_COMPLIANT', - 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. + ComplianceStatus query parameter. Specify "Compliance status(es)" separated by commas. The Compliance status + can be 'COMPLIANT', 'NON_COMPLIANT', 'IN_PROGRESS', 'NOT_AVAILABLE', 'NOT_APPLICABLE', 'ERROR'. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Compliance GetComplianceStatusCount description: Complete reference of the GetComplianceStatusCount API. @@ -56,7 +56,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -65,6 +64,6 @@ sample: > { "version": "string", - "response": 0 + "response": "string" } """ diff --git a/plugins/modules/configuration_template.py b/plugins/modules/configuration_template.py index 05e7acf351..95752c49bc 100644 --- a/plugins/modules/configuration_template.py +++ b/plugins/modules/configuration_template.py @@ -512,8 +512,8 @@ description: Current version of template. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates DeletesTheTemplate description: Complete reference of the DeletesTheTemplate API. @@ -713,7 +713,6 @@ templateId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_clone.py b/plugins/modules/configuration_template_clone.py index c21257ba40..3be0b8e3f1 100644 --- a/plugins/modules/configuration_template_clone.py +++ b/plugins/modules/configuration_template_clone.py @@ -28,8 +28,8 @@ description: TemplateId path parameter. UUID of the template to clone it. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates CreatesACloneOfTheGivenTemplate description: Complete reference of the CreatesACloneOfTheGivenTemplate API. @@ -58,7 +58,6 @@ templateId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_create.py b/plugins/modules/configuration_template_create.py index f5beee649b..708ebd26f6 100644 --- a/plugins/modules/configuration_template_create.py +++ b/plugins/modules/configuration_template_create.py @@ -508,8 +508,8 @@ description: Current version of template. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates CreateTemplate description: Complete reference of the CreateTemplate API. @@ -691,7 +691,6 @@ version: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_deploy.py b/plugins/modules/configuration_template_deploy.py index a1b1b5265b..c620a3378f 100644 --- a/plugins/modules/configuration_template_deploy.py +++ b/plugins/modules/configuration_template_deploy.py @@ -27,7 +27,8 @@ type: str memberTemplateDeploymentInfo: description: MemberTemplateDeploymentInfo. - type: str + elements: dict + type: list targetInfo: description: Configuration Template Deploy's targetInfo. elements: dict @@ -42,8 +43,10 @@ description: Template params/values to be provisioned. type: dict resourceParams: - description: Resource params to be provisioned. - type: dict + description: Resource params to be provisioned. Refer to features page for usage + details. + elements: dict + type: list type: description: Target type of device. type: str @@ -55,8 +58,8 @@ description: UUID of template to be provisioned. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates DeployTemplate description: Complete reference of the DeployTemplate API. @@ -83,18 +86,19 @@ forcePushTemplate: true isComposite: true mainTemplateId: string - memberTemplateDeploymentInfo: string + memberTemplateDeploymentInfo: + - {} targetInfo: - hostName: string id: string params: {} - resourceParams: {} + resourceParams: + - {} type: string versionedTemplateId: string templateId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_deploy_status_info.py b/plugins/modules/configuration_template_deploy_status_info.py index 46c7439eb5..256b3f548c 100644 --- a/plugins/modules/configuration_template_deploy_status_info.py +++ b/plugins/modules/configuration_template_deploy_status_info.py @@ -24,8 +24,8 @@ - DeploymentId path parameter. UUID of deployment to retrieve template deployment status. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates StatusOfTemplateDeployment description: Complete reference of the StatusOfTemplateDeployment API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_deploy_v2.py b/plugins/modules/configuration_template_deploy_v2.py index af7f1094d4..f6e2686070 100644 --- a/plugins/modules/configuration_template_deploy_v2.py +++ b/plugins/modules/configuration_template_deploy_v2.py @@ -27,7 +27,8 @@ type: str memberTemplateDeploymentInfo: description: MemberTemplateDeploymentInfo. - type: str + elements: dict + type: list targetInfo: description: Configuration Template Deploy V2's targetInfo. elements: dict @@ -42,8 +43,10 @@ description: Template params/values to be provisioned. type: dict resourceParams: - description: Resource params to be provisioned. - type: dict + description: Resource params to be provisioned. Refer to features page for usage + details. + elements: dict + type: list type: description: Target type of device. type: str @@ -55,8 +58,8 @@ description: UUID of template to be provisioned. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates DeployTemplateV2 description: Complete reference of the DeployTemplateV2 API. @@ -83,18 +86,19 @@ forcePushTemplate: true isComposite: true mainTemplateId: string - memberTemplateDeploymentInfo: string + memberTemplateDeploymentInfo: + - {} targetInfo: - hostName: string id: string params: {} - resourceParams: {} + resourceParams: + - {} type: string versionedTemplateId: string templateId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_export_project.py b/plugins/modules/configuration_template_export_project.py index f414750054..6d4a4d4eb6 100644 --- a/plugins/modules/configuration_template_export_project.py +++ b/plugins/modules/configuration_template_export_project.py @@ -21,8 +21,8 @@ elements: dict type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates ExportsTheProjectsForAGivenCriteria description: Complete reference of the ExportsTheProjectsForAGivenCriteria API. @@ -50,7 +50,6 @@ - {} """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_export_template.py b/plugins/modules/configuration_template_export_template.py index d460cef406..fa443a3325 100644 --- a/plugins/modules/configuration_template_export_template.py +++ b/plugins/modules/configuration_template_export_template.py @@ -21,8 +21,8 @@ elements: dict type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates ExportsTheTemplatesForAGivenCriteria description: Complete reference of the ExportsTheTemplatesForAGivenCriteria API. @@ -50,7 +50,6 @@ - {} """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_import_project.py b/plugins/modules/configuration_template_import_project.py index 37b2096e4e..8e0ca8089f 100644 --- a/plugins/modules/configuration_template_import_project.py +++ b/plugins/modules/configuration_template_import_project.py @@ -23,8 +23,8 @@ fails with 'Template already exists' error. type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates ImportsTheProjectsProvided description: Complete reference of the ImportsTheProjectsProvided API. @@ -51,7 +51,6 @@ doVersion: true """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_import_template.py b/plugins/modules/configuration_template_import_template.py index 7f9cf31f6b..5f3d0d8360 100644 --- a/plugins/modules/configuration_template_import_template.py +++ b/plugins/modules/configuration_template_import_template.py @@ -523,8 +523,8 @@ project. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates ImportsTheTemplatesProvided description: Complete reference of the ImportsTheTemplatesProvided API. @@ -709,7 +709,6 @@ projectName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_info.py b/plugins/modules/configuration_template_info.py index ad9e264cf9..b03b4cfaaa 100644 --- a/plugins/modules/configuration_template_info.py +++ b/plugins/modules/configuration_template_info.py @@ -76,8 +76,8 @@ - LatestVersion query parameter. LatestVersion flag to get the latest versioned template. type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetsDetailsOfAGivenTemplate description: Complete reference of the GetsDetailsOfAGivenTemplate API. @@ -135,7 +135,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_project.py b/plugins/modules/configuration_template_project.py index 7678e283c8..f2c59a8ae2 100644 --- a/plugins/modules/configuration_template_project.py +++ b/plugins/modules/configuration_template_project.py @@ -50,504 +50,10 @@ templates: description: List of templates within the project. elements: dict - suboptions: - author: - description: Author of template. - type: str - composite: - description: Is it composite template. - type: bool - containingTemplates: - description: Configuration Template Project's containingTemplates. - elements: dict - suboptions: - composite: - description: Is it composite template. - type: bool - description: - description: Description of template. - type: str - deviceTypes: - description: Configuration Template Project's deviceTypes. - elements: dict - suboptions: - productFamily: - description: Device family. - type: str - productSeries: - description: Device series. - type: str - productType: - description: Device type. - type: str - type: list - id: - description: UUID of template. - type: str - language: - description: Template language (JINJA or VELOCITY). - type: str - name: - description: Name of template. - type: str - projectName: - description: Project name. - type: str - rollbackTemplateParams: - description: Configuration Template Project's rollbackTemplateParams. - elements: dict - suboptions: - binding: - description: Bind to source. - type: str - customOrder: - description: CustomOrder of template param. - type: int - dataType: - description: Datatype of template param. - type: str - defaultValue: - description: Default value of template param. - type: str - description: - description: Description of template param. - type: str - displayName: - description: Display name of param. - type: str - group: - description: Group. - type: str - id: - description: UUID of template param. - type: str - instructionText: - description: Instruction text for param. - type: str - key: - description: Key. - type: str - notParam: - description: Is it not a variable. - type: bool - order: - description: Order of template param. - type: int - paramArray: - description: Is it an array. - type: bool - parameterName: - description: Name of template param. - type: str - provider: - description: Provider. - type: str - range: - description: Configuration Template Project's range. - elements: dict - suboptions: - id: - description: UUID of range. - type: str - maxValue: - description: Max value of range. - type: int - minValue: - description: Min value of range. - type: int - type: list - required: - description: Is param required. - type: bool - selection: - description: Configuration Template Project's selection. - suboptions: - defaultSelectedValues: - description: Default selection values. - elements: str - type: list - id: - description: UUID of selection. - type: str - selectionType: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). - type: str - selectionValues: - description: Selection values. - type: dict - type: dict - type: list - tags: - description: Configuration Template Project's tags. - elements: dict - suboptions: - id: - description: UUID of tag. - type: str - name: - description: Name of tag. - type: str - type: list - templateContent: - description: Template content. - type: str - templateParams: - description: Configuration Template Project's templateParams. - elements: dict - suboptions: - binding: - description: Bind to source. - type: str - customOrder: - description: CustomOrder of template param. - type: int - dataType: - description: Datatype of template param. - type: str - defaultValue: - description: Default value of template param. - type: str - description: - description: Description of template param. - type: str - displayName: - description: Display name of param. - type: str - group: - description: Group. - type: str - id: - description: UUID of template param. - type: str - instructionText: - description: Instruction text for param. - type: str - key: - description: Key. - type: str - notParam: - description: Is it not a variable. - type: bool - order: - description: Order of template param. - type: int - paramArray: - description: Is it an array. - type: bool - parameterName: - description: Name of template param. - type: str - provider: - description: Provider. - type: str - range: - description: Configuration Template Project's range. - elements: dict - suboptions: - id: - description: UUID of range. - type: str - maxValue: - description: Max value of range. - type: int - minValue: - description: Min value of range. - type: int - type: list - required: - description: Is param required. - type: bool - selection: - description: Configuration Template Project's selection. - suboptions: - defaultSelectedValues: - description: Default selection values. - elements: str - type: list - id: - description: UUID of selection. - type: str - selectionType: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). - type: str - selectionValues: - description: Selection values. - type: dict - type: dict - type: list - version: - description: Current version of template. - type: str - type: list - createTime: - description: Create time of template. - type: int - customParamsOrder: - description: Custom Params Order. - type: bool - description: - description: Description of template. - type: str - deviceTypes: - description: Configuration Template Project's deviceTypes. - elements: dict - suboptions: - productFamily: - description: Device family. - type: str - productSeries: - description: Device series. - type: str - productType: - description: Device type. - type: str - type: list - failurePolicy: - description: Define failure policy if template provisioning fails. - type: str - id: - description: UUID of template. - type: str - language: - description: Template language (JINJA or VELOCITY). - type: str - lastUpdateTime: - description: Update time of template. - type: int - latestVersionTime: - description: Latest versioned template time. - type: int - name: - description: Name of template. - type: str - parentTemplateId: - description: Parent templateID. - type: str - projectId: - description: Project UUID. - type: str - projectName: - description: Project name. - type: str - rollbackTemplateContent: - description: Rollback template content. - type: str - rollbackTemplateParams: - description: Configuration Template Project's rollbackTemplateParams. - elements: dict - suboptions: - binding: - description: Bind to source. - type: str - customOrder: - description: CustomOrder of template param. - type: int - dataType: - description: Datatype of template param. - type: str - defaultValue: - description: Default value of template param. - type: str - description: - description: Description of template param. - type: str - displayName: - description: Display name of param. - type: str - group: - description: Group. - type: str - id: - description: UUID of template param. - type: str - instructionText: - description: Instruction text for param. - type: str - key: - description: Key. - type: str - notParam: - description: Is it not a variable. - type: bool - order: - description: Order of template param. - type: int - paramArray: - description: Is it an array. - type: bool - parameterName: - description: Name of template param. - type: str - provider: - description: Provider. - type: str - range: - description: Configuration Template Project's range. - elements: dict - suboptions: - id: - description: UUID of range. - type: str - maxValue: - description: Max value of range. - type: int - minValue: - description: Min value of range. - type: int - type: list - required: - description: Is param required. - type: bool - selection: - description: Configuration Template Project's selection. - suboptions: - defaultSelectedValues: - description: Default selection values. - elements: str - type: list - id: - description: UUID of selection. - type: str - selectionType: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). - type: str - selectionValues: - description: Selection values. - type: dict - type: dict - type: list - softwareType: - description: Applicable device software type. - type: str - softwareVariant: - description: Applicable device software variant. - type: str - softwareVersion: - description: Applicable device software version. - type: str - tags: - description: Configuration Template Project's tags. - elements: dict - suboptions: - id: - description: UUID of tag. - type: str - name: - description: Name of tag. - type: str - type: list - templateContent: - description: Template content. - type: str - templateParams: - description: Configuration Template Project's templateParams. - elements: dict - suboptions: - binding: - description: Bind to source. - type: str - customOrder: - description: CustomOrder of template param. - type: int - dataType: - description: Datatype of template param. - type: str - defaultValue: - description: Default value of template param. - type: str - description: - description: Description of template param. - type: str - displayName: - description: Display name of param. - type: str - group: - description: Group. - type: str - id: - description: UUID of template param. - type: str - instructionText: - description: Instruction text for param. - type: str - key: - description: Key. - type: str - notParam: - description: Is it not a variable. - type: bool - order: - description: Order of template param. - type: int - paramArray: - description: Is it an array. - type: bool - parameterName: - description: Name of template param. - type: str - provider: - description: Provider. - type: str - range: - description: Configuration Template Project's range. - elements: dict - suboptions: - id: - description: UUID of range. - type: str - maxValue: - description: Max value of range. - type: int - minValue: - description: Min value of range. - type: int - type: list - required: - description: Is param required. - type: bool - selection: - description: Configuration Template Project's selection. - suboptions: - defaultSelectedValues: - description: Default selection values. - elements: str - type: list - id: - description: UUID of selection. - type: str - selectionType: - description: Type of selection(SINGLE_SELECT or MULTI_SELECT). - type: str - selectionValues: - description: Selection values. - type: dict - type: dict - type: list - validationErrors: - description: Configuration Template Project's validationErrors. - suboptions: - rollbackTemplateErrors: - description: Validation or design conflicts errors of rollback template. - elements: dict - type: list - templateErrors: - description: Validation or design conflicts errors. - elements: dict - type: list - templateId: - description: UUID of template. - type: str - templateVersion: - description: Current version of template. - type: str - type: dict - version: - description: Current version of template. - type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates CreateProject description: Complete reference of the CreateProject API. @@ -591,164 +97,7 @@ - id: string name: string templates: - - author: string - composite: true - containingTemplates: - - composite: true - description: string - deviceTypes: - - productFamily: string - productSeries: string - productType: string - id: string - language: string - name: string - projectName: string - rollbackTemplateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - tags: - - id: string - name: string - templateContent: string - templateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - version: string - createTime: 0 - customParamsOrder: true - description: string - deviceTypes: - - productFamily: string - productSeries: string - productType: string - failurePolicy: string - id: string - language: string - lastUpdateTime: 0 - latestVersionTime: 0 - name: string - parentTemplateId: string - projectId: string - projectName: string - rollbackTemplateContent: string - rollbackTemplateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - softwareType: string - softwareVariant: string - softwareVersion: string - tags: - - id: string - name: string - templateContent: string - templateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - validationErrors: - rollbackTemplateErrors: - - {} - templateErrors: - - {} - templateId: string - templateVersion: string - version: string + - {} - name: Update all cisco.dnac.configuration_template_project: @@ -768,165 +117,7 @@ tags: - id: string name: string - templates: - - author: string - composite: true - containingTemplates: - - composite: true - description: string - deviceTypes: - - productFamily: string - productSeries: string - productType: string - id: string - language: string - name: string - projectName: string - rollbackTemplateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - tags: - - id: string - name: string - templateContent: string - templateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - version: string - createTime: 0 - customParamsOrder: true - description: string - deviceTypes: - - productFamily: string - productSeries: string - productType: string - failurePolicy: string - id: string - language: string - lastUpdateTime: 0 - latestVersionTime: 0 - name: string - parentTemplateId: string - projectId: string - projectName: string - rollbackTemplateContent: string - rollbackTemplateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - softwareType: string - softwareVariant: string - softwareVersion: string - tags: - - id: string - name: string - templateContent: string - templateParams: - - binding: string - customOrder: 0 - dataType: string - defaultValue: string - description: string - displayName: string - group: string - id: string - instructionText: string - key: string - notParam: true - order: 0 - paramArray: true - parameterName: string - provider: string - range: - - id: string - maxValue: 0 - minValue: 0 - required: true - selection: - defaultSelectedValues: - - string - id: string - selectionType: string - selectionValues: {} - validationErrors: - rollbackTemplateErrors: - - {} - templateErrors: - - {} - templateId: string - templateVersion: string - version: string + templates: {} - name: Delete by id cisco.dnac.configuration_template_project: @@ -941,7 +132,6 @@ projectId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_project_info.py b/plugins/modules/configuration_template_project_info.py index f200203db6..3846cc728d 100644 --- a/plugins/modules/configuration_template_project_info.py +++ b/plugins/modules/configuration_template_project_info.py @@ -34,8 +34,8 @@ - ProjectId path parameter. ProjectId(UUID) of project to get project details. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetsAListOfProjects description: Complete reference of the GetsAListOfProjects API. @@ -83,7 +83,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -102,213 +101,6 @@ "id": "string", "lastUpdateTime": 0, "name": "string", - "templates": [ - { - "tags": [ - { - "id": "string", - "name": "string" - } - ], - "author": "string", - "composite": true, - "containingTemplates": [ - { - "tags": [ - { - "id": "string", - "name": "string" - } - ], - "composite": true, - "description": "string", - "deviceTypes": [ - { - "productFamily": "string", - "productSeries": "string", - "productType": "string" - } - ], - "id": "string", - "language": "string", - "name": "string", - "projectName": "string", - "rollbackTemplateParams": [ - { - "binding": "string", - "customOrder": 0, - "dataType": "string", - "defaultValue": "string", - "description": "string", - "displayName": "string", - "group": "string", - "id": "string", - "instructionText": "string", - "key": "string", - "notParam": true, - "order": 0, - "paramArray": true, - "parameterName": "string", - "provider": "string", - "range": [ - { - "id": "string", - "maxValue": 0, - "minValue": 0 - } - ], - "required": true, - "selection": { - "defaultSelectedValues": [ - "string" - ], - "id": "string", - "selectionType": "string", - "selectionValues": {} - } - } - ], - "templateContent": "string", - "templateParams": [ - { - "binding": "string", - "customOrder": 0, - "dataType": "string", - "defaultValue": "string", - "description": "string", - "displayName": "string", - "group": "string", - "id": "string", - "instructionText": "string", - "key": "string", - "notParam": true, - "order": 0, - "paramArray": true, - "parameterName": "string", - "provider": "string", - "range": [ - { - "id": "string", - "maxValue": 0, - "minValue": 0 - } - ], - "required": true, - "selection": { - "defaultSelectedValues": [ - "string" - ], - "id": "string", - "selectionType": "string", - "selectionValues": {} - } - } - ], - "version": "string" - } - ], - "createTime": 0, - "customParamsOrder": true, - "description": "string", - "deviceTypes": [ - { - "productFamily": "string", - "productSeries": "string", - "productType": "string" - } - ], - "failurePolicy": "string", - "id": "string", - "language": "string", - "lastUpdateTime": 0, - "latestVersionTime": 0, - "name": "string", - "parentTemplateId": "string", - "projectId": "string", - "projectName": "string", - "rollbackTemplateContent": "string", - "rollbackTemplateParams": [ - { - "binding": "string", - "customOrder": 0, - "dataType": "string", - "defaultValue": "string", - "description": "string", - "displayName": "string", - "group": "string", - "id": "string", - "instructionText": "string", - "key": "string", - "notParam": true, - "order": 0, - "paramArray": true, - "parameterName": "string", - "provider": "string", - "range": [ - { - "id": "string", - "maxValue": 0, - "minValue": 0 - } - ], - "required": true, - "selection": { - "defaultSelectedValues": [ - "string" - ], - "id": "string", - "selectionType": "string", - "selectionValues": {} - } - } - ], - "softwareType": "string", - "softwareVariant": "string", - "softwareVersion": "string", - "templateContent": "string", - "templateParams": [ - { - "binding": "string", - "customOrder": 0, - "dataType": "string", - "defaultValue": "string", - "description": "string", - "displayName": "string", - "group": "string", - "id": "string", - "instructionText": "string", - "key": "string", - "notParam": true, - "order": 0, - "paramArray": true, - "parameterName": "string", - "provider": "string", - "range": [ - { - "id": "string", - "maxValue": 0, - "minValue": 0 - } - ], - "required": true, - "selection": { - "defaultSelectedValues": [ - "string" - ], - "id": "string", - "selectionType": "string", - "selectionValues": {} - } - } - ], - "validationErrors": { - "rollbackTemplateErrors": {}, - "templateErrors": {}, - "templateId": "string", - "templateVersion": "string" - }, - "version": "string" - } - ] + "templates": {} } """ diff --git a/plugins/modules/configuration_template_version_create.py b/plugins/modules/configuration_template_version_create.py index d0317ea84c..b95eb03548 100644 --- a/plugins/modules/configuration_template_version_create.py +++ b/plugins/modules/configuration_template_version_create.py @@ -23,8 +23,8 @@ description: UUID of template. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates VersionTemplate description: Complete reference of the VersionTemplate API. @@ -52,7 +52,6 @@ templateId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/configuration_template_version_info.py b/plugins/modules/configuration_template_version_info.py index 0dfdb8a930..2d148981f3 100644 --- a/plugins/modules/configuration_template_version_info.py +++ b/plugins/modules/configuration_template_version_info.py @@ -24,8 +24,8 @@ - TemplateId path parameter. TemplateId(UUID) to get list of versioned templates. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetsAllTheVersionsOfAGivenTemplate description: Complete reference of the GetsAllTheVersionsOfAGivenTemplate API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/credential_to_site_by_siteid_create_v2.py b/plugins/modules/credential_to_site_by_siteid_create_v2.py index 1ee9e33a91..68d88b5f09 100644 --- a/plugins/modules/credential_to_site_by_siteid_create_v2.py +++ b/plugins/modules/credential_to_site_by_siteid_create_v2.py @@ -11,7 +11,7 @@ description: - Manage operation create of the resource Credential To Site By Siteid Create V2. - API to assign Device Credential to a site. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -38,8 +38,8 @@ description: SNMPv3 Credential Id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings AssignDeviceCredentialToSiteV2 description: Complete reference of the AssignDeviceCredentialToSiteV2 API. @@ -72,7 +72,6 @@ snmpV3Id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_configs_backup_workflow_manager.py b/plugins/modules/device_configs_backup_workflow_manager.py new file mode 100644 index 0000000000..2658c09ce6 --- /dev/null +++ b/plugins/modules/device_configs_backup_workflow_manager.py @@ -0,0 +1,623 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2024, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type +__author__ = ("Abinash Mishra, Madhan Sankaranarayanan") + +DOCUMENTATION = r""" +--- +module: device_configs_backup_workflow_manager +short_description: Resource module for device_configs_backup functions +description: +- Manage operation related to taking the backup of running config, static config and vlan.dat.bat +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.workflow_manager_params +author: Abinash Mishra (@abimishr) + Madhan Sankaranarayanan (@madhansansel) +options: + config_verify: + description: Set to True to verify the Cisco Catalyst Center config after applying the playbook config. + type: bool + default: False + state: + description: The state of Cisco Catalyst Center after module completion. + type: str + choices: [ merged ] + default: merged + config: + description: + - List of details regarding the device configuration backups being taken + - Alteast one of the paramters mentioned in the suboptions must be passed in config + type: list + elements: dict + required: true + suboptions: + hostname: + description: Hostname of the device as displayed on the inventory GUI of Cisco Catalyst Center + type: str + management_ip_address: + description: IP address of the device as displayed on the inventory GUI of Cisco Catalyst Center + type: str + mac_address: + description: Mac address of the device as displayed on the inventory GUI of Cisco Catalyst Center + type: str + serial_number: + description: Serial number of the device as displayed on the inventory GUI of Cisco Catalyst Center + type: str + family: + description: Family of the device(s) as displayed on the inventory GUI of Cisco Catalyst Center + type: str + type: + description: Specifies the type of the device(s) from the family, like Cisco Catalyst 9300 Switch or Cisco Catalyst 9500 Switch + type: str + series: + description: Specifies the series of the device(s) from the type, like Cisco Catalyst 9300 Series Switches + type: str + collection_status: + description: Specifies the collection status of the device(s) on the GUI of Cisco Catalyst Center + type: str + file_path: + description: + - Location of the path or folder where the configs need to be exported in local system. + - If the file_path is not provided, the backup file(s) will be stored in a directory named + "tmp" in the same directory as the playbook. + type: str + default: tmp + file_password: + description: + - Optional file password for zipping and unzipping the config file. + - Minimum password length is 8 and it should contain atleast one lower case letter, one uppercase + letter, one digit and one special characters from -=\\\\\\\\;,./~!@$%^&*()_+{}[]|:?" + type: str +requirements: + - dnacentersdk == 2.6.10 + - python >= 3.5 +notes: + - SDK Methods used are devices.Devices.get_device_list, + configuration_archive.ConfigurationsArchive.export_device_configurations, + task.Task.get_task_by_id + - Paths used are get /dna/intent/api/v1/network-device + post dna/intent/api/v1/network-device-archive/cleartext + get /dna/intent/api/v1/task/${taskId} + +""" + +EXAMPLES = r""" +- name: Take backup of a 9300 wired device + cisco.dnac.device_configs_backup_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{dnac_log_level}}" + state: merged + config: + - hostname: NY-BN-9500.cisco.local + management_ip_address: 205.1.1.4 + serial_number: F2AKI0082J + family: Switches and Hubs + type: Cisco Catalyst 9300 Switch + series: Cisco Catalyst 9300 Series Switches + collection_status: Managed + file_path: /home/admin/madhan_ansible/collections/ansible_collections/cisco/dnac/playbooks/new_tmp +""" + +RETURN = r""" +# Case_1: Successful creation and exportation of device configs +response_1: + description: A dictionary with with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: dict + sample: > + { + "response": + { + "response": String, + "version": String + }, + "msg": String + } + +# Case_2: Error while taking a device_configs_backup +response_2: + description: A string with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: list + sample: > + { + "response": [], + "msg": String + } +""" +# common approach when a module relies on optional dependencies that are not available during the validation process. +try: + import pyzipper + HAS_PYZIPPER = True +except ImportError: + HAS_PYZIPPER = False + pyzipper = None + +try: + import pathlib +except ImportError: + pathlib = None + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.dnac.plugins.module_utils.dnac import ( + DnacBase, + validate_list_of_dicts +) +from io import BytesIO +import random +import string +import re +import time + + +class Device_configs_backup(DnacBase): + + """ + Class containing member attributes for device_configs_backup workflow_manager module + """ + def __init__(self, module): + super().__init__(module) + + def validate_input(self): + """ + Validate the fields provided in the playbook. Checks the + configuration provided in the playbook against a predefined + specification to ensure it adheres to the expected structure + and data types. + + Parameters: + - self: The instance of the class containing the 'config' attribute + to be validated. + Returns: + The method returns an instance of the class with updated attributes: + - self.msg: A message describing the validation result. + - self.status: The status of the validation (either 'success' or 'failed'). + - self.validated_config: If successful, a validated version of the + 'config' parameter. + Example: + To use this method, create an instance of the class and call + 'validate_input' on it.If the validation succeeds, 'self.status' + will be 'success'and 'self.validated_config' will contain the + validated configuration. If it fails, 'self.status' will be + 'failed', and 'self.msg' will describe the validation issues. + """ + + if not self.config: + self.msg = "config not available in playbook for validattion" + self.status = "success" + return self + + device_configs_backup_spec = { + 'hostname': {'type': 'str', 'required': False}, + 'management_ip_address': {'type': 'str', 'required': False}, + 'mac_address': {'type': 'str', 'required': False}, + 'serial_number': {'type': 'str', 'required': False}, + 'family': {'type': 'str', 'required': False}, + 'type': {'type': 'str', 'required': False}, + 'series': {'type': 'str', 'required': False}, + 'collection_status': {'type': 'str', 'required': False}, + 'file_path': {'type': 'str', 'required': False, 'default': 'tmp'}, + 'file_password': {'type': 'str', 'required': False} + } + # Validate device_configs_backup params + valid_device_configs_backup, invalid_params = validate_list_of_dicts( + self.config, device_configs_backup_spec + ) + if invalid_params: + self.msg = "Invalid parameters in playbook: {0}".format( + "\n".join(invalid_params)) + self.log(str(self.msg), "ERROR") + self.status = "failed" + return self + + self.validated_config = valid_device_configs_backup + self.msg = "Successfully validated playbook configuration parameters using 'validate_input': {0}".format(str(valid_device_configs_backup)) + self.status = "success" + return self + + def validate_ipv4_address(self): + """ + Validates the management ip adress passed by the user + """ + + ip_address = self.validated_config[0].get("management_ip_address") + + if ip_address: + if self.is_valid_ipv4(ip_address) is False: + msg = "IP address {0} is not valid".format(ip_address) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + + self.log("Validated IP address collected for config collection is {0}".format(ip_address), "INFO") + + def get_have(self): + """ + Get the current device_configs_backup details + Args: + self: The instance of the class containing the 'config' attribute to be validated. + Returns: + The method returns an instance of the class with updated attributes: + - self. + Example: + Stored paramters are used to call the APIs to store the validated configs + """ + + have = {} + have = self.validated_config[0] + self.have = have + self.log("Parameters collected from get have api are {0}".format(self.have), "INFO") + return self + + def get_device_ids_list(self): + """ + Fethces the list of device ids from various paramters passed in the playbook + Args: + self: The instance of the class containing the 'config' attribute to be validated. + Returns: + dev_id_list: The list of device ids based on the parameters passed by the user + Example: + Stored paramters like management ip address/ family can be used to fetch the device ids + list + """ + + device_params = self.validated_config[0] + if device_params.get("file_password"): + if len(device_params) - 1 == 0: + msg = "Please provide atleast one device parameter as mentioned in the documentation to fetch device configs" + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + + response = self.dnac_apply['exec']( + family="devices", + function='get_device_list', + params=device_params, + op_modifies=True + ) + self.log("Reponse collected from the API 'get_device_list' is {0}".format(str(response)), "DEBUG") + device_list = response.get("response") + + self.log("Length of the device list fetched from the API 'get_device_list' is {0}".format(str(device_list)), "INFO") + if len(device_list) == 0: + msg = "Couldn't find any devices in the inventory that match the given parameters." + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + + dev_id_list = [id.get("id") for id in device_list] + self.log("Device Ids list collected is {0}".format(dev_id_list), "INFO") + return dev_id_list + + def password_generator(self): + """ + Creates a password that matches Cisco Catalyst Center's requirements + Min password length is 8 and it should contain atleast one lower case letter, + one uppercase letter, one digit and one special characters from -=\\\\;,./~!@#$%^&*()_+{}[]|:? + """ + + punctuation = "-=;,.~!@#$%^&*()_+{}[]|:?" + password_chars = punctuation + string.ascii_letters + string.digits + password_list = [ + random.choice(punctuation), + random.choice(string.ascii_uppercase), + random.choice(string.ascii_lowercase), + random.choice(string.digits), + random.choice(password_chars), + random.choice(password_chars), + random.choice(password_chars), + random.choice(password_chars), + ] + password = [] + while password_list: + password.append( + password_list.pop(random.randint(0, len(password_list) - 1)) + ) + password = "".join(password) + + self.log("File password is generated using the password generator API", "INFO") + return password + + def validate_password(self, password=None): + """ + Validates the user-defined password for Cisco catalyst Center's requirements + Min password length is 8 and it should contain atleast one lower case letter, + one uppercase letter, one digit and one special characters from -=\\\\;,./~!@#$%^&*()_+{}[]|:? + """ + + pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[-=\\;,./~!@#$%^&*()_+{}[\]|:?\"]).{8,}$" + self.log("User defined password is {0}".format(password), "DEBUG") + if re.match(pattern, password): + return True + else: + return False + + def get_want(self): + """ + Get all device_configs_backup related informantion from the playbook and preprare it to call + the API to export the device configurations. + Args: + self: The instance of the class containing the 'config' attribute to be validated. + Returns: + The method returns an instance of the class with updated attributes: + - self.want: A dictionary of paramters obtained from the playbook + - self.msg: A message indicating all the paramters from the playbook are + collected + - self.status: Success + Example: + It stores all the paramters passed from the playbook for further processing + before calling the APIs + """ + + self.want = {} + + self.want["deviceId"] = self.get_device_ids_list() + if self.validated_config[0].get("file_password"): + password = self.validated_config[0].get("file_password") + if self.validate_password(password=password) is True: + self.want["password"] = password + + else: + msg = "Invalid input as Invalid password. Min password length is 8 and it should contain" + \ + "atleast one lower case letter, one uppercase letter, one digit and one special characters" + \ + "from -=\\\\\\\\;,./~!@#$%^&*()_+{}[]|:?" + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + + else: + self.want["password"] = self.password_generator() + + self.msg = "Successfully collected all parameters from playbook " + \ + "for comparison" + self.status = "success" + self.log(self.msg, "INFO") + return self + + def get_device_config(self): + """ + Cisco Catalyst Center creates a ZIP file by calling the export API + """ + + response = self.dnac_apply['exec']( + family="configuration_archive", + function='export_device_configurations', + params=self.want, + op_modifies=True + ) + response = response.get("response") + + self.log("Response collected from 'export_device_configurations' API is {0}".format(str(response)), "DEBUG") + if response.get("errorCode"): + msg = response.get("message") + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + + task_id = response.get("taskId") + self.log("Task Id of the task is {0}".format(task_id), "INFO") + return task_id + + def get_task_status(self, task_id=None): + """ + 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: + - task_id: The ID of the task to monitor. + + Returns: + - result: True if the task completed successfully, False otherwise. + With True it also returns additionalStatusURL + """ + + 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("Response collected from 'get task by id' is {0}".format(response), "DEBUG") + if response.get('isError') or re.search( + 'failed', response.get('progress'), flags=re.IGNORECASE + ): + msg = 'Device backup 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') + self.log("Progress of the task is {0}".format(str(progress)), "DEBUG") + + if progress == "Device configuration Successfully exported as password protected ZIP.": + result = True + additionalStatusURL = response.get("additionalStatusURL") + self.log("The backup process is completed", "INFO") + self.result.update(dict(backup_task=response)) + return (result, additionalStatusURL) + + self.log("The progress status is {0}, continue to check the status after 3 seconds. Putting into sleep for 3 seconds".format(progress), "INFO") + time.sleep(3) + + def download_file(self, additionalStatusURL=None): + """ + Downloading file and store locally + Using unzip path settings for directory + Paremetrs: + self: The instance of the class containing the 'config' attribute to be validated. + additionalStatusURL: This paramter is used to fetch the file id + + Returns: + - result: True if the file downloaded and uzipped, else False + """ + + self.log("Downloading: {0}".format(additionalStatusURL), "INFO") + file_id = additionalStatusURL.split("/")[-1] + + try: + response = self.dnac._exec( + family="file", + function='download_a_file_by_fileid', + op_modifies=True, + params={"file_id": file_id}, + ) + self.log("Received API response from 'download_a_file_by_fileid': {0}".format(str(response)), "DEBUG") + except Exception as e: + self.log("File couldn't be downloaded: {0}".format(e), "INFO") + return False + + if isinstance(response, dict) and response.get("errorCode"): + self.log(response.get("message"), "CRITICAL") + self.module.fail_json(msg=response.get("message")) + + zip_data = BytesIO(response.data) + self.log("ZIP data collected is {0}".format(zip_data), "INFO") + + pathlib.Path(self.have.get("file_path")).mkdir(parents=True, exist_ok=True) + self.log("Unzipping file after completion of download", "INFO") + + try: + with pyzipper.AESZipFile(zip_data, 'r') as f: + f.pwd = bytes(self.want.get("password"), encoding="utf-8") + f.extractall(path=str(self.have.get("file_path"))) + except Exception as e: + self.log("Error in unzipping: {0}".format(e), "CRITICAL") + return False + + self.log("Unzipping complete", "INFO") + return True + + def get_diff_merged(self): + """ + Add to device_configs_backup database + Args: + self: An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + object: An instance of the class with updated results and status + based on the processing of differences. + Description: + The function processes the differences and, depending on the + changes required, it may add, update,or resynchronize devices in + Cisco Catalyst Center. The updated results and status are stored in the + class instance for further use. + """ + + if self.have.get('management_ip_address'): + self.validate_ipv4_address() + + task_id = self.get_device_config() + result, additionalStatusURL = self.get_task_status(task_id=task_id) + + if result is True: + download_status = self.download_file(additionalStatusURL=additionalStatusURL) + if download_status is True: + self.result['response'] = task_id + self.result['msg'] = "Device configs got downloaded" + self.log(self.result['msg'], "INFO") + self.result['changed'] = True + return self + return self + + def verify_diff_merged(self): + """ + Verify the merged status(Creation/Updation) of Discovery in Cisco Catalyst Center. + Args: + - self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Return: + - self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Description: + This method checks the merged status of a configuration in Cisco Catalyst Center by + retrieving the current state (have) and desired state (want) of the configuration, + logs the states, and validates whether the specified device(s) exists in the DNA + Center configuration's Discovery Database. + """ + + self.log("Current State (have): {0}".format(str(self.have)), "INFO") + self.log("Desired State (want): {0}".format(str(self.want)), "INFO") + # Code to validate Cisco Catalyst Center config for merged state + window_seconds = 10 + current_time = time.time() + window_start_time = current_time - window_seconds + files_modified_within_window = [ + f.name for f in pathlib.Path(self.have.get("file_path")).iterdir() + if f.stat().st_mtime > window_start_time + ] + + if len(files_modified_within_window) > 0: + self.log("Backup has been taken in the following files {0}".format(str(files_modified_within_window)), "INFO") + else: + self.log("Backup has not been taken, please check", "WARNING") + + self.status = "success" + + return self + + +def main(): + + """ + main entry point for module execution + """ + + element_spec = {'dnac_host': {'required': True, 'type': 'str'}, + 'dnac_port': {'type': 'str', 'default': '443'}, + 'dnac_username': {'type': 'str', 'default': 'admin', 'aliases': ['user']}, + 'dnac_password': {'type': 'str', 'no_log': True}, + 'dnac_verify': {'type': 'bool', 'default': 'True'}, + 'dnac_version': {'type': 'str', 'default': '2.2.3.3'}, + 'dnac_debug': {'type': 'bool', 'default': False}, + 'dnac_log': {'type': 'bool', 'default': False}, + "dnac_log_level": {"type": 'str', "default": 'WARNING'}, + "dnac_log_file_path": {"type": 'str', "default": 'dnac.log'}, + "dnac_log_append": {"type": 'bool', "default": True}, + "config_verify": {"type": 'bool', "default": False}, + 'dnac_api_task_timeout': {'type': 'int', "default": 1200}, + 'dnac_task_poll_interval': {'type': 'int', "default": 2}, + 'validate_response_schema': {'type': 'bool', 'default': True}, + 'config': {'required': True, 'type': 'list', 'elements': 'dict'}, + 'state': {'default': 'merged', 'choices': ['merged']} + } + module = AnsibleModule(argument_spec=element_spec, + supports_check_mode=False) + ccc_device_configs_backup = Device_configs_backup(module) + + state = ccc_device_configs_backup.params.get("state") + if state not in ccc_device_configs_backup.supported_states: + ccc_device_configs_backup.status = "invalid" + ccc_device_configs_backup.msg = "State {0} is invalid".format(state) + ccc_device_configs_backup.check_return_status() + + config_verify = ccc_device_configs_backup.params.get("config_verify") + ccc_device_configs_backup.validate_input().check_return_status() + + for config in ccc_device_configs_backup.validated_config: + ccc_device_configs_backup.reset_values() + ccc_device_configs_backup.get_have().check_return_status() + ccc_device_configs_backup.get_want().check_return_status() + ccc_device_configs_backup.get_diff_state_apply[state]().check_return_status() + if config_verify: + ccc_device_configs_backup.verify_diff_state_apply[state]().check_return_status() + + module.exit_json(**ccc_device_configs_backup.result) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/device_configurations_export.py b/plugins/modules/device_configurations_export.py index 4d7ba14db0..c205a51608 100644 --- a/plugins/modules/device_configurations_export.py +++ b/plugins/modules/device_configurations_export.py @@ -17,15 +17,17 @@ author: Rafael Campos (@racampos) options: deviceId: - description: Device Id. - elements: str - type: list + description: UUIDs of the devices for which configurations need to be exported. + type: str password: - description: Password. + description: Password for the zip file to protect exported configurations. Must + contain, at minimum 8 characters, one lowercase letter, one uppercase letter, + one number, one special character(-=;,./~!@#$%^&*()_+{}| ?). It may not contain + white space or the characters <>. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Archive ExportDeviceConfigurations description: Complete reference of the ExportDeviceConfigurations API. @@ -49,12 +51,10 @@ dnac_port: "{{dnac_port}}" dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" - deviceId: - - string + deviceId: string password: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -62,10 +62,10 @@ type: dict sample: > { + "version": "string", "response": { - "taskId": "string", - "url": "string" - }, - "version": "string" + "url": "string", + "taskId": "string" + } } """ diff --git a/plugins/modules/device_credential_create.py b/plugins/modules/device_credential_create.py index b26ec83a09..10662f946c 100644 --- a/plugins/modules/device_credential_create.py +++ b/plugins/modules/device_credential_create.py @@ -10,7 +10,9 @@ short_description: Resource module for Device Credential Create description: - Manage operation create of the resource Device Credential Create. -- API to create device credentials. +- > + API to create device credentials. This API has been deprecated and will not be available in a Cisco DNA Center + release after August 1st 2024 23 59 59 GMT. Please refer new Intent API Create Global Credentials V2. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -48,7 +50,7 @@ type: str port: description: Port for http read credential. - type: int + type: float username: description: User name of the http read credential. type: str @@ -65,7 +67,7 @@ type: str port: description: Port for http write credential. - type: int + type: float username: description: User name of the http write credential. type: str @@ -120,8 +122,8 @@ type: list type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings CreateDeviceCredentials description: Complete reference of the CreateDeviceCredentials API. @@ -177,7 +179,6 @@ username: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_credential_delete.py b/plugins/modules/device_credential_delete.py index 73d1449977..716bcfef0b 100644 --- a/plugins/modules/device_credential_delete.py +++ b/plugins/modules/device_credential_delete.py @@ -10,7 +10,9 @@ short_description: Resource module for Device Credential Delete description: - Manage operation delete of the resource Device Credential Delete. -- Delete device credential. +- > + Delete device credential. This API has been deprecated and will not be available in a Cisco DNA Center release + after August 1st 2024 23 59 59 GMT. Please refer new Intent API Delete Global Credentials V2. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -20,8 +22,8 @@ description: Id path parameter. Global credential id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings DeleteDeviceCredential description: Complete reference of the DeleteDeviceCredential API. @@ -48,7 +50,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_credential_info.py b/plugins/modules/device_credential_info.py index 27175a6692..c0db3bbcff 100644 --- a/plugins/modules/device_credential_info.py +++ b/plugins/modules/device_credential_info.py @@ -10,7 +10,9 @@ short_description: Information module for Device Credential description: - Get all Device Credential. -- API to get device credential details. +- > + API to get device credential details. This API has been deprecated and will not be available in a Cisco DNA Center + release after August 1st 2024 23 59 59 GMT. Please refer new Intent API Get All Global Credentials V2. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -24,8 +26,8 @@ - SiteId query parameter. Site id to retrieve the credential details associated with the site. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings GetDeviceCredentialDetails description: Complete reference of the GetDeviceCredentialDetails API. @@ -54,7 +56,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_credential_intent.py b/plugins/modules/device_credential_intent.py index 3b887aa8d2..0bd15f1fad 100644 --- a/plugins/modules/device_credential_intent.py +++ b/plugins/modules/device_credential_intent.py @@ -298,7 +298,7 @@ description: snmp_v3 Credential Id. Use Description or Id. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Discovery CreateGlobalCredentialsV2 diff --git a/plugins/modules/device_credential_update.py b/plugins/modules/device_credential_update.py index 7c5cafd5ba..5a25c48501 100644 --- a/plugins/modules/device_credential_update.py +++ b/plugins/modules/device_credential_update.py @@ -10,7 +10,9 @@ short_description: Resource module for Device Credential Update description: - Manage operation update of the resource Device Credential Update. -- API to update device credentials. +- > + API to update device credentials. This API has been deprecated and will not be available in a Cisco DNA Center + release after August 1st 2024 23 59 59 GMT. Please refer new Intent API Update Global Credentials V2. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -132,8 +134,8 @@ type: dict type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateDeviceCredentials description: Complete reference of the UpdateDeviceCredentials API. @@ -195,7 +197,6 @@ username: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_credential_workflow_manager.py b/plugins/modules/device_credential_workflow_manager.py index a6d188de40..c7b8e8921e 100644 --- a/plugins/modules/device_credential_workflow_manager.py +++ b/plugins/modules/device_credential_workflow_manager.py @@ -298,7 +298,7 @@ description: snmp_v3 Credential Id. Use Description or Id. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco Catalyst Center documentation for Discovery CreateGlobalCredentialsV2 @@ -951,15 +951,15 @@ def get_cli_params(self, cliDetails): def get_snmpV2cRead_params(self, snmpV2cReadDetails): """ - Format the snmpV2cRead parameters for the snmpV2cRead + Format the snmp_v2c_read parameters for the snmp_v2c_read credential configuration in Cisco Catalyst Center. Parameters: snmpV2cReadDetails (list of dict) - Cisco Catalyst Center - Details containing snmpV2cRead Credentials. + Details containing snmp_v2c_read Credentials. Returns: - snmpV2cRead (list of dict) - Processed snmpV2cRead credential + snmpV2cRead (list of dict) - Processed snmp_v2c_read credential data in the format suitable for the Cisco Catalyst Center config. """ @@ -977,15 +977,15 @@ def get_snmpV2cRead_params(self, snmpV2cReadDetails): def get_snmpV2cWrite_params(self, snmpV2cWriteDetails): """ - Format the snmpV2cWrite parameters for the snmpV2cWrite + Format the snmp_v2c_write parameters for the snmp_v2c_write credential configuration in Cisco Catalyst Center. Parameters: snmpV2cWriteDetails (list of dict) - Cisco Catalyst Center - Details containing snmpV2cWrite Credentials. + Details containing snmp_v2c_write Credentials. Returns: - snmpV2cWrite (list of dict) - Processed snmpV2cWrite credential + snmpV2cWrite (list of dict) - Processed snmp_v2c_write credential data in the format suitable for the Cisco Catalyst Center config. """ @@ -1003,15 +1003,15 @@ def get_snmpV2cWrite_params(self, snmpV2cWriteDetails): def get_httpsRead_params(self, httpsReadDetails): """ - Format the httpsRead parameters for the httpsRead + Format the https_read parameters for the https_read credential configuration in Cisco Catalyst Center. Parameters: httpsReadDetails (list of dict) - Cisco Catalyst Center - Details containing httpsRead Credentials. + Details containing https_read Credentials. Returns: - httpsRead (list of dict) - Processed httpsRead credential + httpsRead (list of dict) - Processed https_read credential data in the format suitable for the Cisco Catalyst Center config. """ @@ -1031,15 +1031,15 @@ def get_httpsRead_params(self, httpsReadDetails): def get_httpsWrite_params(self, httpsWriteDetails): """ - Format the httpsWrite parameters for the httpsWrite + Format the https_write parameters for the https_write credential configuration in Cisco Catalyst Center. Parameters: httpsWriteDetails (list of dict) - Cisco Catalyst Center - Details containing httpsWrite Credentials. + Details containing https_write Credentials. Returns: - httpsWrite (list of dict) - Processed httpsWrite credential + httpsWrite (list of dict) - Processed https_write credential data in the format suitable for the Cisco Catalyst Center config. """ @@ -1059,13 +1059,13 @@ def get_httpsWrite_params(self, httpsWriteDetails): def get_snmpV3_params(self, snmpV3Details): """ - Format the snmpV3 parameters for the snmpV3 credential configuration in Cisco Catalyst Center. + Format the snmp_v3 parameters for the snmp_v3 credential configuration in Cisco Catalyst Center. Parameters: - snmpV3Details (list of dict) - Cisco Catalyst Center details containing snmpV3 Credentials. + snmpV3Details (list of dict) - Cisco Catalyst Center details containing snmp_v3 Credentials. Returns: - snmpV3 (list of dict) - Processed snmpV3 credential + snmpV3 (list of dict) - Processed snmp_v3 credential data in the format suitable for the Cisco Catalyst Center config. """ @@ -1128,8 +1128,8 @@ def get_cli_credentials(self, CredentialDetails, global_credentials): if item.get("description") == cliOldDescription \ and item.get("username") == cliOldUsername: if cliDetail: - self.msg = "More than one CLI credential with same \ - old_description and old_username. Pass ID." + self.msg = "There are multiple CLI credentials with the same old_description and old_username. " + \ + "Kindly provide the ID for the global device credentials." self.status = "failed" return self cliDetail = item @@ -1145,8 +1145,8 @@ def get_cli_credentials(self, CredentialDetails, global_credentials): if item.get("description") == cliDescription \ and item.get("username") == cliUsername: if cliDetail: - self.msg = "More than one CLI Credential with same \ - description and username. Pass ID." + self.msg = "There are multiple CLI credentials with the same description and username. " + \ + "Kindly provide the ID for the global device credentials." self.status = "failed" return self cliDetail = item @@ -1155,7 +1155,7 @@ def get_cli_credentials(self, CredentialDetails, global_credentials): def get_snmpV2cRead_credentials(self, CredentialDetails, global_credentials): """ - Get the current snmpV2cRead Credential from + Get the current snmp_v2c_read Credential from Cisco Catalyst Center based on the provided playbook details. Check this API using the check_return_status. @@ -1164,14 +1164,16 @@ def get_snmpV2cRead_credentials(self, CredentialDetails, global_credentials): global_credentials (dict) - All global device credentials details. Returns: - snmpV2cReadDetails (List) - The current snmpV2cRead. + snmpV2cReadDetails (List) - The current snmp_v2c_read. """ - # Playbook snmpV2cRead Credential details + # Playbook snmp_v2c_read Credential details all_snmpV2cRead = CredentialDetails.get("snmp_v2c_read") - # All snmpV2cRead details from the Cisco Catalyst Center + + # All snmp_v2c_read details from the Cisco Catalyst Center snmpV2cRead_details = global_credentials.get("snmpV2cRead") - # Cisco Catalyst Center details for the snmpV2cRead Credential given in the playbook + + # Cisco Catalyst Center details for the snmp_v2c_read Credential given in the playbook snmpV2cReadDetails = [] if all_snmpV2cRead and snmpV2cRead_details: for snmpV2cReadCredential in all_snmpV2cRead: @@ -1180,7 +1182,7 @@ def get_snmpV2cRead_credentials(self, CredentialDetails, global_credentials): if snmpV2cReadId: snmpV2cReadDetail = get_dict_result(snmpV2cRead_details, "id", snmpV2cReadId) if not snmpV2cReadDetail: - self.msg = "snmpV2cRead credential ID is invalid" + self.msg = "snmp_v2c_read credential ID is invalid" self.status = "failed" return self @@ -1192,7 +1194,7 @@ def get_snmpV2cRead_credentials(self, CredentialDetails, global_credentials): snmpV2cReadOldDescription ) if not snmpV2cReadDetail: - self.msg = "snmpV2cRead credential old_description is invalid" + self.msg = "snmp_v2c_read credential old_description is invalid" self.status = "failed" return self @@ -1208,7 +1210,7 @@ def get_snmpV2cRead_credentials(self, CredentialDetails, global_credentials): def get_snmpV2cWrite_credentials(self, CredentialDetails, global_credentials): """ - Get the current snmpV2cWrite Credential from + Get the current snmp_v2c_write Credential from Cisco Catalyst Center based on the provided playbook details. Check this API using the check_return_status. @@ -1217,14 +1219,16 @@ def get_snmpV2cWrite_credentials(self, CredentialDetails, global_credentials): global_credentials (dict) - All global device credentials details. Returns: - snmpV2cWriteDetails (List) - The current snmpV2cWrite. + snmpV2cWriteDetails (List) - The current snmp_v2c_write. """ - # Playbook snmpV2cWrite Credential details + # Playbook snmp_v2c_write Credential details all_snmpV2cWrite = CredentialDetails.get("snmp_v2c_write") - # All snmpV2cWrite details from the Cisco Catalyst Center + + # All snmp_v2c_write details from the Cisco Catalyst Center snmpV2cWrite_details = global_credentials.get("snmpV2cWrite") - # Cisco Catalyst Center details for the snmpV2cWrite Credential given in the playbook + + # Cisco Catalyst Center details for the snmp_v2c_write Credential given in the playbook snmpV2cWriteDetails = [] if all_snmpV2cWrite and snmpV2cWrite_details: for snmpV2cWriteCredential in all_snmpV2cWrite: @@ -1233,7 +1237,7 @@ def get_snmpV2cWrite_credentials(self, CredentialDetails, global_credentials): if snmpV2cWriteId: snmpV2cWriteDetail = get_dict_result(snmpV2cWrite_details, "id", snmpV2cWriteId) if not snmpV2cWriteDetail: - self.msg = "snmpV2cWrite credential ID is invalid" + self.msg = "snmp_v2c_write credential ID is invalid" self.status = "failed" return self @@ -1245,7 +1249,7 @@ def get_snmpV2cWrite_credentials(self, CredentialDetails, global_credentials): snmpV2cWriteOldDescription ) if not snmpV2cWriteDetail: - self.msg = "snmpV2cWrite credential old_description is invalid " + self.msg = "snmp_v2c_write credential old_description is invalid " self.status = "failed" return self @@ -1261,7 +1265,7 @@ def get_snmpV2cWrite_credentials(self, CredentialDetails, global_credentials): def get_httpsRead_credentials(self, CredentialDetails, global_credentials): """ - Get the current httpsRead Credential from + Get the current https_read Credential from Cisco Catalyst Center based on the provided playbook details. Check this API using the check_return_status. @@ -1270,14 +1274,16 @@ def get_httpsRead_credentials(self, CredentialDetails, global_credentials): global_credentials (dict) - All global device credentials details. Returns: - httpsReadDetails (List) - The current httpsRead. + httpsReadDetails (List) - The current https_read. """ - # Playbook httpsRead Credential details + # Playbook https_read Credential details all_httpsRead = CredentialDetails.get("https_read") - # All httpsRead details from the Cisco Catalyst Center + + # All https_read details from the Cisco Catalyst Center httpsRead_details = global_credentials.get("httpsRead") - # Cisco Catalyst Center details for the httpsRead Credential given in the playbook + + # Cisco Catalyst Center details for the https_read Credential given in the playbook httpsReadDetails = [] if all_httpsRead and httpsRead_details: for httpsReadCredential in all_httpsRead: @@ -1286,7 +1292,7 @@ def get_httpsRead_credentials(self, CredentialDetails, global_credentials): if httpsReadId: httpsReadDetail = get_dict_result(httpsRead_details, "id", httpsReadId) if not httpsReadDetail: - self.msg = "httpsRead credential Id is invalid" + self.msg = "https_read credential Id is invalid" self.status = "failed" return self @@ -1297,13 +1303,13 @@ def get_httpsRead_credentials(self, CredentialDetails, global_credentials): if item.get("description") == httpsReadOldDescription \ and item.get("username") == httpsReadOldUsername: if httpsReadDetail: - self.msg = "More than one httpsRead credential with same \ - old_description and old_username. Pass ID." + self.msg = "There are multiple https_read credentials with the same old_description and old_username. " + \ + "Kindly provide the ID for the global device credentials." self.status = "failed" return self httpsReadDetail = item if not httpsReadDetail: - self.msg = "httpsRead credential old_description or old_username is invalid" + self.msg = "https_read credential old_description or old_username is invalid" self.status = "failed" return self @@ -1314,8 +1320,8 @@ def get_httpsRead_credentials(self, CredentialDetails, global_credentials): if item.get("description") == httpsReadDescription \ and item.get("username") == httpsReadUsername: if httpsReadDetail: - self.msg = "More than one httpsRead credential with same \ - description and username. Pass ID." + self.msg = "There are multiple https_read credentials with the same description and username. " + \ + "Kindly provide the ID for the global device credentials." self.status = "failed" return self httpsReadDetail = item @@ -1324,7 +1330,7 @@ def get_httpsRead_credentials(self, CredentialDetails, global_credentials): def get_httpsWrite_credentials(self, CredentialDetails, global_credentials): """ - Get the current httpsWrite Credential from + Get the current https_write Credential from Cisco Catalyst Center based on the provided playbook details. Check this API using the check_return_status. @@ -1333,14 +1339,16 @@ def get_httpsWrite_credentials(self, CredentialDetails, global_credentials): global_credentials (dict) - All global device credentials details. Returns: - httpsWriteDetails (List) - The current httpsWrite. + httpsWriteDetails (List) - The current https_write. """ - # Playbook httpsWrite Credential details + # Playbook https_write Credential details all_httpsWrite = CredentialDetails.get("https_write") - # All httpsWrite details from the Cisco Catalyst Center + + # All https_write details from the Cisco Catalyst Center httpsWrite_details = global_credentials.get("httpsWrite") - # Cisco Catalyst Center details for the httpsWrite Credential given in the playbook + + # Cisco Catalyst Center details for the https_write Credential given in the playbook httpsWriteDetails = [] if all_httpsWrite and httpsWrite_details: for httpsWriteCredential in all_httpsWrite: @@ -1349,7 +1357,7 @@ def get_httpsWrite_credentials(self, CredentialDetails, global_credentials): if httpsWriteId: httpsWriteDetail = get_dict_result(httpsWrite_details, "id", httpsWriteId) if not httpsWriteDetail: - self.msg = "httpsWrite credential Id is invalid" + self.msg = "https_write credential Id is invalid" self.status = "failed" return self @@ -1360,14 +1368,14 @@ def get_httpsWrite_credentials(self, CredentialDetails, global_credentials): if item.get("description") == httpsWriteOldDescription \ and item.get("username") == httpsWriteOldUsername: if httpsWriteDetail: - self.msg = "More than one httpsWrite credential with same \ - old_description and old_username. Pass ID" + self.msg = "There are multiple https_write credentials with the same old_description and old_username. " + \ + "Kindly provide the ID for the global device credentials." self.status = "failed" return self httpsWriteDetail = item if not httpsWriteDetail: - self.msg = "httpsWrite credential old_description or \ - old_username is invalid" + self.msg = "https_write credential old_description or " + \ + "old_username is invalid" self.status = "failed" return self @@ -1377,13 +1385,18 @@ def get_httpsWrite_credentials(self, CredentialDetails, global_credentials): for item in httpsWrite_details: if item.get("description") == httpsWriteDescription \ and item.get("username") == httpsWriteUsername: + if httpsWriteDetail: + self.msg = "There are multiple https_write credentials with the same description and username. " + \ + "Kindly provide the ID for the global device credentials." + self.status = "failed" + return self httpsWriteDetail = item httpsWriteDetails.append(httpsWriteDetail) return httpsWriteDetails def get_snmpV3_credentials(self, CredentialDetails, global_credentials): """ - Get the current snmpV3 Credential from + Get the current snmp_v3 Credential from Cisco Catalyst Center based on the provided playbook details. Check this API using the check_return_status. @@ -1392,14 +1405,16 @@ def get_snmpV3_credentials(self, CredentialDetails, global_credentials): global_credentials (dict) - All global device credentials details. Returns: - snmpV3Details (List) - The current snmpV3. + snmpV3Details (List) - The current snmp_v3. """ - # Playbook snmpV3 Credential details + # Playbook snmp_v3 Credential details all_snmpV3 = CredentialDetails.get("snmp_v3") - # All snmpV3 details from the Cisco Catalyst Center + + # All snmp_v3 details from the Cisco Catalyst Center snmpV3_details = global_credentials.get("snmpV3") - # Cisco Catalyst Center details for the snmpV3 Credential given in the playbook + + # Cisco Catalyst Center details for the snmp_v3 Credential given in the playbook snmpV3Details = [] if all_snmpV3 and snmpV3_details: for snmpV3Credential in all_snmpV3: @@ -1408,7 +1423,7 @@ def get_snmpV3_credentials(self, CredentialDetails, global_credentials): if snmpV3Id: snmpV3Detail = get_dict_result(snmpV3_details, "id", snmpV3Id) if not snmpV3Detail: - self.msg = "snmpV3 credential id is invalid" + self.msg = "snmp_v3 credential id is invalid" self.status = "failed" return self @@ -1417,7 +1432,7 @@ def get_snmpV3_credentials(self, CredentialDetails, global_credentials): snmpV3Detail = get_dict_result(snmpV3_details, "description", snmpV3OldDescription) if not snmpV3Detail: - self.msg = "snmpV3 credential old_description is invalid" + self.msg = "snmp_v3 credential old_description is invalid" self.status = "failed" return self @@ -1533,8 +1548,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_cli_ptr] \ .update({values[i]: item.get(values[i])}) else: - self.msg = values[i] + " is mandatory for creating \ - cliCredential " + str(have_cli_ptr) + self.msg = values[i] + " is mandatory for creating cli_credential " + str(have_cli_ptr) self.status = "failed" return self @@ -1551,8 +1565,7 @@ def get_want_device_credentials(self, CredentialDetails): update_credential[update_cli_ptr] \ .update({"password": item.get("password")}) else: - self.msg = "password is mandatory for udpating \ - cliCredential " + str(have_cli_ptr) + self.msg = "password is mandatory for updating cli_credential " + str(have_cli_ptr) self.status = "failed" return self @@ -1592,8 +1605,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_snmpv2cread_ptr] \ .update({keys[i]: item.get(values[i])}) else: - self.msg = values[i] + " is mandatory for creating \ - snmpV2cRead " + str(have_snmpv2cread_ptr) + self.msg = values[i] + " is mandatory for creating snmp_v2c_read " + str(have_snmpv2cread_ptr) self.status = "failed" return self create_snmpv2cread_ptr = create_snmpv2cread_ptr + 1 @@ -1606,8 +1618,7 @@ def get_want_device_credentials(self, CredentialDetails): update_credential[update_snmpv2cread_ptr] \ .update({"readCommunity": item.get("read_community")}) else: - self.msg = "read_community is mandatory for updating \ - snmpV2cRead " + str(have_snmpv2cread_ptr) + self.msg = "read_community is mandatory for updating snmp_v2c_read " + str(have_snmpv2cread_ptr) self.status = "failed" return self for i in range(1, 3): @@ -1641,8 +1652,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_snmpv2cwrite_ptr] \ .update({keys[i]: item.get(values[i])}) else: - self.msg = values[i] + " is mandatory for creating \ - snmpV2cWrite " + str(have_snmpv2cwrite_ptr) + self.msg = values[i] + " is mandatory for creating snmp_v2c_write " + str(have_snmpv2cwrite_ptr) self.status = "failed" return self create_snmpv2cwrite_ptr = create_snmpv2cwrite_ptr + 1 @@ -1655,8 +1665,7 @@ def get_want_device_credentials(self, CredentialDetails): update_credential[update_snmpv2cwrite_ptr] \ .update({"writeCommunity": item.get("write_community")}) else: - self.msg = "write_community is mandatory for updating \ - snmpV2cWrite " + str(have_snmpv2cwrite_ptr) + self.msg = "write_community is mandatory for updating snmp_v2c_write " + str(have_snmpv2cwrite_ptr) self.status = "failed" return self for i in range(1, 3): @@ -1691,8 +1700,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_httpsread_ptr] \ .update({values[i]: item.get(values[i])}) else: - self.msg = values[i] + " is mandatory for creating \ - httpsRead " + str(have_httpsread_ptr) + self.msg = values[i] + " is mandatory for creating https_read " + str(have_httpsread_ptr) self.status = "failed" return self if item.get("port"): @@ -1711,8 +1719,7 @@ def get_want_device_credentials(self, CredentialDetails): update_credential[update_httpsread_ptr] \ .update({"password": item.get("password")}) else: - self.msg = "password is mandatory for updating \ - httpsRead " + str(have_httpsread_ptr) + self.msg = "The password is mandatory for updating https_read " + str(have_httpsread_ptr) self.status = "failed" return self for i in range(1, 5): @@ -1745,8 +1752,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_httpswrite_ptr] \ .update({values[i]: item.get(values[i])}) else: - self.msg = values[i] + " is mandatory for creating \ - httpsWrite " + str(have_httpswrite_ptr) + self.msg = values[i] + " is mandatory for creating https_write " + str(have_httpswrite_ptr) self.status = "failed" return self if item.get("port"): @@ -1765,8 +1771,7 @@ def get_want_device_credentials(self, CredentialDetails): update_credential[update_httpswrite_ptr] \ .update({"password": item.get("password")}) else: - self.msg = "password is mandatory for updating \ - httpsRead " + str(have_httpswrite_ptr) + self.msg = "The password is mandatory for updating https_write " + str(have_httpswrite_ptr) self.status = "failed" return self for i in range(1, 5): @@ -1799,8 +1804,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_snmpv3_ptr] \ .update({values[i]: item.get(values[i])}) else: - self.msg = values[i] + " is mandatory for creating \ - snmpV3 " + str(have_snmpv3_ptr) + self.msg = values[i] + " is mandatory for creating snmp_v3 " + str(have_snmpv3_ptr) self.status = "failed" return self if item.get("snmp_mode"): @@ -1821,8 +1825,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_snmpv3_ptr] \ .update({keys[auth]: item.get(auth)}) else: - self.msg = auth + " is mandatory for creating \ - snmpV3 " + str(have_snmpv3_ptr) + self.msg = auth + " is mandatory for creating snmp_v3 " + str(have_snmpv3_ptr) self.status = "failed" return self if len(item.get("auth_password")) < 8: @@ -1842,8 +1845,7 @@ def get_want_device_credentials(self, CredentialDetails): create_credential[create_snmpv3_ptr] \ .update({key[priv]: item.get(priv)}) else: - self.msg = priv + " is mandatory for creating \ - snmpV3 " + str(have_snmpv3_ptr) + self.msg = priv + " is mandatory for creating snmp_v3 " + str(have_snmpv3_ptr) self.status = "failed" return self if len(item.get("privacy_password")) < 8: @@ -1851,8 +1853,7 @@ def get_want_device_credentials(self, CredentialDetails): self.status = "failed" return self elif create_credential[create_snmpv3_ptr].get("snmpMode") != "NOAUTHNOPRIV": - self.msg = "snmp_mode in snmpV3 is not \ - ['AUTHPRIV', 'AUTHNOPRIV', 'NOAUTHNOPRIV']" + self.msg = "snmp_mode in snmpV3 is not ['AUTHPRIV', 'AUTHNOPRIV', 'NOAUTHNOPRIV']" self.status = "failed" return self create_snmpv3_ptr = create_snmpv3_ptr + 1 @@ -1885,7 +1886,7 @@ def get_want_device_credentials(self, CredentialDetails): .get("snmpMode")[have_snmpv3_ptr].get("authType") }) else: - self.msg = "auth_type is required for updating snmpV3 " + \ + self.msg = "auth_type is required for updating snmp_v3 " + \ str(have_snmpv3_ptr) self.status = "failed" return self @@ -1893,7 +1894,7 @@ def get_want_device_credentials(self, CredentialDetails): update_credential[update_snmpv3_ptr] \ .update({"authPassword": item.get("auth_password")}) else: - self.msg = "auth_password is required for updating snmpV3 " + \ + self.msg = "auth_password is required for updating snmp_v3 " + \ str(have_snmpv3_ptr) self.status = "failed" return self @@ -1912,7 +1913,7 @@ def get_want_device_credentials(self, CredentialDetails): .get("snmpMode")[have_snmpv3_ptr].get("privacyType") }) else: - self.msg = "privacy_type is required for updating snmpV3 " + \ + self.msg = "privacy_type is required for updating snmp_v3 " + \ str(have_snmpv3_ptr) self.status = "failed" return self @@ -1920,7 +1921,7 @@ def get_want_device_credentials(self, CredentialDetails): update_credential[update_snmpv3_ptr] \ .update({"privacyPassword": item.get("privacy_password")}) else: - self.msg = "privacy_password is required for updating snmpV3 " + \ + self.msg = "privacy_password is required for updating snmp_v3 " + \ str(have_snmpv3_ptr) self.status = "failed" return self @@ -1953,17 +1954,19 @@ def get_want_assign_credentials(self, AssignCredentials): } site_name = AssignCredentials.get("site_name") if not site_name: - self.msg = "site_name is required for AssignCredentials" + self.msg = "The 'site_name' is required parameter for 'assign_credentials_to_site'" self.status = "failed" return self + site_id = [] for site_name in site_name: siteId = self.get_site_id(site_name) - if not site_name: - self.msg = "site_name is invalid in AssignCredentials" + if not site_id: + self.msg = "The site_name '{0}' is invalid in 'assign_credentials_to_site'".format(site_name) self.status = "failed" return self site_id.append(siteId) + want.update({"site_id": site_id}) global_credentials = self.get_global_credentials_params() cli_credential = AssignCredentials.get("cli_credential") @@ -2003,17 +2006,17 @@ def get_want_assign_credentials(self, AssignCredentials): snmpV2cReadDescription = snmp_v2c_read.get("description") if snmpV2cReadId or snmpV2cReadDescription: - # All snmpV2cRead details from the Cisco Catalyst Center + # All snmp_v2c_read details from the Cisco Catalyst Center snmpV2cRead_details = global_credentials.get("snmpV2cRead") if not snmpV2cRead_details: - self.msg = "Global snmpV2cRead credential is not available" + self.msg = "Global snmp_v2c_read credential is not available" self.status = "failed" return self snmpV2cReadDetail = None if snmpV2cReadId: snmpV2cReadDetail = get_dict_result(snmpV2cRead_details, "id", snmpV2cReadId) if not snmpV2cReadDetail: - self.msg = "The ID of the snmpV2cRead credential is not valid." + self.msg = "The ID of the snmp_v2c_read credential is not valid." self.status = "failed" return self elif snmpV2cReadDescription: @@ -2021,7 +2024,7 @@ def get_want_assign_credentials(self, AssignCredentials): if item.get("description") == snmpV2cReadDescription: snmpV2cReadDetail = item if not snmpV2cReadDetail: - self.msg = "The username and description for the snmpV2cRead credential are invalid." + self.msg = "The username and description for the snmp_v2c_read credential are invalid." self.status = "failed" return self want.get("assign_credentials").update({"snmpV2ReadId": snmpV2cReadDetail.get("id")}) @@ -2032,17 +2035,17 @@ def get_want_assign_credentials(self, AssignCredentials): snmpV2cWriteDescription = snmp_v2c_write.get("description") if snmpV2cWriteId or snmpV2cWriteDescription: - # All snmpV2cWrite details from the Cisco Catalyst Center + # All snmp_v2c_write details from the Cisco Catalyst Center snmpV2cWrite_details = global_credentials.get("snmpV2cWrite") if not snmpV2cWrite_details: - self.msg = "Global snmpV2cWrite Credential is not available" + self.msg = "Global snmp_v2c_write Credential is not available" self.status = "failed" return self snmpV2cWriteDetail = None if snmpV2cWriteId: snmpV2cWriteDetail = get_dict_result(snmpV2cWrite_details, "id", snmpV2cWriteId) if not snmpV2cWriteDetail: - self.msg = "The ID of the snmpV2cWrite credential is invalid." + self.msg = "The ID of the snmp_v2c_write credential is invalid." self.status = "failed" return self elif snmpV2cWriteDescription: @@ -2050,7 +2053,7 @@ def get_want_assign_credentials(self, AssignCredentials): if item.get("description") == snmpV2cWriteDescription: snmpV2cWriteDetail = item if not snmpV2cWriteDetail: - self.msg = "The username and description of the snmpV2cWrite credential are invalid." + self.msg = "The username and description of the snmp_v2c_write credential are invalid." self.status = "failed" return self want.get("assign_credentials").update({"snmpV2WriteId": snmpV2cWriteDetail.get("id")}) @@ -2123,17 +2126,17 @@ def get_want_assign_credentials(self, AssignCredentials): snmpV3Description = snmp_v3.get("description") if snmpV3Id or snmpV3Description: - # All snmpV3 details from the Cisco Catalyst Center + # All snmp_v3 details from the Cisco Catalyst Center snmpV3_details = global_credentials.get("snmpV3") if not snmpV3_details: - self.msg = "Global snmpV3 Credential is not available." + self.msg = "Global snmp_v3 Credential is not available." self.status = "failed" return self snmpV3Detail = None if snmpV3Id: snmpV3Detail = get_dict_result(snmpV3_details, "id", snmpV3Id) if not snmpV3Detail: - self.msg = "The ID of the snmpV3 credential is not valid." + self.msg = "The ID of the snmp_v3 credential is not valid." self.status = "failed" return self elif snmpV3Description: @@ -2141,7 +2144,7 @@ def get_want_assign_credentials(self, AssignCredentials): if item.get("description") == snmpV3Description: snmpV3Detail = item if not snmpV3Detail: - self.msg = "The username and description for the snmpV2cWrite credential are invalid." + self.msg = "The username and description for the snmp_v2c_write credential are invalid." self.status = "failed" return self want.get("assign_credentials").update({"snmpV3Id": snmpV3Detail.get("id")}) @@ -2470,7 +2473,6 @@ def verify_diff_merged(self, config): self """ - self.log(str("Entered the verify function."), "DEBUG") self.get_have(config) self.get_want(config) self.log("Current State (have): {0}".format(self.have), "INFO") @@ -2513,8 +2515,7 @@ def verify_diff_merged(self, config): self.log("Successfully validated the assign device credential to site", "INFO") self.result.get("response")[0].get("assignCredential").update({"Validation": "Success"}) - self.msg = "Successfully validated the Global Device Credential and \ - Assign Device Credential to Site." + self.msg = "Successfully validated the global device credential and assigned device credential to site." self.status = "success" return self @@ -2540,12 +2541,14 @@ def verify_diff_deleted(self, config): credential_types = ["cliCredential", "snmpV2cRead", "snmpV2cWrite", "httpsRead", "httpsWrite", "snmpV3"] for credential_type in credential_types: - for item in have_global_credential.get(credential_type): - if item is not None: - self.msg = "Delete Global Device Credentials config \ - is not applied to the config" - self.status = "failed" - return self + have_global_credential_type = have_global_credential.get(credential_type) + if have_global_credential_type is not None: + for item in have_global_credential_type: + if item is not None: + self.msg = "The configuration for deleting the global device credentials " + \ + "is not being applied to the current configuration" + self.status = "failed" + return self self.log("Successfully validated absence of global device credential.", "INFO") self.result.get("response")[0].get("globalCredential").update({"Validation": "Success"}) diff --git a/plugins/modules/device_details_info.py b/plugins/modules/device_details_info.py index 05793acd29..bbf8396358 100644 --- a/plugins/modules/device_details_info.py +++ b/plugins/modules/device_details_info.py @@ -21,19 +21,19 @@ type: dict timestamp: description: - - Timestamp query parameter. Epoch time(in milliseconds) when the device data is required. - type: str - searchBy: + - Timestamp query parameter. UTC timestamp of device data in milliseconds. + type: float + identifier: description: - - SearchBy query parameter. MAC Address or Device Name value or UUID of the network device. + - Identifier query parameter. One of "macAddress", "nwDeviceName", "uuid" (case insensitive). type: str - identifier: + searchBy: description: - - Identifier query parameter. One of keywords macAddress or uuid or nwDeviceName. + - SearchBy query parameter. MAC Address, device name, or UUID of the network device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceDetail description: Complete reference of the GetDeviceDetail API. @@ -58,13 +58,12 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" - timestamp: string - searchBy: string + timestamp: 0 identifier: string + searchBy: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -72,49 +71,91 @@ type: dict sample: > { - "HALastResetReason": "string", - "managementIpAddr": "string", - "HAPrimaryPowerStatus": "string", - "redundancyMode": "string", - "communicationState": "string", + "noiseScore": 0, + "policyTagName": "string", + "interferenceScore": 0, + "opState": "string", + "powerSaveMode": "string", + "mode": "string", + "resetReason": "string", + "nwDeviceRole": "string", + "protocol": "string", + "powerMode": "string", + "connectedTime": "string", + "ringStatus": true, + "ledFlashSeconds": "string", + "ip_addr_managementIpAddr": "string", + "stackType": "string", + "subMode": "string", + "serialNumber": "string", "nwDeviceName": "string", - "redundancyUnit": "string", - "platformId": "string", - "redundancyPeerState": "string", + "deviceGroupHierarchyId": "string", + "cpu": "string", + "utilization": "string", "nwDeviceId": "string", - "redundancyState": "string", - "nwDeviceRole": "string", + "siteHierarchyGraphId": "string", "nwDeviceFamily": "string", "macAddress": "string", - "collectionStatus": "string", + "homeApEnabled": "string", "deviceSeries": "string", - "osType": "string", - "clientCount": "string", - "HASecondaryPowerStatus": "string", + "collectionStatus": "string", + "utilizationScore": 0, + "maintenanceMode": true, + "interference": "string", "softwareVersion": "string", - "nwDeviceType": "string", + "tagIdList": [ + {} + ], + "powerType": "string", "overallHealth": 0, - "memoryScore": 0, - "cpuScore": 0, - "noiseScore": 0, - "utilizationScore": 0, - "airQualityScore": 0, - "interferenceScore": 0, - "wqeScore": 0, - "freeMbufScore": 0, - "packetPoolScore": 0, - "freeTimerScore": 0, + "managementIpAddr": "string", "memory": "string", - "cpu": "string", + "communicationState": "string", + "apType": "string", + "adminState": "string", "noise": "string", - "utilization": "string", + "icapCapability": "string", + "regulatoryDomain": "string", + "ethernetMac": "string", + "nwDeviceType": "string", "airQuality": "string", - "interference": "string", - "wqe": "string", - "freeMbuf": "string", - "packetPool": "string", - "freeTimer": "string", + "rfTagName": "string", + "siteTagName": "string", + "platformId": "string", + "upTime": "string", + "memoryScore": 0, + "powerSaveModeCapable": "string", + "powerProfile": "string", + "airQualityScore": 0, "location": "string", - "timestamp": "string" + "flexGroup": "string", + "lastBootTime": 0, + "powerCalendarProfile": "string", + "connectivityStatus": 0, + "ledFlashEnabled": "string", + "cpuScore": 0, + "avgTemperature": 0, + "maxTemperature": 0, + "haStatus": "string", + "osType": "string", + "timestamp": 0, + "apGroup": "string", + "redundancyMode": "string", + "featureFlagList": [ + "string" + ], + "freeMbufScore": 0, + "HALastResetReason": "string", + "wqeScore": 0, + "redundancyPeerStateDerived": "string", + "freeTimerScore": 0, + "redundancyPeerState": "string", + "redundancyStateDerived": "string", + "redundancyState": "string", + "packetPoolScore": 0, + "freeTimer": 0, + "packetPool": 0, + "wqe": 0, + "freeMbuf": 0 } """ diff --git a/plugins/modules/device_enrichment_details_info.py b/plugins/modules/device_enrichment_details_info.py index 37a46f792f..a825d5c9c5 100644 --- a/plugins/modules/device_enrichment_details_info.py +++ b/plugins/modules/device_enrichment_details_info.py @@ -22,8 +22,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceEnrichmentDetails description: Complete reference of the GetDeviceEnrichmentDetails API. @@ -51,7 +51,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_family_identifiers_details_info.py b/plugins/modules/device_family_identifiers_details_info.py index 97736aa741..4210b61136 100644 --- a/plugins/modules/device_family_identifiers_details_info.py +++ b/plugins/modules/device_family_identifiers_details_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) GetDeviceFamilyIdentifiers description: Complete reference of the GetDeviceFamilyIdentifiers API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_health_info.py b/plugins/modules/device_health_info.py index 7b0775f33e..dd604930b5 100644 --- a/plugins/modules/device_health_info.py +++ b/plugins/modules/device_health_info.py @@ -23,35 +23,35 @@ type: dict deviceRole: description: - - DeviceRole query parameter. The device role (One of CORE, ACCESS, DISTRIBUTION, ROUTER, WLC, AP). + - DeviceRole query parameter. CORE, ACCESS, DISTRIBUTION, ROUTER, WLC, or AP (case insensitive). type: str siteId: description: - - SiteId query parameter. Assurance site UUID value. + - SiteId query parameter. DNAC site UUID. type: str health: description: - - Health query parameter. The device overall health (One of POOR, FAIR, GOOD). + - Health query parameter. DNAC health catagory POOR, FAIR, or GOOD (case insensitive). type: str startTime: description: - StartTime query parameter. UTC epoch time in milliseconds. - type: int + type: float endTime: description: - - EndTime query parameter. UTC epoch time in miliseconds. - type: int + - EndTime query parameter. UTC epoch time in milliseconds. + type: float limit: description: - - Limit query parameter. Max number of device entries in the response (default to 50. Max at 1000). - type: int + - Limit query parameter. Max number of device entries in the response (default to 50. Max at 500). + type: float offset: description: - - Offset query parameter. The offset of the first device in the returned data. - type: int + - Offset query parameter. The offset of the first device in the returned data (Mutiple of 'limit' + 1). + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices Devices description: Complete reference of the Devices API. @@ -86,7 +86,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -98,51 +97,84 @@ "totalCount": 0, "response": [ { - "name": "string", - "model": "string", - "osVersion": "string", - "ipAddress": "string", - "overallHealth": 0, - "issueCount": 0, - "location": "string", - "deviceFamily": "string", "deviceType": "string", - "macAddress": "string", - "interfaceLinkErrHealth": 0, - "cpuUlitilization": 0, - "cpuHealth": 0, - "memoryUtilizationHealth": 0, - "memoryUtilization": 0, - "interDeviceLinkAvailHealth": 0, - "reachabilityHealth": "string", - "clientCount": { + "cpuUtilization": 0, + "overallHealth": 0, + "utilizationHealth": { "radio0": 0, "radio1": 0, + "radio2": 0, + "radio3": 0, "Ghz24": 0, "Ghz50": 0 }, - "interferenceHealth": { + "airQualityHealth": { "radio0": 0, "radio1": 0, + "radio2": 0, + "radio3": 0, "Ghz24": 0, "Ghz50": 0 }, + "ipAddress": "string", + "cpuHealth": 0, + "deviceFamily": "string", + "issueCount": 0, + "macAddress": "string", "noiseHealth": { + "radio0": 0, "radio1": 0, + "radio2": 0, + "radio3": 0, + "Ghz24": 0, "Ghz50": 0 }, - "airQualityHealth": { + "osVersion": "string", + "name": "string", + "interfaceLinkErrHealth": 0, + "memoryUtilization": 0, + "interDeviceLinkAvailHealth": 0, + "interferenceHealth": { "radio0": 0, "radio1": 0, + "radio2": 0, + "radio3": 0, "Ghz24": 0, "Ghz50": 0 }, - "utilizationHealth": { + "model": "string", + "location": "string", + "reachabilityHealth": "string", + "band": { + "radio0": "string", + "radio1": "string", + "radio2": "string", + "radio3": 0 + }, + "memoryUtilizationHealth": 0, + "clientCount": { "radio0": 0, "radio1": 0, + "radio2": 0, + "radio3": 0, "Ghz24": 0, "Ghz50": 0 - } + }, + "avgTemperature": 0, + "maxTemperature": 0, + "interDeviceLinkAvailFabric": 0, + "apCount": 0, + "freeTimerScore": 0, + "freeTimer": 0, + "packetPoolHealth": 0, + "packetPool": 0, + "freeMemoryBufferHealth": 0, + "freeMemoryBuffer": 0, + "wqePoolsHealth": 0, + "wqePools": 0, + "wanLinkUtilization": 0, + "cpuUlitilization": 0, + "uuid": "string" } ] } diff --git a/plugins/modules/device_interface_by_ip_info.py b/plugins/modules/device_interface_by_ip_info.py index df7223b150..d9ea17a249 100644 --- a/plugins/modules/device_interface_by_ip_info.py +++ b/plugins/modules/device_interface_by_ip_info.py @@ -24,8 +24,8 @@ - IpAddress path parameter. IP address of the interface. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetInterfaceByIP description: Complete reference of the GetInterfaceByIP API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -64,9 +63,24 @@ { "response": [ { + "addresses": [ + { + "address": { + "ipAddress": { + "address": "string" + }, + "ipMask": { + "address": "string" + }, + "isInverseMask": true + }, + "type": "string" + } + ], "adminStatus": "string", "className": "string", "description": "string", + "name": "string", "deviceId": "string", "duplex": "string", "id": "string", @@ -77,11 +91,14 @@ "ipv4Address": "string", "ipv4Mask": "string", "isisSupport": "string", + "lastOutgoingPacketTime": 0, + "lastIncomingPacketTime": 0, "lastUpdated": "string", "macAddress": "string", "mappedPhysicalInterfaceId": "string", "mappedPhysicalInterfaceName": "string", "mediaType": "string", + "mtu": "string", "nativeVlanId": "string", "ospfSupport": "string", "pid": "string", diff --git a/plugins/modules/device_interface_count_info.py b/plugins/modules/device_interface_count_info.py index 01d3361fbb..5f416c933b 100644 --- a/plugins/modules/device_interface_count_info.py +++ b/plugins/modules/device_interface_count_info.py @@ -20,12 +20,12 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Devices GetDeviceInterfaceCount - description: Complete reference of the GetDeviceInterfaceCount API. - link: https://developer.cisco.com/docs/dna-center/#!get-device-interface-count +- name: Cisco DNA Center documentation for Devices GetDeviceInterfaceCountForMultipleDevices + description: Complete reference of the GetDeviceInterfaceCountForMultipleDevices API. + link: https://developer.cisco.com/docs/dna-center/#!get-device-interface-count-for-multiple-devices notes: - SDK Method used are devices.Devices.get_device_interface_count, @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_interface_info.py b/plugins/modules/device_interface_info.py index 31b2bc4c64..983189ebfb 100644 --- a/plugins/modules/device_interface_info.py +++ b/plugins/modules/device_interface_info.py @@ -42,8 +42,8 @@ - Id path parameter. Interface ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetAllInterfaces description: Complete reference of the GetAllInterfaces API. @@ -93,7 +93,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -102,9 +101,24 @@ sample: > { "response": { + "addresses": [ + { + "address": { + "ipAddress": { + "address": "string" + }, + "ipMask": { + "address": "string" + }, + "isInverseMask": true + }, + "type": "string" + } + ], "adminStatus": "string", "className": "string", "description": "string", + "name": "string", "deviceId": "string", "duplex": "string", "id": "string", @@ -115,11 +129,14 @@ "ipv4Address": "string", "ipv4Mask": "string", "isisSupport": "string", + "lastOutgoingPacketTime": 0, + "lastIncomingPacketTime": 0, "lastUpdated": "string", "macAddress": "string", "mappedPhysicalInterfaceId": "string", "mappedPhysicalInterfaceName": "string", "mediaType": "string", + "mtu": "string", "nativeVlanId": "string", "ospfSupport": "string", "pid": "string", diff --git a/plugins/modules/device_interface_isis_info.py b/plugins/modules/device_interface_isis_info.py index 798c478215..2be160ae79 100644 --- a/plugins/modules/device_interface_isis_info.py +++ b/plugins/modules/device_interface_isis_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetISISInterfaces description: Complete reference of the GetISISInterfaces API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -59,9 +58,24 @@ { "response": [ { + "addresses": [ + { + "address": { + "ipAddress": { + "address": "string" + }, + "ipMask": { + "address": "string" + }, + "isInverseMask": true + }, + "type": "string" + } + ], "adminStatus": "string", "className": "string", "description": "string", + "name": "string", "deviceId": "string", "duplex": "string", "id": "string", @@ -72,11 +86,14 @@ "ipv4Address": "string", "ipv4Mask": "string", "isisSupport": "string", + "lastOutgoingPacketTime": 0, + "lastIncomingPacketTime": 0, "lastUpdated": "string", "macAddress": "string", "mappedPhysicalInterfaceId": "string", "mappedPhysicalInterfaceName": "string", "mediaType": "string", + "mtu": "string", "nativeVlanId": "string", "ospfSupport": "string", "pid": "string", diff --git a/plugins/modules/device_interface_ospf_info.py b/plugins/modules/device_interface_ospf_info.py index ed87a4b0cd..69e49d3e6d 100644 --- a/plugins/modules/device_interface_ospf_info.py +++ b/plugins/modules/device_interface_ospf_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetOSPFInterfaces description: Complete reference of the GetOSPFInterfaces API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -59,9 +58,24 @@ { "response": [ { + "addresses": [ + { + "address": { + "ipAddress": { + "address": "string" + }, + "ipMask": { + "address": "string" + }, + "isInverseMask": true + }, + "type": "string" + } + ], "adminStatus": "string", "className": "string", "description": "string", + "name": "string", "deviceId": "string", "duplex": "string", "id": "string", @@ -72,11 +86,14 @@ "ipv4Address": "string", "ipv4Mask": "string", "isisSupport": "string", + "lastOutgoingPacketTime": 0, + "lastIncomingPacketTime": 0, "lastUpdated": "string", "macAddress": "string", "mappedPhysicalInterfaceId": "string", "mappedPhysicalInterfaceName": "string", "mediaType": "string", + "mtu": "string", "nativeVlanId": "string", "ospfSupport": "string", "pid": "string", diff --git a/plugins/modules/device_reboot_apreboot.py b/plugins/modules/device_reboot_apreboot.py index 92e7c41ee0..e4c73707ff 100644 --- a/plugins/modules/device_reboot_apreboot.py +++ b/plugins/modules/device_reboot_apreboot.py @@ -21,8 +21,8 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless RebootAccessPoints description: Complete reference of the RebootAccessPoints API. @@ -51,7 +51,6 @@ - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_reboot_apreboot_info.py b/plugins/modules/device_reboot_apreboot_info.py index c4e500062a..556038da9f 100644 --- a/plugins/modules/device_reboot_apreboot_info.py +++ b/plugins/modules/device_reboot_apreboot_info.py @@ -11,7 +11,7 @@ description: - Get all Device Reboot Apreboot. - Users can query the access point reboot status using this intent API. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -24,8 +24,8 @@ - ParentTaskId query parameter. Task id of ap reboot request. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless GetAccessPointRebootTaskResult description: Complete reference of the GetAccessPointRebootTaskResult API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_replacement.py b/plugins/modules/device_replacement.py index a5353ddd06..99a9bfa009 100644 --- a/plugins/modules/device_replacement.py +++ b/plugins/modules/device_replacement.py @@ -22,51 +22,52 @@ elements: dict suboptions: creationTime: - description: Device Replacement's creationTime. + description: Date and time of marking the device for replacement. type: int family: - description: Device Replacement's family. + description: Faulty device family. type: str faultyDeviceId: - description: Device Replacement's faultyDeviceId. + description: Unique identifier of the faulty device. type: str faultyDeviceName: - description: Device Replacement's faultyDeviceName. + description: Faulty device name. type: str faultyDevicePlatform: - description: Device Replacement's faultyDevicePlatform. + description: Faulty device platform. type: str faultyDeviceSerialNumber: - description: Device Replacement's faultyDeviceSerialNumber. + description: Faulty device serial number. type: str id: - description: Device Replacement's id. + description: Unique identifier of the device replacement resource. type: str neighbourDeviceId: - description: Device Replacement's neighbourDeviceId. + description: Unique identifier of the neighbor device to create the DHCP server. type: str networkReadinessTaskId: - description: Device Replacement's networkReadinessTaskId. + description: Unique identifier of network readiness task. type: str replacementDevicePlatform: - description: Device Replacement's replacementDevicePlatform. + description: Replacement device platform. type: str replacementDeviceSerialNumber: - description: Device Replacement's replacementDeviceSerialNumber. + description: Replacement device serial number. type: str replacementStatus: - description: Device Replacement's replacementStatus. + description: Device replacement status. Use NON-FAULTY to unmark the device + for replacement. type: str replacementTime: - description: Device Replacement's replacementTime. + description: Date and time of device replacement. type: int workflowId: - description: Device Replacement's workflowId. + description: Unique identifier of the device replacement workflow. type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Replacement MarkDeviceForReplacement description: Complete reference of the MarkDeviceForReplacement API. @@ -139,7 +140,6 @@ workflowId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_replacement_count_info.py b/plugins/modules/device_replacement_count_info.py index 8aae86979d..313326f070 100644 --- a/plugins/modules/device_replacement_count_info.py +++ b/plugins/modules/device_replacement_count_info.py @@ -27,8 +27,8 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Replacement ReturnReplacementDevicesCount description: Complete reference of the ReturnReplacementDevicesCount API. @@ -57,7 +57,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_replacement_deploy.py b/plugins/modules/device_replacement_deploy.py index 81dfc92516..83b7b31352 100644 --- a/plugins/modules/device_replacement_deploy.py +++ b/plugins/modules/device_replacement_deploy.py @@ -19,14 +19,14 @@ author: Rafael Campos (@racampos) options: faultyDeviceSerialNumber: - description: Device Replacement Deploy's faultyDeviceSerialNumber. + description: Faulty device serial number. type: str replacementDeviceSerialNumber: - description: Device Replacement Deploy's replacementDeviceSerialNumber. + description: Replacement device serial number. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Replacement DeployDeviceReplacementWorkflow description: Complete reference of the DeployDeviceReplacementWorkflow API. @@ -54,7 +54,6 @@ replacementDeviceSerialNumber: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/device_replacement_info.py b/plugins/modules/device_replacement_info.py index 4dd9756d5f..592aa958d7 100644 --- a/plugins/modules/device_replacement_info.py +++ b/plugins/modules/device_replacement_info.py @@ -71,8 +71,8 @@ - Limit query parameter. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Replacement ReturnListOfReplacementDevicesWithReplacementDetails description: Complete reference of the ReturnListOfReplacementDevicesWithReplacementDetails API. @@ -111,7 +111,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -134,7 +133,9 @@ "replacementDeviceSerialNumber": "string", "replacementStatus": "string", "replacementTime": 0, - "workflowId": "string" + "workflowId": "string", + "workflowFailedStep": "string", + "readinesscheckTaskId": "string" } ], "version": "string" diff --git a/plugins/modules/disassociate_site_to_network_profile.py b/plugins/modules/disassociate_site_to_network_profile.py index 2972ac7f20..e06c5e1986 100644 --- a/plugins/modules/disassociate_site_to_network_profile.py +++ b/plugins/modules/disassociate_site_to_network_profile.py @@ -23,8 +23,8 @@ description: SiteId path parameter. Site Id to be associated. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Site Design Disassociate description: Complete reference of the Disassociate API. @@ -52,7 +52,6 @@ siteId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/disasterrecovery_system_operationstatus_info.py b/plugins/modules/disasterrecovery_system_operationstatus_info.py index 1c6621afee..3f821aeefc 100644 --- a/plugins/modules/disasterrecovery_system_operationstatus_info.py +++ b/plugins/modules/disasterrecovery_system_operationstatus_info.py @@ -20,7 +20,7 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/disasterrecovery_system_status_info.py b/plugins/modules/disasterrecovery_system_status_info.py index f1c3c318cf..2c3d3bb9d1 100644 --- a/plugins/modules/disasterrecovery_system_status_info.py +++ b/plugins/modules/disasterrecovery_system_status_info.py @@ -20,7 +20,7 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/discovery.py b/plugins/modules/discovery.py index 94fca37e00..f688ed7329 100644 --- a/plugins/modules/discovery.py +++ b/plugins/modules/discovery.py @@ -22,200 +22,206 @@ author: Rafael Campos (@racampos) options: attributeInfo: - description: Discovery's attributeInfo. + description: Deprecated. type: dict cdpLevel: - description: Discovery's cdpLevel. + description: CDP level to which neighbor devices to be discovered. type: int deviceIds: - description: Discovery's deviceIds. + description: Ids of the devices discovered in a discovery. type: str discoveryCondition: - description: Discovery's discoveryCondition. + description: To indicate the discovery status. Available options Complete or In + Progress. type: str discoveryStatus: - description: Discovery's discoveryStatus. + description: Status of the discovery. Available options are active, inactive, edit. type: str discoveryType: - description: Discovery's discoveryType. + description: Type of the discovery. 'SINGLE', 'RANGE', 'MULTI RANGE', 'CDP', 'LLDP', + 'CIDR'. type: str enablePasswordList: - description: Discovery's enablePasswordList. + description: Enable Password of the devices to be discovered. type: str globalCredentialIdList: - description: Discovery's globalCredentialIdList. + description: List of global credential ids to be used. elements: str type: list httpReadCredential: description: Discovery's httpReadCredential. suboptions: comments: - description: Discovery's comments. + description: Comments to identify the credential. type: str credentialType: - description: Discovery's credentialType. + description: Credential type to identify the application that uses the credential. type: str description: - description: Discovery's description. + description: Description of the credential. type: str id: - description: Discovery's id. + description: Credential Id. type: str instanceTenantId: - description: Discovery's instanceTenantId. + description: Credential Tenant Id. type: str instanceUuid: - description: Discovery's instanceUuid. + description: Credential Id. type: str password: - description: Discovery's password. + description: HTTP(S) password. type: str port: - description: Discovery's port. + description: HTTP(S) port. type: int secure: - description: Secure flag. + description: Flag for HTTPS. type: bool username: - description: Discovery's username. + description: HTTP(S) username. type: str type: dict httpWriteCredential: description: Discovery's httpWriteCredential. suboptions: comments: - description: Discovery's comments. + description: Comments to identify the credential. type: str credentialType: - description: Discovery's credentialType. + description: Credential type to identify the application that uses the credential. type: str description: - description: Discovery's description. + description: Description of the credential. type: str id: - description: Discovery's id. + description: Credential Id. type: str instanceTenantId: - description: Discovery's instanceTenantId. + description: Credential Tenant Id. type: str instanceUuid: - description: Discovery's instanceUuid. + description: Credential Id. type: str password: - description: Discovery's password. + description: HTTP(S) password. type: str port: - description: Discovery's port. + description: HTTP(S) port. type: int secure: - description: Secure flag. + description: Flag for HTTPS. type: bool username: - description: Discovery's username. + description: HTTP(S) username. type: str type: dict id: - description: Discovery's id. + description: Unique Discovery Id. type: str ipAddressList: - description: Discovery's ipAddressList. + description: List of IP address of the devices to be discovered. type: str ipFilterList: - description: Discovery's ipFilterList. + description: IP addresses of the devices to be filtered. type: str isAutoCdp: - description: IsAutoCdp flag. + description: Flag to mention if CDP discovery or not. type: bool lldpLevel: - description: Discovery's lldpLevel. + description: LLDP level to which neighbor devices to be discovered. type: int name: - description: Discovery's name. + description: Name for the discovery. type: str netconfPort: - description: Discovery's netconfPort. + description: Netconf port on the device. Netconf will need valid sshv2 credentials + for it to work. type: str numDevices: - description: Discovery's numDevices. + description: Number of devices discovered in the discovery. type: int parentDiscoveryId: - description: Discovery's parentDiscoveryId. + description: Parent Discovery Id from which the discovery was initiated. type: str passwordList: - description: Discovery's passwordList. + description: Password of the devices to be discovered. type: str preferredMgmtIPMethod: - description: Discovery's preferredMgmtIPMethod. + description: Preferred management IP method. Available options are 'None' and 'UseLoopBack'. type: str protocolOrder: - description: Discovery's protocolOrder. + description: Order of protocol (ssh/telnet) in which device connection will be tried. + Ex 'telnet' only telnet; 'ssh,telnet' ssh with higher order than telnet. type: str retry: description: Number of times to try establishing connection to device. type: int retryCount: - description: Discovery's retryCount. + description: Number of times to try establishing connection to device. type: int snmpAuthPassphrase: - description: Discovery's snmpAuthPassphrase. + description: Auth passphrase for SNMP. type: str snmpAuthProtocol: - description: Discovery's snmpAuthProtocol. + description: SNMP auth protocol. SHA' or 'MD5'. type: str snmpMode: - description: Discovery's snmpMode. + description: Mode of SNMP. 'AUTHPRIV' or 'AUTHNOPRIV' or 'NOAUTHNOPRIV'. type: str snmpPrivPassphrase: - description: Discovery's snmpPrivPassphrase. + description: Passphrase for SNMP privacy. type: str snmpPrivProtocol: - description: Discovery's snmpPrivProtocol. + description: SNMP privacy protocol. 'AES128'. type: str snmpROCommunity: - description: Snmp RO community of the devices to be discovered. + description: SNMP RO community of the devices to be discovered. type: str snmpROCommunityDesc: - description: Description for Snmp RO community. + description: Description for SNMP RO community. type: str snmpRWCommunity: - description: Snmp RW community of the devices to be discovered. + description: SNMP RW community of the devices to be discovered. type: str snmpRWCommunityDesc: - description: Description for Snmp RW community. + description: Description for SNMP RW community. type: str snmpRoCommunity: - description: Discovery's snmpRoCommunity. + description: SNMP RO community of the devices to be discovered. type: str snmpRoCommunityDesc: - description: Discovery's snmpRoCommunityDesc. + description: Description for SNMP RO community. type: str snmpRwCommunity: - description: Discovery's snmpRwCommunity. + description: SNMP RW community of the devices to be discovered. type: str snmpRwCommunityDesc: - description: Discovery's snmpRwCommunityDesc. + description: Description for SNMP RW community. type: str snmpUserName: - description: Discovery's snmpUserName. + description: SNMP username of the device. type: str snmpVersion: description: Version of SNMP. V2 or v3. type: str timeOut: - description: Discovery's timeOut. + description: Time to wait for device response. type: int timeout: description: Time to wait for device response in seconds. type: int updateMgmtIp: - description: UpdateMgmtIp flag. + description: Updates Management IP if multiple IPs are available for a device. If + set to true, when a device is rediscovered with a different IP, the management + IP is updated. Default value is false. type: bool userNameList: - description: Discovery's userNameList. + description: Username of the devices to be discovered. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery StartDiscovery description: Complete reference of the StartDiscovery API. @@ -388,7 +394,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_count_info.py b/plugins/modules/discovery_count_info.py index 59f92499a0..abf5c9d0c8 100644 --- a/plugins/modules/discovery_count_info.py +++ b/plugins/modules/discovery_count_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetCountOfAllDiscoveryJobs description: Complete reference of the GetCountOfAllDiscoveryJobs API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_device_count_info.py b/plugins/modules/discovery_device_count_info.py index 51da8df803..4a73deeae0 100644 --- a/plugins/modules/discovery_device_count_info.py +++ b/plugins/modules/discovery_device_count_info.py @@ -30,8 +30,8 @@ - TaskId query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetDevicesDiscoveredById description: Complete reference of the GetDevicesDiscoveredById API. @@ -61,7 +61,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_device_info.py b/plugins/modules/discovery_device_info.py index 2bc42ae22b..2fde652725 100644 --- a/plugins/modules/discovery_device_info.py +++ b/plugins/modules/discovery_device_info.py @@ -30,8 +30,8 @@ - TaskId query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveredNetworkDevicesByDiscoveryId description: Complete reference of the GetDiscoveredNetworkDevicesByDiscoveryId API. @@ -61,7 +61,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_device_range_info.py b/plugins/modules/discovery_device_range_info.py index ade1f28280..769d10b141 100644 --- a/plugins/modules/discovery_device_range_info.py +++ b/plugins/modules/discovery_device_range_info.py @@ -27,19 +27,19 @@ type: str startIndex: description: - - StartIndex path parameter. Start index. + - StartIndex path parameter. Starting index for the records. type: int recordsToReturn: description: - - RecordsToReturn path parameter. Number of records to return. + - RecordsToReturn path parameter. Number of records to fetch from the start index. type: int taskId: description: - TaskId query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveredDevicesByRange description: Complete reference of the GetDiscoveredDevicesByRange API. @@ -71,7 +71,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_info.py b/plugins/modules/discovery_info.py index 68d1cc74f4..1973b581e4 100644 --- a/plugins/modules/discovery_info.py +++ b/plugins/modules/discovery_info.py @@ -24,8 +24,8 @@ - Id path parameter. Discovery ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveryById description: Complete reference of the GetDiscoveryById API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_job_info.py b/plugins/modules/discovery_job_info.py index 2e6de4f14f..251b971c1c 100644 --- a/plugins/modules/discovery_job_info.py +++ b/plugins/modules/discovery_job_info.py @@ -44,8 +44,8 @@ - Id path parameter. Discovery ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveryJobsByIP description: Complete reference of the GetDiscoveryJobsByIP API. @@ -98,7 +98,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_range_delete.py b/plugins/modules/discovery_range_delete.py index 876881242e..36b5d5e7eb 100644 --- a/plugins/modules/discovery_range_delete.py +++ b/plugins/modules/discovery_range_delete.py @@ -17,14 +17,15 @@ author: Rafael Campos (@racampos) options: recordsToDelete: - description: RecordsToDelete path parameter. Number of records to delete. + description: RecordsToDelete path parameter. Number of records to delete from the + starting index. type: int startIndex: - description: StartIndex path parameter. Start index. + description: StartIndex path parameter. Starting index for the records. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery DeleteDiscoveryBySpecifiedRange description: Complete reference of the DeleteDiscoveryBySpecifiedRange API. @@ -52,7 +53,6 @@ startIndex: 0 """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_range_info.py b/plugins/modules/discovery_range_info.py index c4fc60ba7e..eeac5d9261 100644 --- a/plugins/modules/discovery_range_info.py +++ b/plugins/modules/discovery_range_info.py @@ -10,7 +10,7 @@ short_description: Information module for Discovery Range description: - Get all Discovery Range. -- Returns the discovery by specified range. +- Returns the discoveries by specified range. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -21,15 +21,15 @@ type: dict startIndex: description: - - StartIndex path parameter. Start index. + - StartIndex path parameter. Starting index for the records. type: int recordsToReturn: description: - - RecordsToReturn path parameter. Number of records to return. + - RecordsToReturn path parameter. Number of records to fetch from the starting index. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetDiscoveriesByRange description: Complete reference of the GetDiscoveriesByRange API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/discovery_summary_info.py b/plugins/modules/discovery_summary_info.py index 9cff8b3ee8..e920fffb92 100644 --- a/plugins/modules/discovery_summary_info.py +++ b/plugins/modules/discovery_summary_info.py @@ -11,8 +11,8 @@ description: - Get all Discovery Summary. - > - Returns the network devices from a discovery job based on given filters. Discovery ID can be obtained using the - "Get Discoveries by range" API. + Returns the devices discovered in the given discovery based on given filters. Discovery ID can be obtained using + the "Get Discoveries by range" API. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -31,45 +31,57 @@ type: str sortBy: description: - - SortBy query parameter. + - > + SortBy query parameter. Sort by field. Available values are pingStatus, cliStatus,snmpStatus, httpStatus and + netconfStatus. type: str sortOrder: description: - - SortOrder query parameter. + - SortOrder query parameter. Order of sorting based on sortBy. Available values are 'asc' and 'des'. type: str ipAddress: description: - - IpAddress query parameter. + - IpAddress query parameter. IP Address of the device. elements: str type: list pingStatus: description: - - PingStatus query parameter. + - > + PingStatus query parameter. Ping status for the IP during the job run. Available values are 'SUCCESS', + 'FAILURE', 'NOT-PROVIDED' and 'NOT-VALIDATED'. elements: str type: list snmpStatus: description: - - SnmpStatus query parameter. + - > + SnmpStatus query parameter. SNMP status for the IP during the job run. Available values are 'SUCCESS', + 'FAILURE', 'NOT-PROVIDED' and 'NOT-VALIDATED'. elements: str type: list cliStatus: description: - - CliStatus query parameter. + - > + CliStatus query parameter. CLI status for the IP during the job run. Available values are 'SUCCESS', + 'FAILURE', 'NOT-PROVIDED' and 'NOT-VALIDATED'. elements: str type: list netconfStatus: description: - - NetconfStatus query parameter. + - > + NetconfStatus query parameter. NETCONF status for the IP during the job run. Available values are 'SUCCESS', + 'FAILURE', 'NOT-PROVIDED' and 'NOT-VALIDATED'. elements: str type: list httpStatus: description: - - HttpStatus query parameter. + - > + HttpStatus query parameter. HTTP staus for the IP during the job run. Available values are 'SUCCESS', + 'FAILURE', 'NOT-PROVIDED' and 'NOT-VALIDATED'. elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetNetworkDevicesFromDiscovery description: Complete reference of the GetNetworkDevicesFromDiscovery API. @@ -107,7 +119,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/dna_command_runner_keywords_info.py b/plugins/modules/dna_command_runner_keywords_info.py index 1e63e6b131..0e3873e8ed 100644 --- a/plugins/modules/dna_command_runner_keywords_info.py +++ b/plugins/modules/dna_command_runner_keywords_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Command Runner GetAllKeywordsOfCLIsAcceptedByCommandRunner description: Complete reference of the GetAllKeywordsOfCLIsAcceptedByCommandRunner API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/dna_event_snmp_config_info.py b/plugins/modules/dna_event_snmp_config_info.py new file mode 100644 index 0000000000..7a4241fb1f --- /dev/null +++ b/plugins/modules/dna_event_snmp_config_info.py @@ -0,0 +1,103 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: dna_event_snmp_config_info +short_description: Information module for Dna Event Snmp Config +description: +- Get all Dna Event Snmp Config. +- Get SNMP Destination. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + configId: + description: + - ConfigId query parameter. List of SNMP configurations. + type: str + offset: + description: + - Offset query parameter. The number of SNMP configuration's to offset in the resultset whose default value 0. + type: float + limit: + description: + - Limit query parameter. The number of SNMP configuration's to limit in the resultset whose default value 10. + type: float + sortBy: + description: + - SortBy query parameter. SortBy field name. + type: str + order: + description: + - Order query parameter. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Event Management GetSNMPDestination + description: Complete reference of the GetSNMPDestination API. + link: https://developer.cisco.com/docs/dna-center/#!get-snmp-destination +notes: + - SDK Method used are + event_management.EventManagement.get_snmp_destination, + + - Paths used are + get /dna/intent/api/v1/dna-event/snmp-config, + +""" + +EXAMPLES = r""" +- name: Get all Dna Event Snmp Config + cisco.dnac.dna_event_snmp_config_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + configId: string + offset: 0 + limit: 0 + sortBy: string + order: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "version": "string", + "tenantId": "string", + "configId": "string", + "name": "string", + "description": "string", + "ipAddress": "string", + "port": 0, + "snmpVersion": "string", + "community": "string", + "userName": "string", + "snmpMode": "string", + "snmpAuthType": "string", + "authPassword": "string", + "snmpPrivacyType": "string", + "privacyPassword": "string" + } + ] +""" diff --git a/plugins/modules/dnac_packages_info.py b/plugins/modules/dnac_packages_info.py index ebc2481a5c..5328fb6ff2 100644 --- a/plugins/modules/dnac_packages_info.py +++ b/plugins/modules/dnac_packages_info.py @@ -11,7 +11,7 @@ description: - Get all Dnac Packages. - Provides information such as name, version of packages installed on the DNA center. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Platform CiscoDNACenterPackagesSummary description: Complete reference of the CiscoDNACenterPackagesSummary API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/dnacaap_management_execution_status_info.py b/plugins/modules/dnacaap_management_execution_status_info.py index 3fc122f4de..8972268c67 100644 --- a/plugins/modules/dnacaap_management_execution_status_info.py +++ b/plugins/modules/dnacaap_management_execution_status_info.py @@ -24,8 +24,8 @@ - ExecutionId path parameter. Execution Id of API. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Task GetBusinessAPIExecutionDetails description: Complete reference of the GetBusinessAPIExecutionDetails API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -71,7 +70,7 @@ "endTimeEpoch": 0, "timeDuration": 0, "status": "string", - "bapiError": "string", - "runtimeInstanceId": "string" + "runtimeInstanceId": "string", + "bapiError": "string" } """ diff --git a/plugins/modules/endpoint_analytics_profiling_rules.py b/plugins/modules/endpoint_analytics_profiling_rules.py index 43633824b2..bbe87bf9b6 100644 --- a/plugins/modules/endpoint_analytics_profiling_rules.py +++ b/plugins/modules/endpoint_analytics_profiling_rules.py @@ -114,7 +114,7 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/endpoint_analytics_profiling_rules_info.py b/plugins/modules/endpoint_analytics_profiling_rules_info.py index 1e3ca88c2a..45bf1bf517 100644 --- a/plugins/modules/endpoint_analytics_profiling_rules_info.py +++ b/plugins/modules/endpoint_analytics_profiling_rules_info.py @@ -60,7 +60,7 @@ - RuleId path parameter. Unique rule identifier. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/eox_status_device_info.py b/plugins/modules/eox_status_device_info.py index dc10734508..c8cdfe7a5f 100644 --- a/plugins/modules/eox_status_device_info.py +++ b/plugins/modules/eox_status_device_info.py @@ -13,7 +13,7 @@ - Get Eox Status Device by id. - Retrieves EoX details for a device. - Retrieves EoX status for all devices in the network. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -26,8 +26,8 @@ - DeviceId path parameter. Device instance UUID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for EoX GetEoXDetailsPerDevice description: Complete reference of the GetEoXDetailsPerDevice API. @@ -37,8 +37,8 @@ link: https://developer.cisco.com/docs/dna-center/#!get-eo-x-status-for-all-devices notes: - SDK Method used are - eo_x.EoX.get_eo_x_details_per_device, - eo_x.EoX.get_eo_x_status_for_all_devices, + eox.Eox.get_eox_details_per_device, + eox.Eox.get_eox_status_for_all_devices, - Paths used are get /dna/intent/api/v1/eox-status/device, @@ -73,7 +73,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -86,27 +85,30 @@ "alertCount": 0, "eoxDetails": [ { + "name": "string", "bulletinHeadline": "string", + "bulletinName": "string", "bulletinNumber": "string", "bulletinURL": "string", - "endOfHardwareNewServiceAttachmentDate": 0, - "endOfHardwareServiceContractRenewalDate": 0, - "endOfLastHardwareShipDate": 0, - "endOfLifeDate": 0, - "endOfLifeExternalAnnouncementDate": 0, - "endOfSaleDate": 0, - "endOfSignatureReleasesDate": 0, - "endOfSoftwareVulnerabilityOrSecuritySupportDate": 0, - "endOfSoftwareVulnerabilityOrSecuritySupportDateHw": 0, - "endOfSoftwareMaintenanceReleasesDate": 0, + "endOfHardwareNewServiceAttachmentDate": "string", + "endOfHardwareServiceContractRenewalDate": "string", + "endOfLastHardwareShipDate": "string", + "endOfLifeExternalAnnouncementDate": "string", + "endOfSignatureReleasesDate": "string", + "endOfSoftwareVulnerabilityOrSecuritySupportDate": "string", + "endOfSoftwareVulnerabilityOrSecuritySupportDateHw": "string", + "endOfSaleDate": "string", + "endOfLifeDate": "string", + "lastDateOfSupport": "string", + "endOfSoftwareMaintenanceReleasesDate": "string", "eoxAlertType": "string", - "lastDateOfSupport": 0, - "name": "string" + "eoXPhysicalType": "string", + "bulletinPID": "string" } ], "scanStatus": "string", "comments": [ - {} + "string" ], "lastScanTime": 0 }, diff --git a/plugins/modules/eox_status_summary_info.py b/plugins/modules/eox_status_summary_info.py index 26dc6d99d1..a77d84cf60 100644 --- a/plugins/modules/eox_status_summary_info.py +++ b/plugins/modules/eox_status_summary_info.py @@ -11,7 +11,7 @@ description: - Get all Eox Status Summary. - Retrieves EoX summary for all devices in the network. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -20,15 +20,15 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for EoX GetEoXSummary description: Complete reference of the GetEoXSummary API. link: https://developer.cisco.com/docs/dna-center/#!get-eo-x-summary notes: - SDK Method used are - eo_x.EoX.get_eo_x_summary, + eox.Eox.get_eox_summary, - Paths used are get /dna/intent/api/v1/eox-status/summary, @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_api_status_info.py b/plugins/modules/event_api_status_info.py index 8c6cf8d139..2583ec4ebf 100644 --- a/plugins/modules/event_api_status_info.py +++ b/plugins/modules/event_api_status_info.py @@ -24,8 +24,8 @@ - ExecutionId path parameter. Execution ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetStatusAPIForEvents description: Complete reference of the GetStatusAPIForEvents API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_artifact_count_info.py b/plugins/modules/event_artifact_count_info.py index fb7d3ab7db..d9c707967a 100644 --- a/plugins/modules/event_artifact_count_info.py +++ b/plugins/modules/event_artifact_count_info.py @@ -10,7 +10,7 @@ short_description: Information module for Event Artifact Count description: - Get all Event Artifact Count. -- Get the count of registered event artifacts with provided eventIds or tags as mandatory. +- Get the count of registered event artifacts. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management EventArtifactCount description: Complete reference of the EventArtifactCount API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_artifact_info.py b/plugins/modules/event_artifact_info.py index 196b1233c2..2e4bda28ed 100644 --- a/plugins/modules/event_artifact_info.py +++ b/plugins/modules/event_artifact_info.py @@ -30,11 +30,11 @@ offset: description: - Offset query parameter. Record start offset. - type: int + type: float limit: description: - Limit query parameter. # of records to return in result set. - type: int + type: float sortBy: description: - SortBy query parameter. Sort by field. @@ -48,8 +48,8 @@ - Search query parameter. Findd matches in name, description, eventId, type, category. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetEventArtifacts description: Complete reference of the GetEventArtifacts API. @@ -84,7 +84,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -128,6 +127,10 @@ "supportedConnectorTypes": [ "string" ], + "configs": { + "isAlert": true, + "isACKnowledgeable": true + }, "tenantId": "string" } ] diff --git a/plugins/modules/event_config_connector_types_info.py b/plugins/modules/event_config_connector_types_info.py index b30a9659a5..d0d29fd6eb 100644 --- a/plugins/modules/event_config_connector_types_info.py +++ b/plugins/modules/event_config_connector_types_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetConnectorTypes description: Complete reference of the GetConnectorTypes API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_count_info.py b/plugins/modules/event_count_info.py index 8643646556..f2fc3e3fb3 100644 --- a/plugins/modules/event_count_info.py +++ b/plugins/modules/event_count_info.py @@ -28,8 +28,8 @@ - Tags query parameter. The registered Tags should be provided. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CountOfEvents description: Complete reference of the CountOfEvents API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_email_config.py b/plugins/modules/event_email_config.py index fd5fdb882f..b0d6740ac3 100644 --- a/plugins/modules/event_email_config.py +++ b/plugins/modules/event_email_config.py @@ -12,7 +12,7 @@ - Manage operations create and update of the resource Event Email Config. - Create Email Destination. - Update Email Destination. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -35,6 +35,9 @@ port: description: Port. type: str + smtpType: + description: SmtpType. + type: str userName: description: User Name. type: str @@ -51,6 +54,9 @@ port: description: Port. type: str + smtpType: + description: SmtpType. + type: str userName: description: User Name. type: str @@ -62,8 +68,8 @@ description: To Email. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateEmailDestination description: Complete reference of the CreateEmailDestination API. @@ -99,11 +105,13 @@ hostName: string password: string port: string + smtpType: string userName: string secondarySMTPConfig: hostName: string password: string port: string + smtpType: string userName: string subject: string toEmail: string @@ -124,17 +132,18 @@ hostName: string password: string port: string + smtpType: string userName: string secondarySMTPConfig: hostName: string password: string port: string + smtpType: string userName: string subject: string toEmail: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_email_config_create.py b/plugins/modules/event_email_config_create.py index 4be4ec3628..f2ee47b163 100644 --- a/plugins/modules/event_email_config_create.py +++ b/plugins/modules/event_email_config_create.py @@ -34,6 +34,9 @@ port: description: Port. type: str + smtpType: + description: SmtpType. + type: str userName: description: User Name. type: str @@ -50,6 +53,9 @@ port: description: Port. type: str + smtpType: + description: SmtpType. + type: str userName: description: User Name. type: str @@ -61,8 +67,8 @@ description: To Email. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateEmailDestination description: Complete reference of the CreateEmailDestination API. @@ -92,17 +98,18 @@ hostName: string password: string port: string + smtpType: string userName: string secondarySMTPConfig: hostName: string password: string port: string + smtpType: string userName: string subject: string toEmail: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_email_config_info.py b/plugins/modules/event_email_config_info.py index 272118cd79..14a1e37081 100644 --- a/plugins/modules/event_email_config_info.py +++ b/plugins/modules/event_email_config_info.py @@ -11,7 +11,7 @@ description: - Get all Event Email Config. - Get Email Destination. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetEmailDestination description: Complete reference of the GetEmailDestination API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -65,14 +64,14 @@ "port": "string", "userName": "string", "password": "string", - "security": "string" + "smtpType": "string" }, "secondarySMTPConfig": { "hostName": "string", "port": "string", "userName": "string", "password": "string", - "security": "string" + "smtpType": "string" }, "fromEmail": "string", "toEmail": "string", diff --git a/plugins/modules/event_email_config_update.py b/plugins/modules/event_email_config_update.py index c471ff807c..97cd325c75 100644 --- a/plugins/modules/event_email_config_update.py +++ b/plugins/modules/event_email_config_update.py @@ -34,6 +34,9 @@ port: description: Port. type: str + smtpType: + description: SmtpType. + type: str userName: description: User Name. type: str @@ -50,6 +53,9 @@ port: description: Port. type: str + smtpType: + description: SmtpType. + type: str userName: description: User Name. type: str @@ -61,8 +67,8 @@ description: To Email. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management UpdateEmailDestination description: Complete reference of the UpdateEmailDestination API. @@ -92,17 +98,18 @@ hostName: string password: string port: string + smtpType: string userName: string secondarySMTPConfig: hostName: string password: string port: string + smtpType: string userName: string subject: string toEmail: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_info.py b/plugins/modules/event_info.py index a3eafb2975..89bd0f5bbc 100644 --- a/plugins/modules/event_info.py +++ b/plugins/modules/event_info.py @@ -30,11 +30,11 @@ offset: description: - Offset query parameter. The number of Registries to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of Registries to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -44,8 +44,8 @@ - Order query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetEvents description: Complete reference of the GetEvents API. @@ -79,7 +79,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_series_audit_logs_info.py b/plugins/modules/event_series_audit_logs_info.py index b5fa297d91..130acb05d9 100644 --- a/plugins/modules/event_series_audit_logs_info.py +++ b/plugins/modules/event_series_audit_logs_info.py @@ -92,23 +92,23 @@ offset: description: - Offset query parameter. Position of a particular Audit Log record in the data. - type: int + type: float limit: description: - Limit query parameter. Number of Audit Log records to be returned per page. - type: int + type: float startTime: description: - > StartTime query parameter. Start Time in milliseconds since Epoch Eg. 1597950637211 (when provided endTime is mandatory). - type: int + type: float endTime: description: - > EndTime query parameter. End Time in milliseconds since Epoch Eg. 1597961437211 (when provided startTime is mandatory). - type: int + type: float sortBy: description: - > @@ -122,8 +122,8 @@ values asc, desc. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetAuditLogRecords description: Complete reference of the GetAuditLogRecords API. @@ -173,7 +173,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_series_audit_logs_parent_records_info.py b/plugins/modules/event_series_audit_logs_parent_records_info.py index 26bd96d296..db0a6f1261 100644 --- a/plugins/modules/event_series_audit_logs_parent_records_info.py +++ b/plugins/modules/event_series_audit_logs_parent_records_info.py @@ -88,23 +88,23 @@ offset: description: - Offset query parameter. Position of a particular Audit Log record in the data. - type: int + type: float limit: description: - Limit query parameter. Number of Audit Log records to be returned per page. - type: int + type: float startTime: description: - > StartTime query parameter. Start Time in milliseconds since Epoch Eg. 1597950637211 (when provided endTime is mandatory). - type: int + type: float endTime: description: - > EndTime query parameter. End Time in milliseconds since Epoch Eg. 1597961437211 (when provided startTime is mandatory). - type: int + type: float sortBy: description: - > @@ -118,8 +118,8 @@ values asc, desc. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetAuditLogParentRecords description: Complete reference of the GetAuditLogParentRecords API. @@ -168,7 +168,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_series_audit_logs_summary_info.py b/plugins/modules/event_series_audit_logs_summary_info.py index 2e0d2e1331..ee86982ba6 100644 --- a/plugins/modules/event_series_audit_logs_summary_info.py +++ b/plugins/modules/event_series_audit_logs_summary_info.py @@ -98,16 +98,16 @@ - > StartTime query parameter. Start Time in milliseconds since Epoch Eg. 1597950637211 (when provided endTime is mandatory). - type: int + type: float endTime: description: - > EndTime query parameter. End Time in milliseconds since Epoch Eg. 1597961437211 (when provided startTime is mandatory). - type: int + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetAuditLogSummary description: Complete reference of the GetAuditLogSummary API. @@ -154,7 +154,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_series_count_info.py b/plugins/modules/event_series_count_info.py index ebd6576f04..d009a852cf 100644 --- a/plugins/modules/event_series_count_info.py +++ b/plugins/modules/event_series_count_info.py @@ -26,11 +26,11 @@ startTime: description: - StartTime query parameter. Start Time in milliseconds. - type: int + type: float endTime: description: - EndTime query parameter. End Time in milliseconds. - type: int + type: float category: description: - Category query parameter. @@ -56,8 +56,8 @@ - Source query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CountOfNotifications description: Complete reference of the CountOfNotifications API. @@ -94,7 +94,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_series_info.py b/plugins/modules/event_series_info.py index 982aa0cbc3..6feb8bccc1 100644 --- a/plugins/modules/event_series_info.py +++ b/plugins/modules/event_series_info.py @@ -26,11 +26,11 @@ startTime: description: - StartTime query parameter. Start Time in milliseconds. - type: int + type: float endTime: description: - EndTime query parameter. End Time in milliseconds. - type: int + type: float category: description: - Category query parameter. @@ -58,11 +58,11 @@ offset: description: - Offset query parameter. Start Offset. - type: int + type: float limit: description: - Limit query parameter. # of records. - type: int + type: float sortBy: description: - SortBy query parameter. Sort By column. @@ -84,8 +84,8 @@ - SiteId query parameter. Site Id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetNotifications description: Complete reference of the GetNotifications API. @@ -129,7 +129,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_snmp_config.py b/plugins/modules/event_snmp_config.py new file mode 100644 index 0000000000..a6cecc76ab --- /dev/null +++ b/plugins/modules/event_snmp_config.py @@ -0,0 +1,144 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: event_snmp_config +short_description: Resource module for Event Snmp Config +description: +- Manage operations create and update of the resource Event Snmp Config. +- Create SNMP Destination. +- Update SNMP Destination. +version_added: '3.1.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + authPassword: + description: Auth Password. + type: str + community: + description: Required only if snmpVersion is V2C. + type: str + configId: + description: Config Id. + type: str + description: + description: Description. + type: str + ipAddress: + description: Ip Address. + type: str + name: + description: Name. + type: str + port: + description: Port. + type: str + privacyPassword: + description: Privacy Password. + type: str + snmpAuthType: + description: Snmp Auth Type. + type: str + snmpMode: + description: If snmpVersion is V3 it is required and cannot be NONE. + type: str + snmpPrivacyType: + description: Snmp Privacy Type. + type: str + snmpVersion: + description: Snmp Version. + type: str + userName: + description: Required only if snmpVersion is V3. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Event Management CreateSNMPDestination + description: Complete reference of the CreateSNMPDestination API. + link: https://developer.cisco.com/docs/dna-center/#!create-snmp-destination +- name: Cisco DNA Center documentation for Event Management UpdateSNMPDestination + description: Complete reference of the UpdateSNMPDestination API. + link: https://developer.cisco.com/docs/dna-center/#!update-snmp-destination +notes: + - SDK Method used are + event_management.EventManagement.create_snmp_destination, + event_management.EventManagement.update_snmp_destination, + + - Paths used are + post /dna/intent/api/v1/event/snmp-config, + put /dna/intent/api/v1/event/snmp-config, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.event_snmp_config: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + authPassword: string + community: string + description: string + ipAddress: string + name: string + port: string + privacyPassword: string + snmpAuthType: string + snmpMode: string + snmpPrivacyType: string + snmpVersion: string + userName: string + +- name: Update all + cisco.dnac.event_snmp_config: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + authPassword: string + community: string + configId: string + description: string + ipAddress: string + name: string + port: string + privacyPassword: string + snmpAuthType: string + snmpMode: string + snmpPrivacyType: string + snmpVersion: string + userName: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "errorMessage": { + "errors": [ + {} + ] + }, + "apiStatus": "string", + "statusMessage": "string" + } +""" diff --git a/plugins/modules/event_subscription.py b/plugins/modules/event_subscription.py index 0aca4d2dba..16d35cc004 100644 --- a/plugins/modules/event_subscription.py +++ b/plugins/modules/event_subscription.py @@ -94,8 +94,8 @@ description: Subscriptions query parameter. List of EventSubscriptionId's for removal. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateEventSubscriptions description: Complete reference of the CreateEventSubscriptions API. @@ -207,7 +207,6 @@ version: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_count_info.py b/plugins/modules/event_subscription_count_info.py index daf1a6fdfe..3ccc77e3c9 100644 --- a/plugins/modules/event_subscription_count_info.py +++ b/plugins/modules/event_subscription_count_info.py @@ -24,8 +24,8 @@ - EventIds query parameter. List of subscriptions related to the respective eventIds. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CountOfEventSubscriptions description: Complete reference of the CountOfEventSubscriptions API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_details_email_info.py b/plugins/modules/event_subscription_details_email_info.py index b6487d13fd..9a665be609 100644 --- a/plugins/modules/event_subscription_details_email_info.py +++ b/plugins/modules/event_subscription_details_email_info.py @@ -30,11 +30,11 @@ offset: description: - Offset query parameter. The number of Email Subscription detail's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of Email Subscription detail's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -44,8 +44,8 @@ - Order query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetEmailSubscriptionDetails description: Complete reference of the GetEmailSubscriptionDetails API. @@ -79,7 +79,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_details_rest_info.py b/plugins/modules/event_subscription_details_rest_info.py index ee793eff1e..c6e8270896 100644 --- a/plugins/modules/event_subscription_details_rest_info.py +++ b/plugins/modules/event_subscription_details_rest_info.py @@ -32,13 +32,13 @@ - > Offset query parameter. The number of Rest/Webhook Subscription detail's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - > Limit query parameter. The number of Rest/Webhook Subscription detail's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -48,8 +48,8 @@ - Order query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetRestWebhookSubscriptionDetails description: Complete reference of the GetRestWebhookSubscriptionDetails API. @@ -83,7 +83,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -99,7 +98,7 @@ "connectorType": "string", "url": "string", "method": "string", - "trustCert": "string", + "trustCert": true, "headers": [ { "name": "string", @@ -111,7 +110,14 @@ ], "pathParams": [ "string" - ] + ], + "body": "string", + "connectTimeout": 0, + "readTimeout": 0, + "serviceName": "string", + "servicePort": "string", + "namespace": "string", + "proxyRoute": true } ] """ diff --git a/plugins/modules/event_subscription_details_syslog_info.py b/plugins/modules/event_subscription_details_syslog_info.py index 18e68fa779..bba66a02e8 100644 --- a/plugins/modules/event_subscription_details_syslog_info.py +++ b/plugins/modules/event_subscription_details_syslog_info.py @@ -32,11 +32,11 @@ - > Offset query parameter. The number of Syslog Subscription detail's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of Syslog Subscription detail's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -46,8 +46,8 @@ - Order query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetSyslogSubscriptionDetails description: Complete reference of the GetSyslogSubscriptionDetails API. @@ -81,7 +81,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_email.py b/plugins/modules/event_subscription_email.py index 13dc4cfe8e..38c3153e55 100644 --- a/plugins/modules/event_subscription_email.py +++ b/plugins/modules/event_subscription_email.py @@ -72,7 +72,8 @@ elements: dict suboptions: instanceId: - description: (From Get Email Subscription Details --> pick InstanceId). + description: (From Get Email Subscription Details --> pick InstanceId if + available). type: str subscriptionDetails: description: Event Subscription Email's subscriptionDetails. @@ -106,8 +107,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateEmailEventSubscription description: Complete reference of the CreateEmailEventSubscription API. @@ -214,7 +215,6 @@ version: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_email_info.py b/plugins/modules/event_subscription_email_info.py index 3eab8992b4..5697521d91 100644 --- a/plugins/modules/event_subscription_email_info.py +++ b/plugins/modules/event_subscription_email_info.py @@ -28,11 +28,11 @@ offset: description: - Offset query parameter. The number of Subscriptions's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of Subscriptions's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -62,8 +62,8 @@ - Name query parameter. List of email subscriptions related to the respective name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetEmailEventSubscriptions description: Complete reference of the GetEmailEventSubscriptions API. @@ -101,7 +101,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_info.py b/plugins/modules/event_subscription_info.py index 9349d81e71..a627bb3fea 100644 --- a/plugins/modules/event_subscription_info.py +++ b/plugins/modules/event_subscription_info.py @@ -26,11 +26,11 @@ offset: description: - Offset query parameter. The number of Subscriptions's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of Subscriptions's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -40,8 +40,8 @@ - Order query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetEventSubscriptions description: Complete reference of the GetEventSubscriptions API. @@ -74,7 +74,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_rest.py b/plugins/modules/event_subscription_rest.py index 81eea1f2eb..f0162b6ed4 100644 --- a/plugins/modules/event_subscription_rest.py +++ b/plugins/modules/event_subscription_rest.py @@ -90,8 +90,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateRestWebhookEventSubscription description: Complete reference of the CreateRestWebhookEventSubscription API. @@ -186,7 +186,6 @@ version: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_rest_info.py b/plugins/modules/event_subscription_rest_info.py index 06e8dab617..809497c6b8 100644 --- a/plugins/modules/event_subscription_rest_info.py +++ b/plugins/modules/event_subscription_rest_info.py @@ -26,11 +26,11 @@ offset: description: - Offset query parameter. The number of Subscriptions's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of Subscriptions's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -60,8 +60,8 @@ - Name query parameter. List of subscriptions related to the respective name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetRestWebhookEventSubscriptions description: Complete reference of the GetRestWebhookEventSubscriptions API. @@ -99,7 +99,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_syslog.py b/plugins/modules/event_subscription_syslog.py index aeff30dd35..243ffd625d 100644 --- a/plugins/modules/event_subscription_syslog.py +++ b/plugins/modules/event_subscription_syslog.py @@ -90,8 +90,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateSyslogEventSubscription description: Complete reference of the CreateSyslogEventSubscription API. @@ -186,7 +186,6 @@ version: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_subscription_syslog_info.py b/plugins/modules/event_subscription_syslog_info.py index ef6ffb044c..9c193e266b 100644 --- a/plugins/modules/event_subscription_syslog_info.py +++ b/plugins/modules/event_subscription_syslog_info.py @@ -26,11 +26,11 @@ offset: description: - Offset query parameter. The number of Subscriptions's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of Subscriptions's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -60,8 +60,8 @@ - Name query parameter. List of subscriptions related to the respective name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetSyslogEventSubscriptions description: Complete reference of the GetSyslogEventSubscriptions API. @@ -99,7 +99,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_syslog_config.py b/plugins/modules/event_syslog_config.py index 11c6d9508b..13f36b2d0a 100644 --- a/plugins/modules/event_syslog_config.py +++ b/plugins/modules/event_syslog_config.py @@ -12,7 +12,7 @@ - Manage operations create and update of the resource Event Syslog Config. - Create Syslog Destination. - Update Syslog Destination. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -31,13 +31,13 @@ type: str port: description: Port. - type: str + type: int protocol: description: Protocol. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateSyslogDestination description: Complete reference of the CreateSyslogDestination API. @@ -71,7 +71,7 @@ description: string host: string name: string - port: string + port: 0 protocol: string - name: Create @@ -88,11 +88,10 @@ description: string host: string name: string - port: string + port: 0 protocol: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_syslog_config_info.py b/plugins/modules/event_syslog_config_info.py index a2e6009c82..d3f6a9c99b 100644 --- a/plugins/modules/event_syslog_config_info.py +++ b/plugins/modules/event_syslog_config_info.py @@ -11,7 +11,7 @@ description: - Get all Event Syslog Config. - Get Syslog Destination. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -34,11 +34,11 @@ offset: description: - Offset query parameter. The number of syslog configuration's to offset in the resultset whose default value 0. - type: int + type: float limit: description: - Limit query parameter. The number of syslog configuration's to limit in the resultset whose default value 10. - type: int + type: float sortBy: description: - SortBy query parameter. SortBy field name. @@ -48,8 +48,8 @@ - Order query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management GetSyslogDestination description: Complete reference of the GetSyslogDestination API. @@ -84,7 +84,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_webhook_create.py b/plugins/modules/event_webhook_create.py index 2859b76158..c32c9db292 100644 --- a/plugins/modules/event_webhook_create.py +++ b/plugins/modules/event_webhook_create.py @@ -36,6 +36,9 @@ description: Value. type: str type: list + isProxyRoute: + description: Is Proxy Route. + type: bool method: description: Method. type: str @@ -52,8 +55,8 @@ description: Required only for update webhook configuration. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management CreateWebhookDestination description: Complete reference of the CreateWebhookDestination API. @@ -83,6 +86,7 @@ encrypt: true name: string value: string + isProxyRoute: true method: string name: string trustCert: true @@ -90,7 +94,6 @@ webhookId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/event_webhook_read_info.py b/plugins/modules/event_webhook_read_info.py new file mode 100644 index 0000000000..21c50893e6 --- /dev/null +++ b/plugins/modules/event_webhook_read_info.py @@ -0,0 +1,112 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: event_webhook_read_info +short_description: Information module for Event Webhook Read +description: +- Get all Event Webhook Read. +- Get Webhook Destination. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + webhookIds: + description: + - WebhookIds query parameter. List of webhook configurations. + type: str + offset: + description: + - Offset query parameter. The number of webhook configuration's to offset in the resultset whose default value 0. + type: float + limit: + description: + - Limit query parameter. The number of webhook configuration's to limit in the resultset whose default value 10. + type: float + sortBy: + description: + - SortBy query parameter. SortBy field name. + type: str + order: + description: + - Order query parameter. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Event Management GetWebhookDestination + description: Complete reference of the GetWebhookDestination API. + link: https://developer.cisco.com/docs/dna-center/#!get-webhook-destination +notes: + - SDK Method used are + event_management.EventManagement.get_webhook_destination, + + - Paths used are + get /dna/intent/api/v1/event/webhook, + +""" + +EXAMPLES = r""" +- name: Get all Event Webhook Read + cisco.dnac.event_webhook_read_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + webhookIds: string + offset: 0 + limit: 0 + sortBy: string + order: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "errorMessage": { + "errors": [ + "string" + ] + }, + "apiStatus": "string", + "statusMessage": [ + { + "version": "string", + "tenantId": "string", + "webhookId": "string", + "name": "string", + "description": "string", + "url": "string", + "method": "string", + "trustCert": true, + "headers": [ + { + "name": "string", + "value": "string", + "defaultValue": "string", + "encrypt": true + } + ], + "isProxyRoute": true + } + ] + } +""" diff --git a/plugins/modules/event_webhook_update.py b/plugins/modules/event_webhook_update.py index 0c50462ed0..c3471193b8 100644 --- a/plugins/modules/event_webhook_update.py +++ b/plugins/modules/event_webhook_update.py @@ -36,6 +36,9 @@ description: Value. type: str type: list + isProxyRoute: + description: Is Proxy Route. + type: bool method: description: Method. type: str @@ -52,8 +55,8 @@ description: Required only for update webhook configuration. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Event Management UpdateWebhookDestination description: Complete reference of the UpdateWebhookDestination API. @@ -83,6 +86,7 @@ encrypt: true name: string value: string + isProxyRoute: true method: string name: string trustCert: true @@ -90,7 +94,6 @@ webhookId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/events_and_notifications_workflow_manager.py b/plugins/modules/events_and_notifications_workflow_manager.py new file mode 100644 index 0000000000..dafd8188c4 --- /dev/null +++ b/plugins/modules/events_and_notifications_workflow_manager.py @@ -0,0 +1,2733 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2022, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type +__author__ = ("Abhishek Maheshwari, Madhan Sankaranarayanan") + +DOCUMENTATION = r""" +--- +module: events_and_notifications_workflow_manager +short_description: Configure various types of destinations to deliver event notifications from Cisco Catalyst Center Platform. +description: +- Configure various types of destinations to deliver event notifications from Cisco Catalyst Center Platform. +- Configuring/Updating the Webhook destination details in Cisco Catalyst Center. +- Configuring/Updating the Email destination details in Cisco Catalyst Center. +- Configuring/Updating the Syslog destination details in Cisco Catalyst Center. +- Configuring/Updating the SNMP destination details in Cisco Catalyst Center. +- Configuring/Updating the ITSM Integration Settings in Cisco Catalyst Center. +- Deletes the ITSM Integration Settings from Cisco Catalyst Center. +- Create/Update Notification using the above destination in Cisco Catalyst Center. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.workflow_manager_params +author: Abhishek Maheshwari (@abmahesh) + Madhan Sankaranarayanan (@madhansansel) +options: + config_verify: + description: Set to True to verify the Cisco Catalyst Center config after applying the playbook config. + type: bool + default: False + state: + description: The state of Cisco Catalyst Center after module completion. + type: str + choices: [ merged, deleted ] + default: merged + config: + description: List containing the subscription configuration for events, notification on site through one or more channels. + type: list + elements: dict + required: True + suboptions: + webhook_destination: + description: Dictionary containing the details for configuring/updating the REST Endpoint to receive Audit logs and + Events from Cisco Catalyst Center Platform. + type: dict + suboptions: + name: + description: Name of the webhook destination. A unique identifier for the webhook destination within the system. + type: str + required: True + description: + description: A brief explanation of what the webhook destination is used for. + type: str + url: + description: Fully qualified URL to which the webhook will send requests (e.g., "https://ciscocatalyst.com"). + type: str + required: True + method: + description: The HTTP method used by the webhook when sending requests (e.g., POST, PUT). + POST - It is typically used to create a new webhook destination. When you set up a new webhook in Cisco Catalyst Center, + you would use the POST method to send the necessary configuration details (like URL, headers, payload format, etc.) + to the server. + PUT - It is used to update an existing webhook destination. If a webhook destination is already configured and you need to + change any of its settings—such as modifying the URL, adjusting headers, or changing the payload format. + type: str + trust_cert: + description: A boolean that indicates whether to verify the SSL/TLS certificate of the URL, setting this to true will bypass + certificate verification. By default, it is set to false. + type: bool + headers: + description: A list of HTTP headers to be included in the webhook request. Each header is represented as a dictionary. + While giving the headers details we can categorize them into - "Basic, Token and No Auth". + Basic Authentication - It is used to ensure that the receiving server can validate the identity of the requesting server by checking + the credentials against its store. This method is straightforward but less secure compared to others since credentials are sent + encoded but not encrypted. + Token Authentication - It involves security tokens which are typically generated by the server. A client must send this token in the + HTTP header to access resources. It is more secure than Basic Authentication as it allows the server to issue tokens that can have + a limited lifetime, be revoked, and carry specific permissions without exposing user credentials. + No Auth - It implies that no authentication method is required to access the webhook destination. This setting can be used in environments + where security is either handled by other means (such as network isolation) or where the data being transmitted is not sensitive. + type: list + elements: dict + suboptions: + name: + description: Name of the HTTP header. + type: str + value: + description: Value assigned to the HTTP header. + type: str + default_value: + description: Default value for the HTTP header that can be used if no specific value is provided. + type: str + encrypt: + description: Indicates whether the value of the header should be encrypted. Useful for sensitive data. + type: bool + is_proxy_route: + description: A boolean value indicating if the request should use a proxy server. It will set to true for proxy routing, and false for direct + connection. By default, it is set to True. + type: bool + email_destination: + description: Configure settings to send out emails from Cisco Catalyst Center. Also we can create or configure email destination in Cisco Catalyst + Center only once then later we can just modify it. + type: dict + suboptions: + primary_smtp_config: + description: Add the primary configuration for smtp while creating/updating email destination. + type: dict + suboptions: + server_address: + description: Hostname or IP address of the primary SMTP server. Supports both IPv4 and IPv6. + type: str + required: True + smtp_type: + description: The type of connection used for the SMTP server, with options being DEFAULT, TLS, or SSL. By default, it is set to DEFAULT. + DEFAULT - Chooses a standard SMTP connection without encryption. If it's selected then port will be 25 only. + TLS - Initiates an unencrypted SMTP connection and upgrades to TLS encryption when available. If it's selected then port will be + either 465 or 587. + SSL - Begins with an encrypted SMTP connection using SSL from the start. If it's selected then port will be + either 465 or 587. + type: str + required: True + port: + description: Port number used for configuring Primary SMTP Server. Also there is a mapping of smtype and port if snmp_type is DEFAULT + then port is 25 and for smtp_type TLS or SSL we can choose either 465 or 587 as port number. + type: str + username: + description: Username for Authenticating Primary SMTP Server. + type: str + password: + description: Password for Authenticating Primary SMTP Server. + type: str + secondary_smtp_config: + description: Include an optional secondary SMTP configuration when creating or updating an email destination. + type: dict + suboptions: + server_address: + description: Hostname or IP address of the secondary SMTP server. Supports both IPv4 and IPv6. + type: str + smtp_type: + description: The type of connection used for the SMTP server, with options being DEFAULT, TLS, or SSL. By default, it is set to DEFAULT. + DEFAULT - Chooses a standard SMTP connection without encryption. If it's selected then port will be 25 only. + TLS - Initiates an unencrypted SMTP connection and upgrades to TLS encryption when available. If it's selected then port will be + either 465 or 587. + SSL - Begins with an encrypted SMTP connection using SSL from the start. If it's selected then port will be + either 465 or 587. + type: str + port: + description: Port number used for configuring Secondary SMTP Server. Also there is a mapping of smtype and port if snmp_type is DEFAULT + then port is 25 and for smtp_type TLS or SSL we can choose either 465 or 587 as port number. + type: str + username: + description: Username for Authenticating Secondary SMTP Server. + type: str + password: + description: Password for Authenticating Secondary SMTP Server. + type: str + from_email: + description: Sender's email address used when setting up or modifying an email destination. + type: str + required: True + to_email: + description: Recipient's email address that will receive emails when an email destination is created or updated. + type: str + required: True + subject: + description: Subject line of the email to be used when sending emails from the specified email destination. + type: str + required: True + syslog_destination: + description: Dictionary containing the details for configuring/updating the Syslog Server to collect Audit logs and Events + from the Cisco Catalyst Center. + type: dict + suboptions: + name: + description: Name of the syslog destination. + type: str + required: True + description: + description: A brief explanation detailing the purpose of the syslog destination. + type: str + required: True + server_address: + description: Hostname or IP address of the Syslog server. + type: str + required: True + protocol: + description: Protocol used for sending syslog messages (e.g., UDP, TCP). + Transmission Control Protocol (TCP) - It is a connection-oriented protocol used for reliable and ordered communication + between devices on a network. It provides error-checking, retransmission of lost packets, and ensures that data is + delivered in the correct order. + User Datagram Protocol (UDP) - It is a connectionless protocol used for sending datagrams between devices on a network. + It provides a lightweight, best-effort delivery mechanism without guaranteeing delivery or ordering of packets. UDP + is commonly used for real-time applications such as streaming media, online gaming, and VoIP. + type: str + required: True + port: + description: Port number on which the syslog server is listening. It must be in the range of 1-65535. If not given any port then + we will use 514 as default port. + type: int + required: True + snmp_destination: + description: Dictionary containing the details for configuring/updating the SNMP Trap Server to receive Audit logs and Events from + Cisco Catalyst Center. + type: dict + suboptions: + name: + description: Name of the SNMP destination. + type: str + required: True + description: + description: Description of the SNMP destination. + type: str + required: True + server_address: + description: IP address of the SNMP server. + type: str + required: True + port: + description: Port number on which the SNMP server is listening. + type: str + required: True + snmp_version: + description: The SNMP protocol version used for network management and monitoring, selectable between SNMPv2c and SNMPv3. + V2C - Utilizes community strings for the authentication between the SNMP manager (like Cisco Catalyst) and managed network + devices (routers, switches, access points), without encryption, as strings are sent in plain text. + V3 - Offers enhanced security features over V2C, including authentication, integrity, and encryption, using usernames, + passwords, and encryption keys for secure communications. + type: str + community: + description: SNMP community string used for authentication, necessary only when the snmp_version is set to V2C. + type: str + username: + description: Username required for SNMP authentication, applicable exclusively when the snmp_version is configured to V3. + type: str + mode: + description: The security mode for SNMP communication (options - AUTH_PRIVACY, AUTH_NO_PRIVACY, NO_AUTH_NO_PRIVACY). + Mandatory for snmp_version V3 and must not be set to NONE. + AUTH_PRIVACY - The most secure mode, providing both verification of the message source through authentication and protection of + message contents with encryption. + If this option is selected, must need to provide auth_type, auth_password, privacy_type, privacy_password parameter in the playbook. + AUTH_NO_PRIVACY - This mode ensures the authenticity of SNMP messages via a community string for validation but does not encrypt + the data, leaving it vulnerable to interception. + If this option is selected, must need to provide auth_type, auth_password parameter in the playbook. + NO_AUTH_NO_PRIVACY - In this mode, SNMP messages are neither authenticated nor encrypted, making it the least secure as it requires no + credentials or data protection. + If this option is selected, not need to provide auth_type, auth_password, privacy_type, privacy_password parameter in the playbook. + type: str + auth_type: + description: Type of SNMP authentication protocol to use, such as MD5 or SHA. + SHA - Stands for Secure Hash Algorithm, a suite of cryptographic hash functions developed by the National Security Agency (NSA) offering + enhanced security. + MD5 - Refers to Message Digest Algorithm 5, a well-established cryptographic hash function generating a 128-bit hash value, employed in + SNMPv3 for message authenticity and integrity verification. + type: str + auth_password: + description: Password used for SNMP authentication. + type: str + privacy_type: + description: Encryption algorithm used for SNMP privacy, such as AES128. + type: str + privacy_password: + description: Password used for encryption in SNMP privacy. + type: str + itsm_setting: + description: Dictionary containing the configuration details to configure the ServiceNow/BMCRemedy settings to automatically create + incidents/problems/RFC's from Cisco Catalyst Center. + type: dict + suboptions: + instance_name: + description: The name of the ITSM configuration. This helps in identifying the integration within the system. Also while deleting + the ITSM Intergration setting from Cisco Catalyst Center. + type: str + required: True + description: + description: A brief description of the ITSM settings, outlining its purpose or usage within the organization. + type: str + connection_settings: + description: A dictionary of settings required to establish a connection with the ITSM system. + type: dict + suboptions: + url: + description: The URL of the ITSM system API endpoint. This is the base URL used for ITSM service requests. + type: str + required: True + username: + description: The username used for authentication with the ITSM system. This is required for accessing the API. + type: str + required: True + password: + description: The password associated with the username for API authentication. It is recommended to handle this data securely. + type: str + required: True + + +requirements: +- dnacentersdk >= 2.5.5 +- python >= 3.5 + +notes: + - Configuring the webhook destination with headers now supports starting from dnacentersdk version 2.9.1 onwards. This enhancement is in + alignment with Catalyst Center Release 2.3.7.5. + - Configuring the SNMP destination now supports starting from dnacentersdk version 2.9.1 onwards. This enhancement is in + alignment with Catalyst Center Release 2.3.7.5. + - SDK Method used are + events.Events.get_syslog_destination, + events.Events.create_syslog_destination, + events.Events.update_syslog_destination, + events.Events.get_snmp_destination, + events.Events.create_snmp_destination, + events.Events.update_snmp_destination, + events.Events.get_webhook_destination, + events.Events.create_webhook_destination, + events.Events.update_webhook_destination, + events.Events.get_email_destination, + events.Events.create_email_destination, + events.Events.get_status_api_for_events, + events.Events.get_all_itsm_integration_settings, + events.Events.get_itsm_integration_setting_by_id, + events.Events.create_itsm_integration_setting, + events.Events.update_itsm_integration_setting, + events.Events.delete_itsm_integration_setting + +""" + +EXAMPLES = r""" +- name: Create Rest Webhook destination with given name. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - webhook_destination: + name: "webhook test" + description: "creating webhook for testing" + url: "https://10.195.227.14/dna" + method: "POST" + trust_cert: False + +- name: Updating Rest Webhook destination with given name. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - webhook_destination: + name: "webhook test" + description: "updating webhook for testing" + + +- name: Configuring the email destination in the system. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - email_destination: + from_email: "test@cisco.com" + to_email: "demo@cisco.com" + subject: "Ansible testing" + primary_smtp_config: + server_address: "outbound.cisco.com" + port: "25" + smtp_type: "DEFAULT" + +- name: Updating the email destination in the system. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - email_destination: + from_email: "test@cisco.com" + to_email: "demo123@cisco.com" + subject: "Ansible updated email config testing" + +- name: Create Syslog destination with given name. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - syslog_destination: + name: Syslog test + description: "Adding syslog destination" + server_address: "10.30.0.90" + protocol: "TCP" + port: 6553 + +- name: Update Syslog destination with given name. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - syslog_destination: + name: Syslog test + description: "Updating syslog destination." + +- name: Create SNMP destination with given name. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - snmp_destination: + name: Snmp test + description: "Adding snmp destination for testing." + server_address: "10.30.0.90" + port: "25" + snmp_version: "V3" + username: cisco + mode: AUTH_PRIVACY + auth_type: SHA + auth_password: authpass123 + privacy_type: AES128 + privacy_password: privacy123 + +- name: Update SNMP destination with given name. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - snmp_destination: + name: Snmp test + description: "Updating snmp destination with snmp version v2." + server_address: "10.30.0.90" + port: "25" + snmp_version: "V2C" + community: "public123" + +- name: Create ITSM Integration Setting with given name in the system. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - itsm_setting: + instance_name: "ITSM test" + description: "ITSM description for testing" + connection_settings: + url: "http/catalystcenter.com" + username: "catalyst" + password: "catalyst@123" + +- name: Updating ITSM Integration Setting with given name in the system. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: merged + config: + - itsm_setting: + instance_name: "ITSM test" + connection_settings: + url: "http/catalystcenterupdate.com" + password: "catalyst@123" + +- name: Deleting ITSM Integration Setting with given name from the system. + cisco.dnac.events_and_notifications_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + state: deleted + config: + - itsm_setting: + instance_name: "ITSM test" + +""" + +RETURN = r""" + +dnac_response: + description: A dictionary or list with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.dnac.plugins.module_utils.dnac import ( + DnacBase, + validate_list_of_dicts, +) +import re +import time + + +class Events(DnacBase): + """Class containing member attributes for inventory workflow manager module""" + + def __init__(self, module): + super().__init__(module) + self.supported_states = ["merged", "deleted"] + + def validate_input(self): + """ + Validate the fields provided in the playbook. + Checks the configuration provided in the playbook against a predefined specification + to ensure it adheres to the expected structure and data types. + Parameters: + self: The instance of the class containing the 'config' attribute to be validated. + Returns: + The method returns an instance of the class with updated attributes: + - self.msg: A message describing the validation result. + - self.status: The status of the validation (either 'success' or 'failed'). + - self.validated_config: If successful, a validated version of the 'config' parameter. + Example: + To use this method, create an instance of the class and call 'validate_input' on it. + If the validation succeeds, 'self.status' will be 'success' and 'self.validated_config' + will contain the validated configuration. If it fails, 'self.status' will be 'failed', and + 'self.msg' will describe the validation issues. + """ + + temp_spec = { + 'webhook_destination': { + 'type': 'dict', + 'name': {'type': 'str'}, + 'description': {'type': 'str'}, + 'url': {'type': 'str'}, + 'method': {'type': 'str', 'default': 'POST'}, + 'trust_cert': {'type': 'bool', 'default': False}, + 'headers': { + 'type': 'dict', + 'name': {'type': 'str'}, + 'value': {'type': 'str'}, + 'default_value': {'type': 'str'}, + 'encrypt': {'type': 'bool'}, + }, + 'is_proxy_route': {'type': 'bool', 'default': True} + }, + 'email_destination': { + 'type': 'dict', + 'primary_smtp_config': { + 'type': 'dict', + 'server_address': {'type': 'str'}, + 'smtp_type': {'type': 'str', 'default': 'DEFAULT'}, + 'port': {'type': 'str', 'default': '25'}, + 'username': {'type': 'str'}, + 'password': {'type': 'str'}, + }, + 'secondary_smtp_config': { + 'type': 'dict', + 'server_address': {'type': 'str'}, + 'smtp_type': {'type': 'str'}, + 'port': {'type': 'str'}, + 'username': {'type': 'str'}, + 'password': {'type': 'str'}, + }, + 'from_email': {'type': 'str'}, + 'to_email': {'type': 'str'}, + 'subject': {'type': 'str'}, + }, + 'syslog_destination': { + 'type': 'dict', + 'name': {'type': 'str'}, + 'description': {'type': 'str'}, + 'server_address': {'type': 'str'}, + 'protocol': {'type': 'str'}, + 'port': {'type': 'int', 'default': 514}, + }, + 'snmp_destination': { + 'type': 'dict', + 'name': {'type': 'str'}, + 'description': {'type': 'str'}, + 'server_address': {'type': 'str'}, + 'port': {'type': 'str'}, + 'snmp_version': {'type': 'str'}, + 'community': {'type': 'str'}, + 'username': {'type': 'str'}, + 'mode': {'type': 'str'}, + 'auth_type': {'type': 'str'}, + 'auth_password': {'type': 'str'}, + 'privacy_type': {'type': 'str'}, + 'privacy_password': {'type': 'str'}, + }, + 'itsm_setting': { + 'type': 'dict', + 'instance_name': {'type': 'str'}, + 'description': {'type': 'str'}, + 'connection_settings': { + 'type': 'dict', + 'url': {'type': 'str'}, + 'username': {'type': 'str'}, + 'password': {'type': 'str'}, + }, + }, + } + + # Validate device params + valid_temp, invalid_params = validate_list_of_dicts( + self.config, temp_spec + ) + + if invalid_params: + self.msg = "The playbook contains invalid parameters: {0}".format(invalid_params) + self.log(self.msg, "ERROR") + self.status = "failed" + return self + + self.validated_config = valid_temp + self.msg = "Successfully validated playbook configuration parameters using 'validate_input': {0}".format(str(valid_temp)) + self.log(self.msg, "INFO") + self.status = "success" + + return self + + def get_have(self, config): + """ + Retrieve and check destinations information present in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + config (dict): A dictionary containing the configuration details of destinations to be checked. + Returns: + self (object): An instance of a class used for interacting with Cisco Catalyst Center having destination details. + - syslog_destinations (list): A list of syslog destinations existing in Cisco Catalyst Center. + - snmp_destinations (list): A list of SNMP destinations existing in Cisco Catalyst Center. + - webhook_destinations (list): A list of webhook destinations existing in Cisco Catalyst Center. + - email_destination (list): A list of email destinations existing in Cisco Catalyst Center. + - itsm_setting (list): A list of ITSM settings existing in Cisco Catalyst Center. + Description: + This function checks the specified destinations in the playbook against the destinations existing in Cisco Catalyst Center. + It retrieves information about various types of destinations (syslog, SNMP, webhook, email, ITSM) and returns a dictionary + with keys representing each type of destination and corresponding lists of existing destinations in Cisco Catalyst Center. + """ + + have = {} + + if config.get('syslog_destination'): + syslog_destination = self.get_syslog_destination_in_ccc() + if syslog_destination: + have['syslog_destinations'] = syslog_destination + + if config.get('snmp_destination'): + snmp_destinations = self.get_snmp_destination_in_ccc() + if snmp_destinations: + have['snmp_destinations'] = snmp_destinations + + if config.get('webhook_destination'): + webhook_destinations = self.get_webhook_destination_in_ccc() + if webhook_destinations: + have['webhook_destinations'] = webhook_destinations + + if config.get('email_destination'): + email_destination = self.get_email_destination_in_ccc() + if email_destination: + have['email_destination'] = email_destination + + if config.get('itsm_setting'): + itsm_setting = self.get_itsm_settings_in_ccc() + if itsm_setting: + have['itsm_setting'] = itsm_setting + + self.have = have + self.log("Current State (have): {0}".format(str(self.have)), "INFO") + + return self + + def get_want(self, config): + """ + Retrieve the desired configuration parameters specified in the playbook. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + config (dict): A dictionary containing the desired configuration details specified in the playbook. + Returns: + self (object): An instance of the class with the desired configuration parameters collected from the playbook. + Description: + This function retrieves the desired configuration parameters specified in the playbook and organizes them into a dictionary. + It collects details related to various types of destinations (syslog, SNMP, webhook, email, ITSM) based on the playbook configuration + and stores them in the 'want' attribute of the class instance. + """ + + want = {} + + if config.get('syslog_destination'): + want['syslog_details'] = config.get('syslog_destination') + + if config.get('snmp_destination'): + want['snmp_details'] = config.get('snmp_destination') + + if config.get('webhook_destination'): + want['webhook_details'] = config.get('webhook_destination') + + if config.get('email_destination'): + want['email_details'] = config.get('email_destination') + + if config.get('itsm_setting'): + want['itsm_details'] = config.get('itsm_setting') + + self.want = want + self.msg = "Successfully collected all parameters from the playbook " + self.status = "success" + self.log("Desired State (want): {0}".format(str(self.want)), "INFO") + + return self + + def get_syslog_destination_in_ccc(self): + """ + Retrieve the details of syslog destinations present in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + str: A string containing the details of syslog destinations present in Cisco Catalyst Center. + Description: + This function queries Cisco Catalyst Center to retrieve the details of syslog destinations. + The response contains the status message indicating the syslog destinations present in Cisco Catalyst Center. + If no syslog destinations are found, it returns an empty string. + In case of any errors during the API call, an exception is raised with an error message. + """ + try: + response = self.dnac._exec( + family="event_management", + function='get_syslog_destination' + ) + self.log("Received API response from 'get_syslog_destination': {0}".format(str(response)), "DEBUG") + response = response.get('statusMessage') + + if not response: + self.log("There is no Syslog destination present in Cisco Catalyst Center", "INFO") + return response + + return response + + except Exception as e: + self.status = "failed" + self.msg = "Error while getting the details of Syslog destination present in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def get_syslog_destination_with_name(self, name): + """ + Retrieve the details of a syslog destination with a specific name from Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + name (str): The name of the syslog destination to retrieve details for. + Returns: + dict: A dictionary containing the details of the syslog destination with the specified name. + Description: + This function queries Cisco Catalyst Center to retrieve the details of a syslog destination with a specific name. + The response contains the status message indicating the syslog destination details. + If no syslog destination is found with the specified name, it returns None. + In case of any errors during the API call, an exception is raised with an error message. + """ + try: + response = self.dnac._exec( + family="event_management", + function='get_syslog_destination', + op_modifies=True, + params={"name": name} + ) + self.log("Received API response from 'get_syslog_destination': {0}".format(str(response)), "DEBUG") + response = response.get('statusMessage') + + if not response: + self.log("There is no Syslog destination added with the name '{0}' in Cisco Catalyst Center".format(name), "INFO") + return response + syslog_details = response[0] + + return syslog_details + + except Exception as e: + self.status = "failed" + self.msg = "Error while getting the details of Syslog destination with the name '{0}' from Cisco Catalyst Center: {1}".format(name, str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def syslog_dest_needs_update(self, syslog_details, syslog_details_in_ccc): + """ + Check if the syslog destination needs an update based on a comparison between desired and current details. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + syslog_details (dict): A dictionary containing the desired syslog destination details. + syslog_details_in_ccc (dict): A dictionary containing the current syslog destination details in Cisco Catalyst Center. + Returns: + bool: A boolean indicating whether an update is needed for the syslog destination. + Description: + This function compares the desired syslog destination details with the current details retrieved from Cisco Catalyst Center. + It iterates through each key-value pair in the desired syslog details and checks if the corresponding value in the current + details matches or if the desired value is empty. If any discrepancy is found, indicating a difference between desired and + current details, the function sets the 'update_needed' flag to True, indicating that an update is needed. + If no discrepancies are found, the function returns False, indicating that no update is needed. + """ + + update_needed = False + for key, value in syslog_details.items(): + if str(syslog_details_in_ccc[key]) == value or value == "": + continue + else: + update_needed = True + + return update_needed + + def add_syslog_destination(self, syslog_details): + """ + Add a syslog destination to Cisco Catalyst Center based on the provided details. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + syslog_details (dict): A dictionary containing the details of the syslog destination to be added. + Returns: + self (object): An instance of the class with the result of the operation. + - If successful, 'status' is set to 'success', 'result['changed']' is True, and 'msg' contains a success message. + - If unsuccessful, 'status' is set to 'failed', 'result['changed']' is False, and 'msg' contains an error message. + Description: + This function adds a syslog destination to Cisco Catalyst Center using the provided details. + It validates the input parameters, including the protocol, and constructs the necessary parameters for the API call. + If the operation is successful, the function sets the appropriate status, logs a success message, and returns the result. + If the operation fails, the function sets the status to 'failed', logs an error message, and returns the result with + details of the failure. + """ + + try: + name = syslog_details.get('name') + description = syslog_details.get('description') + server_address = syslog_details.get('server_address') + protocol = syslog_details.get('protocol') + + if not self.is_valid_ipv4(server_address): + self.status = "failed" + self.msg = "Invalid server adderess '{0}' given in the playbook for configuring syslog destination".format(server_address) + self.log(self.msg, "ERROR") + return self + + if not protocol: + self.status = "failed" + self.msg = "Protocol is needed while configuring the syslog destionation with name '{0}' in Cisco Catalyst Center".format(name) + self.log(self.msg, "ERROR") + return self + + protocol = protocol.upper() + if protocol not in ["TCP", "UDP"]: + self.status = "failed" + self.msg = """Invalid protocol name '{0}' for creating syslog destination in Cisco Catalyst Center. + Select one of the following protocol 'TCP/UDP'.""".format(protocol) + self.log(self.msg, "ERROR") + return self + + port = syslog_details.get('port', 514) + add_syslog_params = { + 'name': name, + 'description': description, + 'host': server_address, + 'protocol': protocol, + 'port': int(port) + } + + response = self.dnac._exec( + family="event_management", + function='create_syslog_destination', + op_modifies=True, + params=add_syslog_params + ) + self.log("Received API response from 'create_syslog_destination': {0}".format(str(response)), "DEBUG") + status = response.get('apiStatus') + + if status == 'SUCCESS': + self.status = "success" + self.result['changed'] = True + self.msg = "Syslog Destination with name '{0}' added successfully in Cisco Catalyst Center".format(name) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + try: + failure_msg = response.get('errorMessage').get('errors') + except Exception as e: + failure_msg = "Unable to Add syslog destination with name '{0}' in Cisco Catalyst Center".format(name) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while Adding the Syslog destination with the name '{0}' in Cisco Catalyst Center: {1}".format(name, str(e)) + self.log(self.msg, "ERROR") + + return self + + def update_syslog_destination(self, syslog_details, syslog_details_in_ccc): + """ + Update an existing syslog destination in Cisco Catalyst Center with the provided details. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + syslog_details (dict): A dictionary containing the desired syslog destination details to update. + syslog_details_in_ccc (dict): A dictionary containing the current syslog destination details in Cisco Catalyst Center. + Returns: + self (object): An instance of the class with the result of the operation. + - If successful, 'status' is set to 'success', 'result['changed']' is True, and 'msg' contains a success message. + - If unsuccessful, 'status' is set to 'failed', 'result['changed']' is False, and 'msg' contains an error message. + Description: + This function updates an existing syslog destination in Cisco Catalyst Center with the provided details. + It constructs the parameters required for the API call by merging the desired syslog details with the current details. + If the operation is successful, the function sets the appropriate status, logs a success message, and returns the result. + If the operation fails, the function sets the status to 'failed', logs an error message, returns the result with failure details. + """ + + try: + update_syslog_params = {} + update_syslog_params['name'] = syslog_details.get('name') or syslog_details_in_ccc.get('name') + update_syslog_params['description'] = syslog_details.get('description') or syslog_details_in_ccc.get('description') + update_syslog_params['host'] = syslog_details.get('server_address') or syslog_details_in_ccc.get('host') + update_syslog_params['protocol'] = syslog_details.get('protocol') or syslog_details_in_ccc.get('protocol') + update_syslog_params['port'] = int(syslog_details.get('port') or syslog_details_in_ccc.get('port')) + update_syslog_params['configId'] = syslog_details_in_ccc.get('configId') + name = update_syslog_params.get('name') + + if update_syslog_params.get('protocol').upper() not in ["TCP", "UDP"]: + self.status = "failed" + self.msg = """Invalid protocol name '{0}' for updating syslog destination in Cisco Catalyst Center. + Select one of the following protocol 'TCP/UDP'.""".format(update_syslog_params.get('protocol')) + self.log(self.msg, "ERROR") + return self + + server_address = update_syslog_params.get('host') + if not self.is_valid_ipv4(server_address): + self.status = "failed" + self.msg = "Invalid server adderess '{0}' given in the playbook for updating syslog destination".format(server_address) + self.log(self.msg, "ERROR") + return self + + response = self.dnac._exec( + family="event_management", + function='update_syslog_destination', + op_modifies=True, + params=update_syslog_params + ) + self.log("Received API response from 'update_syslog_destination': {0}".format(str(response)), "DEBUG") + status = response.get('apiStatus') + + if status == 'SUCCESS': + self.status = "success" + self.result['changed'] = True + self.msg = "Syslog Destination with name '{0}' updated successfully in Cisco Catalyst Center".format(name) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + try: + failure_msg = response.get('errorMessage').get('errors') + except Exception as e: + failure_msg = "Unable to update syslog destination with name '{0}' in Cisco Catalyst Center".format(name) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while Updating the Syslog destination with the name '{0}' in Cisco Catalyst Center: {1}".format(name, str(e)) + self.log(self.msg, "ERROR") + + return self + + def get_snmp_destination_in_ccc(self): + """ + Retrieve the details of SNMP destinations present in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + dict: A dictionary containing the details of SNMP destinations present in Cisco Catalyst Center. + Description: + This function queries Cisco Catalyst Center to retrieve the details of SNMP destinations. + It utilizes the 'event_management' API endpoint with the 'get_snmp_destination' function. + The response contains information about the SNMP destinations present in Cisco Catalyst Center. + If no SNMP destinations are found, it returns an empty dictionary. + """ + try: + response = self.dnac._exec( + family="event_management", + function='get_snmp_destination' + ) + self.log("Received API response from 'get_snmp_destination': {0}".format(str(response)), "DEBUG") + + if not response: + self.log("There is no SNMP destination present in Cisco Catalyst Center", "INFO") + return response + + return response + + except Exception as e: + self.status = "failed" + self.msg = "Error while getting the details of SNMP destination present in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def collect_snmp_playbook_params(self, snmp_details): + """ + Collect the SNMP playbook parameters based on the provided SNMP details. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + snmp_details (dict): A dictionary containing the SNMP destination details. + Returns: + dict: A dictionary containing the SNMP playbook parameters. + Description: + This function constructs the SNMP playbook parameters based on the provided SNMP destination details. + It extracts relevant information such as name, description etc. + The constructed playbook parameters are returned for further use in the playbook. + """ + + playbook_params = { + 'name': snmp_details.get('name'), + 'description': snmp_details.get('description'), + 'ipAddress': snmp_details.get('server_address'), + 'port': snmp_details.get('port'), + 'snmpVersion': snmp_details.get('snmp_version') + } + server_address = snmp_details.get('server_address') + + if server_address and not self.is_valid_ipv4(server_address): + self.status = "failed" + self.msg = "Invalid server adderess '{0}' given in the playbook for configuring SNMP destination".format(server_address) + self.log(self.msg, "ERROR") + self.check_return_status() + + if playbook_params.get('snmpVersion') == "V2C": + playbook_params['community'] = snmp_details.get('community') + elif playbook_params.get('snmpVersion') == "V3": + playbook_params['userName'] = snmp_details.get('username') + playbook_params['snmpMode'] = snmp_details.get('mode') + + if playbook_params['snmpMode'] == "AUTH_PRIVACY": + playbook_params['snmpAuthType'] = snmp_details.get('auth_type') + playbook_params['authPassword'] = snmp_details.get('auth_password') + playbook_params['snmpPrivacyType'] = snmp_details.get('privacy_type', 'AES128') + playbook_params['privacyPassword'] = snmp_details.get('privacy_password') + elif playbook_params['snmpMode'] == "AUTH_NO_PRIVACY": + playbook_params['snmpAuthType'] = snmp_details.get('auth_type') + playbook_params['authPassword'] = snmp_details.get('auth_password') + + return playbook_params + + def check_snmp_required_parameters(self, snmp_params): + """ + Check if all the required parameters for adding an SNMP destination in Cisco Catalyst Center are present. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + snmp_params (dict): A dictionary containing the SNMP destination parameters. + Returns: + self (object): An instance of the class with the result of the parameter check. + - If all required parameters are present, 'status' is set to 'success', and 'msg' contains a success message. + - If any required parameter is missing, 'status' is set to 'failed', 'msg' contains an error message, + and the missing parameters are logged. + Description: + This function validates whether all the required parameters for adding an SNMP destination in Cisco Catalyst Center + are present in the provided SNMP destination parameters. If any required parameter is missing, it logs an error + message with the missing parameters and sets the status to 'failed'. + If all required parameters are present, it logs a success message and sets the status to 'success'. + """ + + missing_params_list = [] + required_parameter_list = ["name", "description", "ipAddress", "port", "snmpVersion"] + + if snmp_params['snmpVersion'] == "V2C": + required_parameter_list.append("community") + else: + required_parameter_list.extend(["userName", "snmpMode"]) + if snmp_params['snmpMode'] == "AUTH_PRIVACY": + required_parameter_list.extend(["snmpAuthType", "authPassword", "privacyPassword"]) + elif snmp_params['snmpMode'] == "AUTH_NO_PRIVACY": + required_parameter_list.extend(["snmpAuthType", "authPassword"]) + + for item in required_parameter_list: + if snmp_params[item] is None: + missing_params_list.append(item) + + if not missing_params_list: + self.status = "success" + self.msg = "All the required parameters for adding SNMP Destination in Cisco Catalyst Center is present." + self.log(self.msg, "INFO") + return self + + self.status = "failed" + self.msg = "Required parameter '{0}' is missing for adding SNMP Destination in Cisco Catalyst Center".format(str(missing_params_list)) + self.log(self.msg, "ERROR") + + return self + + def add_snmp_destination(self, snmp_params): + """ + Add the SNMP destination in Cisco Catalyst Center using the provided SNMP parameters. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + snmp_params (dict): A dictionary containing the SNMP destination parameters. + + Returns: + self (object): An instance of the class with the result of the SNMP destination addition. + - If the SNMP destination is added successfully, 'status' is set to 'success', + 'changed' is set to True, 'msg' contains a success message, and 'response' contains the API response. + - If the addition fails, 'status' is set to 'failed', 'msg' contains an error message, + and 'response' contains the API error response. + Description: + This function adds an SNMP destination in Cisco Catalyst Center using the provided SNMP parameters. + Upon receiving the API response, it checks the status to determine the success or failure of the operation. + If the addition is successful, it sets the appropriate attributes and logs a success message. + If the addition fails, it logs the error message from the API response. + """ + + try: + response = self.dnac._exec( + family="event_management", + function='create_snmp_destination', + op_modifies=True, + params=snmp_params + ) + self.log("Received API response from 'create_snmp_destination': {0}".format(str(response)), "DEBUG") + status = response.get('apiStatus') + + if status == 'SUCCESS': + self.status = "success" + self.result['changed'] = True + self.msg = "SNMP Destination with name '{0}' added successfully in Cisco Catalyst Center".format(snmp_params.get('name')) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + error_messages = response.get('errorMessage') + if error_messages: + failure_msg = error_messages.get('errors') + else: + failure_msg = "Unable to Add SNMP destination with name '{0}' in Cisco Catalyst Center".format(snmp_params.get('name')) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + return self + + except Exception as e: + self.status = "failed" + self.msg = """Error while Adding the SNMP destination with the name '{0}' in Cisco Catalyst Center: + {1}""".format(snmp_params.get('name'), str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def snmp_dest_needs_update(self, snmp_params, snmp_dest_detail_in_ccc): + """ + Determine if an update is needed for the SNMP destination in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + snmp_params (dict): A dictionary containing the updated SNMP destination parameters. + snmp_dest_detail_in_ccc (dict): A dictionary containing the details of existing SNMP destination in Cisco Catalyst Center. + Returns: + self (object): An instance of the class with the result of the SNMP destination addition. + Description: + This function compares the provided SNMP destination parameters with the existing SNMP destination details + in Cisco Catalyst Center to determine if an update is needed. + If any value is different or empty in the updated parameters compared to the existing details, + it sets 'update_needed' to True, indicating that an update is needed. + Otherwise, if all values match or are empty, it sets 'update_needed' to False. + """ + + update_needed = False + for key, value in snmp_params.items(): + if str(snmp_dest_detail_in_ccc[key]) == str(value) or value == "": + continue + else: + update_needed = True + + return update_needed + + def update_snmp_destination(self, snmp_params, snmp_dest_detail_in_ccc): + """ + Update an existing SNMP destination in Cisco Catalyst Center with the provided parameters. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + snmp_params (dict): A dictionary containing the updated parameters for the SNMP destination. + snmp_dest_detail_in_ccc (dict): A dictionary containing the details of the SNMP destination + currently configured in Cisco Catalyst Center. + Returns: + self (object): An object representing the status of the operation, including whether it was successful or failed, + any error messages encountered during the operation, and whether changes were made to the system. + Description: + This function attempts to update an existing SNMP destination in Cisco Catalyst Center with the provided parameters. + It compares the parameters specified in the playbook (`snmp_params`) with the current configuration of the SNMP destination + in Cisco Catalyst Center (`snmp_dest_detail_in_ccc`). If any parameter differs between the playbook and the current + configuration, the function sends a request to update the SNMP destination with the new parameters. + If the operation is successful, it sets the status to "success" and logs a success message. + If the operation fails, it sets the status to "failed" and logs an error message along with any error details + received from the API response. + """ + try: + update_snmp_params = {} + update_snmp_params['name'] = snmp_params.get('name') or snmp_dest_detail_in_ccc.get('name') + update_snmp_params['description'] = snmp_params.get('description') or snmp_dest_detail_in_ccc.get('description') + update_snmp_params['ipAddress'] = snmp_params.get('ipAddress') or snmp_dest_detail_in_ccc.get('ipAddress') + update_snmp_params['port'] = snmp_params.get('port') or snmp_dest_detail_in_ccc.get('port') + update_snmp_params['snmpVersion'] = snmp_params.get('snmpVersion') or snmp_dest_detail_in_ccc.get('snmpVersion') + + if update_snmp_params.get('port'): + try: + port = int(snmp_params.get('port')) + if port not in range(1, 65536): + self.status = "failed" + self.msg = "Invalid Notification trap port '{0}' given in playbook. Select port from the number range(1, 65535)".format(port) + self.log(self.msg, "ERROR") + return self + except Exception as e: + self.status = "failed" + self.msg = """Invalid datatype for the Notification trap port '{0}' given in playbook. Select port with correct datatype from the + number range(1, 65535).""".format(port) + self.log(self.msg, "ERROR") + return self + + if update_snmp_params['snmpVersion'] == "V2C": + update_snmp_params['community'] = snmp_params.get('community') or snmp_dest_detail_in_ccc.get('community') + else: + update_snmp_params['userName'] = snmp_params.get('userName') or snmp_dest_detail_in_ccc.get('userName') + update_snmp_params['snmpMode'] = snmp_params.get('snmpMode') or snmp_dest_detail_in_ccc.get('snmpMode') + if update_snmp_params['snmpMode'] == "AUTH_PRIVACY": + update_snmp_params['snmpAuthType'] = snmp_params.get('snmpAuthType') or snmp_dest_detail_in_ccc.get('snmpAuthType') + update_snmp_params['authPassword'] = snmp_params.get('authPassword') or snmp_dest_detail_in_ccc.get('authPassword') + update_snmp_params['snmpPrivacyType'] = snmp_params.get('snmpPrivacyType', 'AES128') + update_snmp_params['privacyPassword'] = snmp_params.get('privacyPassword') or snmp_dest_detail_in_ccc.get('privacyPassword') + elif update_snmp_params['snmpMode'] == "AUTH_NO_PRIVACY": + update_snmp_params['snmpAuthType'] = snmp_params.get('snmpAuthType') or snmp_dest_detail_in_ccc.get('snmpAuthType') + update_snmp_params['authPassword'] = snmp_params.get('authPassword') or snmp_dest_detail_in_ccc.get('authPassword') + + update_snmp_params['configId'] = snmp_dest_detail_in_ccc.get('configId') + + response = self.dnac._exec( + family="event_management", + function='update_snmp_destination', + op_modifies=True, + params=update_snmp_params + ) + self.log("Received API response from 'update_snmp_destination': {0}".format(str(response)), "DEBUG") + status = response.get('apiStatus') + + if status == 'SUCCESS': + self.status = "success" + self.result['changed'] = True + self.msg = "SNMP Destination with name '{0}' updated successfully in Cisco Catalyst Center".format(update_snmp_params.get('name')) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + error_messages = response.get('errorMessage') + if error_messages: + failure_msg = error_messages.get('errors') + else: + failure_msg = "Unable to update SNMP destination with name '{0}' in Cisco Catalyst Center".format(update_snmp_params.get('name')) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while Updating the SNMP destination with name '{0}' in Cisco Catalyst Center: {1}".format(update_snmp_params.get('name'), str(e)) + self.log(self.msg, "ERROR") + + return self + + def get_webhook_destination_in_ccc(self): + """ + Retrieve details of Rest Webhook destinations present in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + dict: A dictionary containing details of Rest Webhook destinations present in Cisco Catalyst Center, + or None if no Rest Webhook destinations are found. + Description: + This function retrieves the details of Rest Webhook destinations present in Cisco Catalyst Center + using the 'event_management' API endpoint with the 'get_webhook_destination' function. + If an error occurs during the retrieval process, it logs the error message and raises an Exception. + """ + + try: + response = self.dnac._exec( + family="event_management", + function='get_webhook_destination' + ) + self.log("Received API response from 'get_webhook_destination': {0}".format(str(response)), "DEBUG") + response = response.get('statusMessage') + + if not response: + self.log("There is no Rest Webhook destination present in Cisco Catalyst Center", "INFO") + return response + + return response + + except Exception as e: + self.status = "failed" + self.msg = "Error while getting the details of Webhook destination(s) present in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def collect_webhook_playbook_params(self, webhook_details): + """ + Collect parameters for configuring a Rest Webhook destination from the playbook. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + webhook_details (dict): A dictionary containing the details of the Rest Webhook destination to be configured. + Returns: + dict: A dictionary containing the collected parameters for configuring the Rest Webhook destination. + Description: + This function collects parameters for configuring a Rest Webhook destination from the playbook. + """ + + playbook_params = { + 'name': webhook_details.get('name'), + 'description': webhook_details.get('description'), + 'url': webhook_details.get('url'), + 'method': webhook_details.get('method', 'POST').upper(), + 'trustCert': webhook_details.get('trust_cert', False), + 'isProxyRoute': webhook_details.get('is_proxy_route', True) + } + + if webhook_details.get('headers'): + custom_header = webhook_details['headers'] + playbook_params['customHeaders'] = custom_header + + return playbook_params + + def add_webhook_destination(self, webhook_params): + """ + Add or configure REST webhook destination in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + webhook_params (dict): A dictionary containing the parameters for configuring the REST webhook destination. + Returns: + self (object): An instance of a class representing the status of the operation, including whether it was + successful or failed, any error messages encountered during operation. + Description: + This function attempts to add a REST webhook destination in Cisco Catalyst Center using the provided parameters. + It sends a request to create a webhook destination with the specified parameters. + If the operation is successful, it sets the status to "success" and logs a success message. + If the operation fails, it sets the status to "failed" and logs an error message along with any error details + received from the API response. + """ + + try: + self.log("Requested payload for creating webhook destination - {0}".format(str(webhook_params)), "INFO") + response = self.dnac._exec( + family="event_management", + function='create_webhook_destination', + op_modifies=True, + params=webhook_params + ) + self.log("Received API response from 'create_webhook_destination': {0}".format(str(response)), "DEBUG") + status = response.get('apiStatus') + + if status == 'SUCCESS': + self.status = "success" + self.result['changed'] = True + self.msg = "Webhook Destination with name '{0}' added successfully in Cisco Catalyst Center".format(webhook_params.get('name')) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + error_messages = response.get('errorMessage') + if error_messages: + failure_msg = error_messages.get('errors') + else: + failure_msg = "Unable to Add Webhook destination with name '{0}' in Cisco Catalyst Center".format(webhook_params.get('name')) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while Adding the Webhook destination with the name '{0}' in Cisco Catalyst Center: {1}".format(webhook_params.get('name'), str(e)) + self.log(self.msg, "ERROR") + + return self + + def webhook_dest_needs_update(self, webhook_params, webhook_dest_detail_in_ccc): + """ + Check if updates are needed for a webhook destination in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + webhook_params (dict): A dictionary containing the updated parameters for the webhook destination. + webhook_dest_detail_in_ccc (dict): A dictionary containing the details of the webhook destination + currently configured in Cisco Catalyst Center. + Returns: + bool: A boolean value indicating whether updates are needed for the webhook destination. + Description: + This function compares the parameters specified in the playbook (`webhook_params`) with the current configuration + of the webhook destination in Cisco Catalyst Center (`webhook_dest_detail_in_ccc`). If any parameter differs between + the playbook and the current configuration, it returns True, indicating that updates are needed. + If all parameters match or are None, it returns False, indicating that no updates are needed. + """ + + update_needed = False + for key, value in webhook_params.items(): + if webhook_dest_detail_in_ccc[key] == value or value is None: + continue + else: + update_needed = True + + return update_needed + + def update_webhook_destination(self, webhook_params, webhook_dest_detail_in_ccc): + """ + Update a webhook destination in Cisco Catalyst Center with the provided details. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + webhook_params (dict): A dictionary containing the details of the webhook destination to be updated. + webhook_dest_detail_in_ccc (dict): A dictionary containing the details of the webhook destination in Cisco Catalyst Center. + Returns: + self (object): An instance of a class representing the status of the operation, including whether it was + successful or failed, any error messages encountered during operation. + Description: + This function updates a webhook destination in Cisco Catalyst Center with the provided details. + It constructs the parameters needed for the update based on the provided and existing details. + Then, it sends an API request to update the webhook destination with the constructed parameters. + If the update is successful, it sets the status to "success" and logs the success message. + If the update fails, it sets the status to "failed" and logs the failure message. + """ + + try: + update_webhook_params = {} + update_webhook_params['name'] = webhook_params.get('name') or webhook_dest_detail_in_ccc.get('name') + update_webhook_params['description'] = webhook_params.get('description') or webhook_dest_detail_in_ccc.get('description') + update_webhook_params['url'] = webhook_params.get('url') or webhook_dest_detail_in_ccc.get('url') + update_webhook_params['method'] = webhook_params.get('method') or webhook_dest_detail_in_ccc.get('method') + update_webhook_params['trustCert'] = webhook_params.get('trustCert') or webhook_dest_detail_in_ccc.get('trustCert') + update_webhook_params['isProxyRoute'] = webhook_params.get('isProxyRoute') or webhook_dest_detail_in_ccc.get('isProxyRoute') + update_webhook_params['headers'] = webhook_params.get('headers') + + if not update_webhook_params['headers'] and webhook_dest_detail_in_ccc.get('headers'): + update_webhook_params['headers'] = webhook_dest_detail_in_ccc.get('headers')[0] + + update_webhook_params['webhookId'] = webhook_dest_detail_in_ccc.get('webhookId') + name = update_webhook_params.get('name') + + response = self.dnac._exec( + family="event_management", + function='update_webhook_destination', + op_modifies=True, + params=update_webhook_params + ) + self.log("Received API response from 'update_webhook_destination': {0}".format(str(response)), "DEBUG") + status = response.get('apiStatus') + + if status == 'SUCCESS': + self.status = "success" + self.result['changed'] = True + self.msg = "Rest Webhook Destination with name '{0}' updated successfully in Cisco Catalyst Center".format(name) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + error_messages = response.get('errorMessage') + + if error_messages: + failure_msg = error_messages.get('errors') + else: + failure_msg = "Unable to update rest webhook destination with name '{0}' in Cisco Catalyst Center".format(name) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while Updating the Rest Webhook destination with the name '{0}' in Cisco Catalyst Center: {1}".format(name, str(e)) + self.log(self.msg, "ERROR") + + return self + + def get_email_destination_in_ccc(self): + """ + Retrieve the details of the Email destination present in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + dict or None: A dictionary containing the details of the Email destination if it exists, + otherwise returns None. + Description: + This function retrieves the details of the Email destination present in Cisco Catalyst Center. + If the Email destination exists, it returns a dictionary containing its details. + If no Email destination is found, it returns None. + """ + + try: + response = self.dnac._exec( + family="event_management", + function='get_email_destination' + ) + self.log("Received API response from 'get_email_destination': {0}".format(str(response)), "DEBUG") + + if not response: + self.log("There is no Email destination present in Cisco Catalyst Center", "INFO") + return response + + return response[0] + + except Exception as e: + self.status = "failed" + self.msg = "Error while getting the details of Email destination present in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def collect_email_playbook_params(self, email_details): + """ + Collects the parameters required for configuring Email destinations from the playbook. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + email_details (dict): A dictionary containing the Email destination details from the playbook. + Returns: + dict: A dictionary containing the collected parameters for configuring Email destinations. + Description: + This function collects the parameters required for configuring Email destinations from the playbook. + It extracts parameters such as 'fromEmail', 'toEmail', 'subject', and SMTP configurations + (primary and secondary) from the provided email_details dictionary. + """ + + playbook_params = { + 'fromEmail': email_details.get('from_email'), + 'toEmail': email_details.get('to_email'), + 'subject': email_details.get('subject') + } + + if email_details.get('primary_smtp_config'): + primary_smtp_details = email_details.get('primary_smtp_config') + playbook_params['primarySMTPConfig'] = {} + playbook_params['primarySMTPConfig']['hostName'] = primary_smtp_details.get('server_address') + playbook_params['primarySMTPConfig']['smtpType'] = primary_smtp_details.get('smtp_type', "DEFAULT") + + if playbook_params['primarySMTPConfig']['smtpType'] == 'DEFAULT': + playbook_params['primarySMTPConfig']['port'] = "25" + else: + playbook_params['primarySMTPConfig']['port'] = primary_smtp_details.get('port') + playbook_params['primarySMTPConfig']['userName'] = primary_smtp_details.get('username', '') + playbook_params['primarySMTPConfig']['password'] = primary_smtp_details.get('password', '') + + if email_details.get('secondary_smtp_config'): + secondary_smtp_details = email_details.get('secondary_smtp_config') + playbook_params['secondarySMTPConfig'] = {} + playbook_params['secondarySMTPConfig']['hostName'] = secondary_smtp_details.get('server_address') + playbook_params['secondarySMTPConfig']['smtpType'] = secondary_smtp_details.get('smtp_type', "DEFAULT") + + if playbook_params['secondarySMTPConfig']['smtpType'] == 'DEFAULT': + playbook_params['secondarySMTPConfig']['port'] = "25" + else: + playbook_params['secondarySMTPConfig']['port'] = secondary_smtp_details.get('port') + playbook_params['secondarySMTPConfig']['userName'] = secondary_smtp_details.get('username', '') + playbook_params['secondarySMTPConfig']['password'] = secondary_smtp_details.get('password', '') + + return playbook_params + + def add_email_destination(self, email_params): + """ + Adds an Email destination in Cisco Catalyst Center using the provided parameters. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + email_params (dict): A dictionary containing the parameters required for adding an Email destination. + Returns: + self (object): An instance of a class representing the status of the operation, including whether it was + successful or failed, any error messages encountered during operation. + Description: + This function adds an Email destination in Cisco Catalyst Center using the provided parameters. + After the API call, it checks the status of the execution using the 'get_status_api_for_events' API. + If the status indicates success, it sets the status of the operation as 'success' and logs an informational message. + If the status indicates failure, it sets the status of the operation as 'failed' and logs an error message. + + """ + + try: + response = self.dnac._exec( + family="event_management", + function='create_email_destination', + op_modifies=True, + params=email_params + ) + self.log("Received API response from 'create_email_destination': {0}".format(str(response)), "DEBUG") + status = response.get('statusUri') + status_execution_id = status.split("/")[-1] + + # Now we check the status of API Events for configuring Email destination + status_response = self.dnac._exec( + family="event_management", + function='get_status_api_for_events', + op_modifies=True, + params={"execution_id": status_execution_id} + ) + self.log("Received API response from 'get_status_api_for_events': {0}".format(str(status_response)), "DEBUG") + + if status_response['apiStatus'] == "SUCCESS": + self.status = "success" + self.result['changed'] = True + self.msg = "Email Destination added successfully in Cisco Catalyst Center" + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + error_messages = response.get('errorMessage') + + if error_messages: + failure_msg = error_messages.get('errors') + else: + failure_msg = "Unable to Add Email destination in Cisco Catalyst Center." + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while Adding the Email destination in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + + return self + + def email_dest_needs_update(self, email_params, email_dest_detail_in_ccc): + """ + Checks if an update is needed for an Email destination based on the provided parameters and details. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + email_params (dict): A dictionary containing the parameters for the Email destination to be updated. + email_dest_detail_in_ccc (dict): A dictionary containing the current details of Email destination in Cisco Catalyst Center. + Returns: + bool: A boolean value indicating whether an update is needed for the Email destination. + Description: + This function compares the parameters of the Email destination specified in email_params + with the current details of the Email destination in Cisco Catalyst Center specified in email_dest_detail_in_ccc. + If any parameter value in email_params differs from the corresponding value in email_dest_detail_in_ccc, + it indicates that an update is needed and returns True else it returns False indicating that no update is needed. + """ + + update_needed = False + + for key, value in email_params.items(): + if not email_dest_detail_in_ccc.get(key): + update_needed = True + break + + if isinstance(value, dict): + # Recursive call should impact the update_needed flag + update_needed = self.email_dest_needs_update(value, email_dest_detail_in_ccc[key]) + if update_needed: + break + elif email_dest_detail_in_ccc.get(key) != value and value != "": + update_needed = True + break + + return update_needed + + def update_email_destination(self, email_details, email_dest_detail_in_ccc): + """ + Updates an Email destination based on the provided parameters and current details. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + email_details (dict): A dictionary containing the updated parameters for the Email destination. + email_dest_detail_in_ccc (dict): A dictionary containing the current details of the Email + destination in Cisco Catalyst Center. + Returns: + self (object): An instance of a class representing the result of the update operation. + Description: + This function updates the Email destination in Cisco Catalyst Center based on the provided email_details + and the current details of the Email destination specified in email_dest_detail_in_ccc. + It constructs the update_email_params dictionary with the updated parameters. + If the update is successful, it sets the status to 'success' and logs a success message. + If the update fails, it sets the status to 'failed' and logs an error message. + Finally, it returns the result object containing the status and response message. + """ + + try: + update_email_params = {} + update_email_params['primarySMTPConfig'] = email_details.get('primarySMTPConfig') or email_dest_detail_in_ccc.get('primarySMTPConfig') + update_email_params['secondarySMTPConfig'] = email_details.get('secondarySMTPConfig') or email_dest_detail_in_ccc.get('secondarySMTPConfig', 'None') + update_email_params['fromEmail'] = email_details.get('fromEmail') or email_dest_detail_in_ccc.get('fromEmail') + update_email_params['toEmail'] = email_details.get('toEmail') or email_dest_detail_in_ccc.get('toEmail') + update_email_params['subject'] = email_details.get('subject') or email_dest_detail_in_ccc.get('subject') + update_email_params['emailConfigId'] = email_dest_detail_in_ccc.get('emailConfigId') + + response = self.dnac._exec( + family="event_management", + function='update_email_destination', + op_modifies=True, + params=update_email_params + ) + self.log("Received API response from 'update_email_destination': {0}".format(str(response)), "DEBUG") + time.sleep(2) + status = response.get('statusUri') + status_execution_id = status.split("/")[-1] + + # Now we check the status of API Events for configuring Email destination + status_response = self.dnac._exec( + family="event_management", + function='get_status_api_for_events', + op_modifies=True, + params={"execution_id": status_execution_id} + ) + self.log("Received API response from 'get_status_api_for_events': {0}".format(str(status_response)), "DEBUG") + + if status_response['apiStatus'] == "SUCCESS": + self.status = "success" + self.result['changed'] = True + self.msg = "Email Destination updated successfully in Cisco Catalyst Center" + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + error_messages = status_response.get('errorMessage') + + if error_messages: + failure_msg = error_messages.get('errors') + else: + failure_msg = "Unable to update Email destination in Cisco Catalyst Center." + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while Updating the Email destination in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + + return self + + def get_itsm_settings_in_ccc(self): + """ + Retrieves the ITSM Integration Settings present in Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + dict: A dictionary containing the list of details of ITSM Integration Settings. + Description: + This function retrieves the ITSM Integration Settings present in Cisco Catalyst Center + by executing the 'get_all_itsm_integration_settings' API call. + It logs the API response and extracts the data. + If there are no ITSM Integration Settings, it logs an INFO message. + If an error occurs during the process, it logs an ERROR message and raises an Exception. + """ + + try: + response = self.dnac._exec( + family="itsm_integration", + function='get_all_itsm_integration_settings' + ) + self.log("Received API response from 'get_all_itsm_integration_settings': {0}".format(str(response)), "DEBUG") + response = response.get('data') + if not response: + self.log("There is no ITSM Integration settings present in Cisco Catalyst Center", "INFO") + + return response + + except Exception as e: + self.status = "failed" + self.msg = "Error while getting the details of ITSM Integration Settings present in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def get_itsm_settings_by_id(self, itsm_id): + """ + Retrieves the ITSM Integration Settings with the specified ID from Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + itsm_id (str): The ID of the ITSM Integration Setting to retrieve. + Returns: + dict: A dictionary containing the ITSM Integration Setting information for the given itsm id. + Description: + This function retrieves the ITSM Integration Setting with the specified ID from Cisco Catalyst Center. + It logs the API response and returns the data if it exists. + If there is no ITSM Integration Setting with the given ID, it logs an INFO message. + If an error occurs during the process, it logs an ERROR message and raises an Exception. + """ + + try: + response = self.dnac._exec( + family="itsm_integration", + function='get_itsm_integration_setting_by_id', + op_modifies=True, + params={"instance_id": itsm_id} + ) + self.log("Received API response from 'get_itsm_integration_setting_by_id': {0}".format(str(response)), "DEBUG") + + if not response: + self.log("There is no ITSM Integration settings with given ID present in Cisco Catalyst Center", "INFO") + + return response + + except Exception as e: + self.status = "failed" + self.msg = "Error while getting the details of ITSM Integration Setting by id present in Cisco Catalyst Center: {0}".format(str(e)) + self.log(self.msg, "ERROR") + self.check_return_status() + + def collect_itsm_playbook_params(self, itsm_details): + """ + Constructs the ITSM playbook parameters from the provided ITSM details. + Args: + self (object): An instance of a class used for ITSM playbook operations. + itsm_details (dict): A dictionary containing details about an ITSM integration. + Returns: + dict: A dictionary structured as required by the ITSM playbook for interaction. + Description: + This function takes a dictionary containing ITSM integration details, and constructs + a set of parameters formatted to meet the requirements of an ITSM playbook. These parameters can then be used to + configure ITSM connections through playbook executions. + """ + + playbook_params = { + 'name': itsm_details.get('instance_name'), + 'description': itsm_details.get('description'), + 'dypName': 'ServiceNowConnection' + } + playbook_params['data'] = {} + connection_details = itsm_details.get('connection_settings') + + if connection_details: + playbook_params['data']['ConnectionSettings'] = {} + playbook_params['data']['ConnectionSettings']['Url'] = connection_details.get('url') + playbook_params['data']['ConnectionSettings']['Auth_UserName'] = connection_details.get('username') + playbook_params['data']['ConnectionSettings']['Auth_Password'] = connection_details.get('password') + + return playbook_params + + def check_required_itsm_param(self, itsm_params, invalid_itsm_params): + """ + Recursively checks for required ITSM parameters and collects any that are missing. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + itsm_params (dict): A dictionary of ITSM parameters that need validation. + invalid_itsm_params (list): A list to accumulate the keys of missing parameters. + Returns: + list: A list containing the keys of parameters that are found to be missing or None. + Description: + This method iteratively and recursively examines a dictionary of ITSM parameters + to ensure that all necessary parameters except 'description' are present and not None. + If a parameter is found to be missing or explicitly set to None, its key is added to the + 'invalid_itsm_params' list. This function is particularly useful for validating nested + parameter structures commonly found in configurations for ITSM systems. + """ + + for key, value in itsm_params.items(): + if isinstance(value, dict): + self.check_required_itsm_param(value, invalid_itsm_params) + elif key == "description": + continue + elif itsm_params.get(key) is None: + invalid_itsm_params.append(key) + + return invalid_itsm_params + + def create_itsm_integration_setting(self, itsm_params): + """ + Creates a new ITSM integration setting in the Cisco Catalyst Center using provided parameters. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + itsm_params (dict): A dictionary containing the parameters necessary to create an ITSM integration setting. + Returns: + self (object): An instance of a class representing the status of the operation, including whether it was + successful or failed, any error messages encountered during operation. + Description: + This method sends a request to the Cisco Catalyst Center to create an ITSM integration setting based on the + parameters provided in 'itsm_params'. + It then makes an API call and logs the response. If the creation is successful, indicated by the presence + of a 'createdDate' in the response, it logs a success message, sets the internal state to 'success', and + marks the operation as having changed the system state. If the creation fails, it attempts to log any errors + returned by the API or logs a generic failure message if no specific error is provided. + """ + + try: + instance_name = itsm_params.get('name') + response = self.dnac._exec( + family="itsm_integration", + function='create_itsm_integration_setting', + op_modifies=True, + params=itsm_params + ) + self.log("Received API response from 'create_itsm_integration_setting': {0}".format(str(response)), "DEBUG") + created_date = response.get('createdDate') + + if created_date: + self.status = "success" + self.result['changed'] = True + self.msg = "ITSM Integration Settings with name '{0}' has been created successfully in Cisco Catalyst Center".format(instance_name) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + failure_msg = response.get('errors') + + if not failure_msg: + failure_msg = "Unable to create ITSM Integration Settings with name '{0}' in Cisco Catalyst Center".format(instance_name) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = "Error while creating the ITSM Integration Settings with name '{0}' in Cisco Catalyst Center: {1}".format(instance_name, str(e)) + self.log(self.msg, "ERROR") + + return self + + def itsm_needs_update(self, itsm_params, itsm_in_ccc): + """ + Checks if the ITSM settings in Cisco Catalyst Center need to be updated based on provided parameters. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + itsm_params (dict): A dictionary containing the new ITSM settings parameters. + itsm_in_ccc (dict): A dictionary containing the existing ITSM settings in the Cisco Catalyst Center. + Returns: + bool: True if an update is required based on the differences between the provided parameters and the existing settings, False otherwise. + Description: + This method compares provided ITSM integration parameters against the current settings stored in the Cisco Catalyst Center + to determine if an update is necessary. + If any of the checked fields or connection settings differ between the provided parameters and the existing settings, the method + will return True indicating an update is required. Otherwise, it returns False. + """ + + itsm_require_update = False + required_params = ["name", "description"] + for key in required_params: + if key == "description" and itsm_params[key]: + if itsm_params[key] != itsm_in_ccc[key]: + itsm_require_update = True + return itsm_require_update + elif itsm_params[key] != itsm_in_ccc[key]: + itsm_require_update = True + return itsm_require_update + + if itsm_params.get('data') is None or itsm_params.get('data').get('ConnectionSettings') is None: + self.log("ITSM Connection settings parameters are not given in the input playbook so no update required.", "INFO") + return itsm_require_update + + url = itsm_params.get('data').get('ConnectionSettings').get('Url') + username = itsm_params.get('data').get('ConnectionSettings').get('Auth_UserName') + + if url and url != itsm_in_ccc.get('data').get('ConnectionSettings').get('Url'): + itsm_require_update = True + if username and username != itsm_in_ccc.get('data').get('ConnectionSettings').get('Auth_UserName'): + itsm_require_update = True + + return itsm_require_update + + def update_itsm_integration_setting(self, itsm_params, itsm_in_ccc): + """ + Updates the ITSM integration settings in the Cisco Catalyst Center based on the provided parameters. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + itsm_params (dict): A dictionary containing the new ITSM settings parameters. + itsm_in_ccc (dict): A dictionary containing the existing ITSM settings in the Cisco Catalyst Center. + Returns: + self (object): The instance itself with updated status and message properties reflecting the result of the operation. + Description: + This method updates existing ITSM integration settings in the Cisco Catalyst Center using the provided new parameters. + The method performs several checks: + - It verifies that the 'password' is provided when updating the connection settings. If not, it sets the status + to 'failed' and logs an informational message. + - It validates that the provided URL starts with 'https://'. If the URL is invalid, it sets the status to 'failed' and + logs an informational message. + Upon successful update, the method logs the success and returns the instance with a 'success' status. If the update + fails for any reason (such as an invalid URL or API errors), it logs the failure and returns the instance with a 'failed' + status. + """ + + try: + update_itsm_params = {} + update_itsm_params['name'] = itsm_params.get('name') or itsm_in_ccc.get('name') + update_itsm_params['description'] = itsm_params.get('description') or itsm_in_ccc.get('description') + update_itsm_params['dypName'] = 'ServiceNowConnection' + + update_itsm_params['data'] = {} + update_itsm_params['data']['ConnectionSettings'] = {} + if itsm_params.get('data') is None or itsm_params.get('data').get('ConnectionSettings') is None: + update_itsm_params['data']['ConnectionSettings']['Url'] = itsm_in_ccc.get('data').get('ConnectionSettings').get('Url') + update_itsm_params['data']['ConnectionSettings']['Auth_UserName'] = itsm_in_ccc.get('data').get('ConnectionSettings').get('Auth_UserName') + else: + connection_params = itsm_params.get('data').get('ConnectionSettings') + update_itsm_params['data']['ConnectionSettings']['Url'] = connection_params.get('Url') + update_itsm_params['data']['ConnectionSettings']['Auth_UserName'] = connection_params.get('Auth_UserName') + + if not connection_params.get('Auth_Password'): + self.status = "failed" + self.msg = """Unable to update ITSM setting '{0}' as 'Auth Password' is the required parameter for updating + ITSM Intergartion setting.""".format(update_itsm_params.get('name')) + self.log(self.msg, "INFO") + return self + + update_itsm_params['data']['ConnectionSettings']['Auth_Password'] = connection_params.get('Auth_Password') + + # Check whether the given url is valid or not + url = update_itsm_params.get('data').get('ConnectionSettings').get('Url') + regex_pattern = r'https://\S+' + + if not re.match(regex_pattern, url): + self.status = "failed" + self.msg = "Given url '{0}' is invalid url for ITSM Intergartion setting. It must start with 'https://'".format(url) + self.log(self.msg, "ERROR") + return self + + itsm_param_dict = { + 'payload': update_itsm_params, + 'instance_id': itsm_in_ccc.get('id') + } + + response = self.dnac._exec( + family="itsm_integration", + function='update_itsm_integration_setting', + op_modifies=True, + params=itsm_param_dict, + ) + self.log("Received API response from 'update_itsm_integration_setting': {0}".format(str(response)), "DEBUG") + + updated_date = response.get('updatedDate') + + if updated_date: + self.status = "success" + self.result['changed'] = True + self.msg = """ITSM Integration Settings with name '{0}' has been updated successfully in Cisco Catalyst + Center.""".format(update_itsm_params.get('name')) + self.log(self.msg, "INFO") + self.result['response'] = self.msg + return self + + self.status = "failed" + failure_msg = response.get('errors') + + if not failure_msg: + failure_msg = "Unable to update ITSM Integration Settings with name '{0}' in Cisco Catalyst Center".format(update_itsm_params.get('name')) + + self.msg = failure_msg + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + + except Exception as e: + self.status = "failed" + self.msg = """Error while Updating the ITSM Integration Settings with name '{0}' in Cisco Catalyst Center due to: + {1}""".format(update_itsm_params.get('name'), str(e)) + self.log(self.msg, "ERROR") + + return self + + def delete_itsm_integration_setting(self, itsm_name, itsm_id): + """ + Deletes a specified ITSM integration setting from the Cisco Catalyst Center. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + itsm_name (str): The name of the ITSM integration setting to be deleted. + itsm_id (str): The unique identifier of the ITSM integration setting to be deleted. + Returns: + self (object): The instance itself with updated status and message properties reflecting the result of the operation. + Description: + This method attempts to delete an ITSM integration setting based on the provided name and ID. + If the deletion is not successful, the method logs an error message and sets the 'status' attribute to 'failed'. + This could occur if the ITSM integration setting does not exist or due to a failure in the API call. + Exceptions caught during the API call are handled by logging an error message detailing the issue and setting the 'status' + attribute to 'failed'. + """ + + try: + response = self.dnac._exec( + family="itsm_integration", + function='delete_itsm_integration_setting', + op_modifies=True, + params={"instance_id": itsm_id} + ) + self.log("Received API response from 'delete_itsm_integration_setting': {0}".format(str(response)), "DEBUG") + + if "successfully" in response: + self.msg = "ITSM Integration settings instance with name '{0}' deleted successfully from Cisco Catalyst Center".format(itsm_name) + self.status = "success" + self.log(self.msg, "INFO") + self.result['changed'] = True + self.result['response'] = self.msg + return self + + self.status = "failed" + self.msg = "Cannot delete ITSM Integration settings instance with name '{0}' from Cisco Catalyst Center".format(itsm_name) + self.log(self.msg, "ERROR") + + except Exception as e: + self.status = "failed" + self.msg = "Error while deleting ITSM Integration Setting with name '{0}' from Cisco Catalyst Center due to: {1}".format(itsm_name, str(e)) + self.log(self.msg, "ERROR") + + return self + + def get_diff_merged(self, config): + """ + Processes the configuration difference and merges them into Cisco Catalyst Center. + This method updates Cisco Catalyst Center configurations based on the differences detected + between the desired state (`want`) and the current state (`have`). It handles different + types of configurations such as syslog, SNMP, REST webhook, email, and ITSM settings. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + config (dict): A dictionary containing various destination settings that may include + syslog destination, SNMP destination, REST webhook destination, + email destination, and ITSM settings. Each key should point to a dictionary + that defines specific configuration for that setting type. + Return: + self (object): Returns the instance itself after potentially modifying internal state to reflect + the status of operation, messages to log, and response details. + Description: + This method acts as a controller that delegates specific tasks such as adding or updating + configurations for syslog, SNMP, REST webhook, email, and ITSM settings in the Cisco Catalyst + Center. It ensures required parameters are present, validates them, and calls the appropriate + methods to add or update the configurations. Error handling is included to manage any exceptions + or invalid configurations, updating the internal state to reflect these errors. + """ + + # Create/Update Rest Webhook destination in Cisco Catalyst Center + if config.get('webhook_destination'): + webhook_details = self.want.get('webhook_details') + destination_name = webhook_details.get('name') + + if not destination_name: + self.status = "failed" + self.msg = "Name is required parameter for adding/updating Webhook destination for creating/updating the event." + self.log(self.msg, "ERROR") + return self + + is_destination_exist = False + for webhook_dict in self.have.get('webhook_destinations'): + if webhook_dict['name'] == destination_name: + webhook_dest_detail_in_ccc = webhook_dict + is_destination_exist = True + break + webhook_params = self.collect_webhook_playbook_params(webhook_details) + + if webhook_params.get('method') not in ["POST", "PUT"]: + self.status = "failed" + self.msg = """Invalid Webhook method name '{0}' for creating/updating Webhook destination in Cisco Catalyst Center. + Select one of the following method 'POST/PUT'.""".format(webhook_params.get('method')) + self.log(self.msg, "ERROR") + return self + + regex_pattern = r'https://\S+' + url = webhook_params.get('url') + + if not re.match(regex_pattern, url): + self.status = "failed" + self.msg = "Given url '{0}' is invalid url for Creating/Updating Webhook destination. It must starts with 'https://'".format(url) + self.log(self.msg, "ERROR") + return self + + if not is_destination_exist: + # Need to Add snmp destination in Cisco Catalyst Center with given playbook params + if not url: + self.status = "failed" + self.msg = "Url is required parameter for creating Webhook destination for creating/updating the event in Cisco Catalyst Center." + self.log(self.msg, "ERROR") + return self + + self.add_webhook_destination(webhook_params).check_return_status() + else: + # Check destination needs update and if yes then update SNMP Destination + webhook_need_update = self.webhook_dest_needs_update(webhook_params, webhook_dest_detail_in_ccc) + + if not webhook_need_update: + self.msg = "Webhook Destination with name '{0}' needs no update in Cisco Catalyst Center".format(destination_name) + self.log(self.msg, "INFO") + self.result['changed'] = False + self.result['response'] = self.msg + else: + # Update the syslog destination with given + self.update_webhook_destination(webhook_params, webhook_dest_detail_in_ccc).check_return_status() + + # Create/Update Email destination in Cisco Catalyst Center + if config.get('email_destination'): + email_details = self.want.get('email_details') + email_params = self.collect_email_playbook_params(email_details) + + if not self.have.get('email_destination'): + # Need to Add snmp destination in Cisco Catalyst Center with given playbook params + required_params = ['fromEmail', 'toEmail', 'subject'] + invalid_email_params = [] + for item in required_params: + if not email_params[item]: + invalid_email_params.append(item) + if email_params.get('primarySMTPConfig') and not email_params.get('primarySMTPConfig').get('hostName'): + invalid_email_params.append('server_address') + + if invalid_email_params: + self.status = "failed" + self.msg = """Required parameter '{0}' for configuring Email Destination in Cisco Catalyst Center + is missing.""".format(str(invalid_email_params)) + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + return self + self.log("Required parameter validated successfully for adding Email Destination in Cisco Catalyst Center.", "INFO") + self.add_email_destination(email_params).check_return_status() + else: + # Check destination needs update and if yes then update Email Destination + email_dest_detail_in_ccc = self.have.get('email_destination') + email_need_update = self.email_dest_needs_update(email_params, email_dest_detail_in_ccc) + + if not email_need_update: + self.msg = "Email Destination needs no update in Cisco Catalyst Center" + self.log(self.msg, "INFO") + self.result['changed'] = False + self.result['response'] = self.msg + else: + # Update the email destination with given details in the playbook + self.update_email_destination(email_params, email_dest_detail_in_ccc).check_return_status() + + # Create/Update Syslog destination in Cisco Catalyst Center + if config.get('syslog_destination'): + syslog_details = self.want.get('syslog_details') + name = syslog_details.get('name') + port = syslog_details.get('port') + + if not name: + self.status = "failed" + self.msg = "Name is required parameter for adding/updating syslog destination for creating/updating the event." + self.log(self.msg, "ERROR") + return self + + if isinstance(port, str): + if not port.isdigit() or (int(port) not in range(1, 65536)): + self.status = "failed" + self.msg = """Invalid Syslog destination port '{0}' given in playbook. Please choose a port within the range of + numbers (1, 65535)""".format(port) + self.log(self.msg, "ERROR") + return self + + if isinstance(port, int) and (int(port) not in range(1, 65536)): + self.status = "failed" + self.msg = "Invalid Syslog destination port '{0}' given in playbook. Please choose a port within the range of numbers (1, 65535)".format(port) + self.log(self.msg, "ERROR") + return self + + syslog_details_in_ccc = self.get_syslog_destination_with_name(name) + + if not syslog_details_in_ccc: + # We need to Add the Syslog Destination in the Catalyst Center + self.add_syslog_destination(syslog_details).check_return_status() + else: + # Check destination needs update and if yes then update Syslog Destination + syslog_need_update = self.syslog_dest_needs_update(syslog_details, syslog_details_in_ccc) + if not syslog_need_update: + self.msg = "Syslog Destination with name '{0}' needs no update in Cisco Catalyst Center".format(name) + self.log(self.msg, "INFO") + self.result['changed'] = False + self.result['response'] = self.msg + else: + # Update the syslog destination with given + self.update_syslog_destination(syslog_details, syslog_details_in_ccc).check_return_status() + + # Create/Update snmp destination in Cisco Catalyst Center + if config.get('snmp_destination'): + snmp_details = self.want.get('snmp_details') + destination_name = snmp_details.get('name') + + if not destination_name: + self.status = "failed" + self.msg = "Name is required parameter for adding/updating SNMP destination for creating/updating the event." + self.log(self.msg, "ERROR") + return self + is_destination_exist = False + + for snmp_dict in self.have.get('snmp_destinations'): + if snmp_dict['name'] == destination_name: + snmp_dest_detail_in_ccc = snmp_dict + is_destination_exist = True + break + snmp_params = self.collect_snmp_playbook_params(snmp_details) + + if snmp_params.get('port'): + try: + port = int(snmp_params.get('port')) + if port not in range(1, 65536): + self.status = "failed" + self.msg = "Invalid Notification trap port '{0}' given in playbook. Select port from the number range(1, 65535)".format(port) + self.log(self.msg, "ERROR") + return self + except Exception as e: + self.status = "failed" + self.msg = "Invalid Notification trap port '{0}' given in playbook. Select port from the number range(1, 65535)".format(port) + self.log(self.msg, "ERROR") + return self + + if not is_destination_exist: + # Need to Add snmp destination in Cisco Catalyst Center with given playbook params + self.check_snmp_required_parameters(snmp_params).check_return_status() + self.log("""Required parameter validated successfully for adding SNMP Destination with name '{0}' in Cisco + Catalyst Center.""".format(destination_name), "INFO") + self.add_snmp_destination(snmp_params).check_return_status() + else: + # Check destination needs update and if yes then update SNMP Destination + snmp_need_update = self.snmp_dest_needs_update(snmp_params, snmp_dest_detail_in_ccc) + if not snmp_need_update: + self.msg = "SNMP Destination with name '{0}' needs no update in Cisco Catalyst Center".format(destination_name) + self.log(self.msg, "INFO") + self.result['changed'] = False + self.result['response'] = self.msg + else: + # Update the email destination with given details in the playbook + self.update_snmp_destination(snmp_params, snmp_dest_detail_in_ccc).check_return_status() + + # Create/Update ITSM Integration Settings in Cisco Catalyst Center + if config.get('itsm_setting'): + itsm_details = self.want.get('itsm_details') + itsm_name = itsm_details.get('instance_name') + if not itsm_name: + self.status = "failed" + self.msg = "Instance name is required parameter for adding/updating ITSM integration setting in Cisco Catalyst Center." + self.log(self.msg, "ERROR") + return self + + itsm_params = self.collect_itsm_playbook_params(itsm_details) + + is_itsm_exist = False + itsm_detail_in_ccc = self.have.get('itsm_setting') + if not itsm_detail_in_ccc: + self.log("There is no ITSM Intergartion setting present in Cisco Catalyst Center", "INFO") + else: + # Check whether the given itsm integration present in Cisco Catalyst Center or not. + for itsm in itsm_detail_in_ccc: + if itsm['name'] == itsm_name: + itsm_id = itsm['id'] + is_itsm_exist = True + break + + if not is_itsm_exist: + # Need to Add snmp destination in Cisco Catalyst Center with given playbook params + invalid_itsm_params = [] + invalid_itsm_params = self.check_required_itsm_param(itsm_params, invalid_itsm_params) + connection_setting = itsm_params.get('data').get('ConnectionSettings') + + if not connection_setting: + invalid_itsm_params.extends(["url", "username", "password"]) + self.status = "failed" + self.msg = """Required parameter '{0}' for configuring ITSM Intergartion setting in Cisco Catalyst + Center is missing.""".format(str(invalid_itsm_params)) + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + return self + + # Check whether the url exist or not and if exists is it valid + url = connection_setting.get('Url') + if not url and "Url" not in invalid_itsm_params: + invalid_itsm_params.append("URL") + + if invalid_itsm_params: + self.status = "failed" + self.msg = """Required parameter '{0}' for configuring ITSM Intergartion setting in Cisco Catalyst + Center is missing.""".format(str(invalid_itsm_params)) + self.log(self.msg, "ERROR") + self.result['response'] = self.msg + return self + + regex_pattern = r'https://\S+' + if not re.match(regex_pattern, url): + self.status = "failed" + self.msg = "Given url '{0}' is invalid url for ITSM Intergartion setting. It must starts with 'https://'".format(url) + self.log(self.msg, "ERROR") + return self + + self.log("Required parameter validated successfully for configuring ITSM Intergartion setting in Cisco Catalyst Center.", "INFO") + self.create_itsm_integration_setting(itsm_params).check_return_status() + else: + itsm_in_ccc = self.get_itsm_settings_by_id(itsm_id) + if not itsm_in_ccc: + self.status = "failed" + self.msg = "Unable to update as there is no ITSM Integration setting with name '{0}' present in Cisco Catalyst Center".format(itsm_name) + self.log(self.msg, "ERROR") + return self + + # Check destination needs update and if yes then update Email Destination + itsm_need_update = self.itsm_needs_update(itsm_params, itsm_in_ccc) + + if not itsm_need_update: + self.msg = "ITSM Intergartion setting with name '{0}' needs no update in Cisco Catalyst Center".format(itsm_name) + self.log(self.msg, "INFO") + self.result['changed'] = False + self.result['response'] = self.msg + else: + # Update the ITSM integration settings with given details in the playbook + self.update_itsm_integration_setting(itsm_params, itsm_in_ccc).check_return_status() + + return self + + def get_diff_deleted(self, config): + """ + Handles the deletion of ITSM integration settings in Cisco Catalyst Center based on the configuration provided. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + config (dict): A dictionary containing the 'itsm_setting' key with details about the ITSM integration to be deleted. + Returns: + self (object): The instance of the class with updated status, results, and message based on the deletion operation. + Description: + This function is responsible for deleting an ITSM setting from Cisco Catalyst Center if it exists. + It checks whether the specified ITSM setting exists in the current Catalyst Center configuration. If it exists, + the function proceeds to delete it. If it does not exist or is already deleted, the function updates the instance + status and results to reflect that no change was needed. + """ + + if config.get('webhook_destination'): + self.status = "failed" + self.msg = "Deleting the Webhook destination is not supported in Cisco Catalyst Center because of API limitations" + self.log(self.msg, "ERROR") + self.result['changed'] = False + + if config.get('email_destination'): + self.status = "failed" + self.msg = "Deleting the Email destination is not supported in Cisco Catalyst Center because of API limitations" + self.log(self.msg, "ERROR") + self.result['changed'] = False + + if config.get('syslog_destination'): + self.status = "failed" + self.msg = "Deleting the Syslog destination is not supported in Cisco Catalyst Center because of API limitations" + self.log(self.msg, "ERROR") + self.result['changed'] = False + + if config.get('snmp_destination'): + self.status = "failed" + self.msg = "Deleting the SNMP destination is not supported in Cisco Catalyst Center because of API limitations" + self.log(self.msg, "ERROR") + self.result['changed'] = False + + if config.get('itsm_setting'): + itsm_details = self.want.get('itsm_details') + itsm_name = itsm_details.get('instance_name') + itsm_detail_in_ccc = self.have.get('itsm_setting') + if not itsm_detail_in_ccc: + self.status = "success" + self.result['changed'] = False + self.msg = """There is no ITSM Intergartion setting present in Cisco Catalyst Center so cannot delete + the ITSM Integartion setting with name '{0}'""".format(itsm_name) + self.log(self.name, "INFO") + return self + + # Check whether the given itsm integration present in Catalyst Center or not + itsm_exist = False + for itsm in itsm_detail_in_ccc: + if itsm['name'] == itsm_name: + itsm_id = itsm.get('id') + itsm_exist = True + break + if itsm_exist: + self.delete_itsm_integration_setting(itsm_name, itsm_id).check_return_status() + else: + self.msg = "Unable to delete ITSM Integartion setting with name '{0}' as it is not present in Cisco Catalyst Center".format(itsm_name) + self.log(self.msg, "INFO") + self.result['changed'] = False + self.result['response'] = self.msg + + return self + + def verify_diff_merged(self, config): + """ + Verify the addition/update status of configurations in Cisco Catalyst Center. + Parameters: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + config (dict): The configuration details to be verified. + Returns: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Description: + This method verifies whether the specified configurations have been successfully added/updated + in Cisco Catalyst Center as desired. + """ + + self.get_have(config) + self.log("Current State (have): {0}".format(str(self.have)), "INFO") + self.log("Desired State (want): {0}".format(str(self.want)), "INFO") + + if config.get('syslog_destination'): + syslog_details = self.want.get('syslog_details') + syslog_name = syslog_details.get('name') + syslog_details_in_ccc = self.get_syslog_destination_with_name(syslog_name) + + if syslog_details_in_ccc: + self.status = "success" + msg = """Requested Syslog Destination '{0}' have been successfully added/updated to the Cisco Catalyst Center and their + addition/updation has been verified.""".format(syslog_name) + self.log(msg, "INFO") + else: + self.log("""Playbook's input does not match with Cisco Catalyst Center, indicating that the Syslog destination with name + '{0}' addition/updation task may not have executed successfully.""".format(syslog_name), "INFO") + + if config.get('snmp_destination'): + snmp_details = self.want.get('snmp_details') + snmp_dest_name = snmp_details.get('name') + is_snmp_dest_exist = False + + for snmp_dict in self.have.get('snmp_destinations'): + if snmp_dict['name'] == snmp_dest_name: + is_snmp_dest_exist = True + break + + if is_snmp_dest_exist: + self.status = "success" + msg = """Requested SNMP Destination '{0}' have been successfully added/updated to the Cisco Catalyst Center and their + addition/updation has been verified.""".format(snmp_dest_name) + self.log(msg, "INFO") + else: + self.log("""Playbook's input does not match with Cisco Catalyst Center, indicating that the SNMP destination with name + '{0}' addition/updation task may not have executed successfully.""".format(snmp_dest_name), "INFO") + + if config.get('webhook_destination'): + webhook_details = self.want.get('webhook_details') + webhook_name = webhook_details.get('name') + + is_webhook_dest_exist = False + for webhook_dict in self.have.get('webhook_destinations'): + if webhook_dict['name'] == webhook_name: + is_webhook_dest_exist = True + break + if is_webhook_dest_exist: + self.status = "success" + msg = """Requested Rest Webhook Destination '{0}' have been successfully added/updated to the Cisco Catalyst Center and their + addition/updation has been verified.""".format(webhook_name) + self.log(msg, "INFO") + else: + self.log("""Playbook's input does not match with Cisco Catalyst Center, indicating that Rest Webhook destination with name + '{0}' addition/updation task may not have executed successfully.""".format(webhook_name), "INFO") + + if config.get('email_destination'): + + if self.have.get('email_destination'): + self.status = "success" + msg = """Requested Email Destination have been successfully configured to the Cisco Catalyst Center and their + configuration has been verified.""" + self.log(msg, "INFO") + else: + self.log("""Playbook's input does not match with Cisco Catalyst Center, indicating that Email destination configuration + task may not have executed successfully.""", "INFO") + + if config.get('itsm_setting'): + itsm_details = self.want.get('itsm_details') + itsm_name = itsm_details.get('instance_name') + is_itsm_exist = False + itsm_detail_in_ccc = self.have.get('itsm_setting') + + if not itsm_detail_in_ccc: + self.log("There is no ITSM Intergartion setting present in Cisco Catalyst Center", "INFO") + else: + # Check whether the given itsm integration present in Cisco Catalyst Center or not. + for itsm in itsm_detail_in_ccc: + if itsm['name'] == itsm_name: + is_itsm_exist = True + break + + if is_itsm_exist: + self.status = "success" + msg = """Requested ITSM Integration setting '{0}' have been successfully added/updated to the Cisco Catalyst Center + and their addition/updation has been verified.""".format(itsm_name) + self.log(msg, "INFO") + else: + self.log("""Playbook's input does not match with Cisco Catalyst Center, indicating that ITSM Integration setting with + name '{0}' addition/updation task may not have executed successfully.""".format(itsm_name), "INFO") + + return self + + def verify_diff_deleted(self, config): + """ + Verify the deletion status of ITSM Integration Setting in Cisco Catalyst Center. + Parameters: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + config (dict): The configuration details to be verified. + Returns: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Description: + This method checks the deletion status of a configuration in Cisco Catalyst Center. + It validates whether the specified ITSM Integration setting deleted from Cisco Catalyst Center. + """ + + self.get_have(config) + self.log("Current State (have): {0}".format(str(self.have)), "INFO") + self.log("Desired State (want): {0}".format(str(self.want)), "INFO") + + if config.get('itsm_setting'): + itsm_details = self.want.get('itsm_details') + itsm_name = itsm_details.get('instance_name') + itsm_detail_in_ccc = self.have.get('itsm_setting') + itsm_deleted = True + + # Check whether the given itsm integration present in Catalyst Center or not + if not itsm_detail_in_ccc: + itsm_deleted = True + else: + for itsm in itsm_detail_in_ccc: + if itsm['name'] == itsm_name: + itsm_deleted = False + break + + if itsm_deleted: + self.status = "success" + msg = """Requested ITSM Integration setting '{0}' have been successfully deleted from the Cisco Catalyst Center + and their deletion has been verified.""".format(itsm_name) + self.log(msg, "INFO") + else: + self.log("""Playbook's input does not match with Cisco Catalyst Center, indicating that ITSM Integration setting with + name '{0}' deletion task may not have executed successfully.""".format(itsm_name), "INFO") + + return self + + +def main(): + """ main entry point for module execution + """ + + element_spec = {'dnac_host': {'required': True, 'type': 'str'}, + 'dnac_port': {'type': 'str', 'default': '443'}, + 'dnac_username': {'type': 'str', 'default': 'admin', 'aliases': ['user']}, + 'dnac_password': {'type': 'str', 'no_log': True}, + 'dnac_verify': {'type': 'bool', 'default': 'True'}, + 'dnac_version': {'type': 'str', 'default': '2.2.3.3'}, + 'dnac_debug': {'type': 'bool', 'default': False}, + 'dnac_log_level': {'type': 'str', 'default': 'WARNING'}, + "dnac_log_file_path": {"type": 'str', "default": 'dnac.log'}, + "dnac_log_append": {"type": 'bool', "default": True}, + 'dnac_log': {'type': 'bool', 'default': False}, + 'validate_response_schema': {'type': 'bool', 'default': True}, + 'config_verify': {'type': 'bool', "default": False}, + 'dnac_api_task_timeout': {'type': 'int', "default": 1200}, + 'dnac_task_poll_interval': {'type': 'int', "default": 2}, + 'config': {'required': True, 'type': 'list', 'elements': 'dict'}, + 'state': {'default': 'merged', 'choices': ['merged', 'deleted']} + } + + module = AnsibleModule(argument_spec=element_spec, + supports_check_mode=False) + + ccc_events = Events(module) + state = ccc_events.params.get("state") + + if state not in ccc_events.supported_states: + ccc_events.status = "invalid" + ccc_events.msg = "State {0} is invalid".format(state) + ccc_events.check_return_status() + + ccc_events.validate_input().check_return_status() + config_verify = ccc_events.params.get("config_verify") + + for config in ccc_events.validated_config: + ccc_events.reset_values() + ccc_events.get_want(config).check_return_status() + ccc_events.get_have(config).check_return_status() + ccc_events.get_diff_state_apply[state](config).check_return_status() + if config_verify: + ccc_events.verify_diff_state_apply[state](config).check_return_status() + + module.exit_json(**ccc_events.result) + + +if __name__ == '__main__': + main() diff --git a/plugins/modules/execute_suggested_actions_commands.py b/plugins/modules/execute_suggested_actions_commands.py index 43fce32030..24a0a0e133 100644 --- a/plugins/modules/execute_suggested_actions_commands.py +++ b/plugins/modules/execute_suggested_actions_commands.py @@ -14,7 +14,7 @@ This API triggers the execution of the suggested actions for an issue, given the Issue Id. It will return an execution Id. At the completion of the execution, the output of the commands associated with the suggested actions will be provided. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -27,8 +27,8 @@ description: Contains the actual value for the entity type that has been defined. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Issues ExecuteSuggestedActionsCommands description: Complete reference of the ExecuteSuggestedActionsCommands API. @@ -56,7 +56,6 @@ entity_value: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/file_import.py b/plugins/modules/file_import.py index f9909edddd..ec3ce7f075 100644 --- a/plugins/modules/file_import.py +++ b/plugins/modules/file_import.py @@ -23,8 +23,8 @@ description: NameSpace path parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for File UploadFile description: Complete reference of the UploadFile API. @@ -52,7 +52,6 @@ nameSpace: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/file_info.py b/plugins/modules/file_info.py index b9bdba4b9e..aec9a594f2 100644 --- a/plugins/modules/file_info.py +++ b/plugins/modules/file_info.py @@ -36,8 +36,8 @@ - The filename used to save the download file. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for File DownloadAFileByFileId description: Complete reference of the DownloadAFileByFileId API. @@ -63,13 +63,9 @@ dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" fileId: string - dirPath: /tmp/downloads/Test-242.bin - saveFile: true - filename: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/file_namespace_files_info.py b/plugins/modules/file_namespace_files_info.py index 0e16dbc1af..cae4582a6a 100644 --- a/plugins/modules/file_namespace_files_info.py +++ b/plugins/modules/file_namespace_files_info.py @@ -24,8 +24,8 @@ - NameSpace path parameter. A listing of fileId's. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for File GetListOfFiles description: Complete reference of the GetListOfFiles API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/file_namespaces_info.py b/plugins/modules/file_namespaces_info.py index 8492681110..c781369634 100644 --- a/plugins/modules/file_namespaces_info.py +++ b/plugins/modules/file_namespaces_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for File GetListOfAvailableNamespaces description: Complete reference of the GetListOfAvailableNamespaces API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/flexible_report_content_info.py b/plugins/modules/flexible_report_content_info.py new file mode 100644 index 0000000000..502596e2de --- /dev/null +++ b/plugins/modules/flexible_report_content_info.py @@ -0,0 +1,72 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: flexible_report_content_info +short_description: Information module for Flexible Report Content +description: +- Get Flexible Report Content by id. +- > + This is used to download the flexible report. The API returns report content. Save the response to a file by + converting the response data as a blob and setting the file format available from content-disposition response + header. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + reportId: + description: + - ReportId path parameter. Id of the report. + type: str + executionId: + description: + - ExecutionId path parameter. Id of execution. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Reports DownloadFlexibleReport + description: Complete reference of the DownloadFlexibleReport API. + link: https://developer.cisco.com/docs/dna-center/#!download-flexible-report +notes: + - SDK Method used are + reports.Reports.download_flexible_report, + + - Paths used are + get /dna/data/api/v1/flexible-report/report/content/{reportId}/{executionId}, + +""" + +EXAMPLES = r""" +- name: Get Flexible Report Content by id + cisco.dnac.flexible_report_content_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + reportId: string + executionId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: str + sample: > + "'string'" +""" diff --git a/plugins/modules/flexible_report_execute.py b/plugins/modules/flexible_report_execute.py new file mode 100644 index 0000000000..f10db659f8 --- /dev/null +++ b/plugins/modules/flexible_report_execute.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: flexible_report_execute +short_description: Resource module for Flexible Report Execute +description: +- Manage operation create of the resource Flexible Report Execute. +- This API is used for executing the report. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + reportId: + description: ReportId path parameter. Id of the Report. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Reports ExecutingTheFlexibleReport + description: Complete reference of the ExecutingTheFlexibleReport API. + link: https://developer.cisco.com/docs/dna-center/#!executing-the-flexible-report +notes: + - SDK Method used are + reports.Reports.executing_the_flexible_report, + + - Paths used are + post /dna/data/api/v1/flexible-report/report/{reportId}/execute, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.flexible_report_execute: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + reportId: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "executionId": "string", + "startTime": 0, + "endTime": 0, + "processStatus": {}, + "requestStatus": "string", + "errors": [ + "string" + ], + "warnings": [ + {} + ] + } +""" diff --git a/plugins/modules/flexible_report_executions_info.py b/plugins/modules/flexible_report_executions_info.py new file mode 100644 index 0000000000..14eaf06569 --- /dev/null +++ b/plugins/modules/flexible_report_executions_info.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: flexible_report_executions_info +short_description: Information module for Flexible Report Executions +description: +- Get all Flexible Report Executions. +- Get Execution Id by Report Id. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + reportId: + description: + - ReportId path parameter. Id of the report. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Reports GetExecutionIdByReportId + description: Complete reference of the GetExecutionIdByReportId API. + link: https://developer.cisco.com/docs/dna-center/#!get-execution-id-by-report-id +notes: + - SDK Method used are + reports.Reports.get_execution_id_by_report_id, + + - Paths used are + get /dna/data/api/v1/flexible-report/report/{reportId}/executions, + +""" + +EXAMPLES = r""" +- name: Get all Flexible Report Executions + cisco.dnac.flexible_report_executions_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + reportId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "reportId": "string", + "reportName": "string", + "executions": [ + { + "executionId": "string", + "startTime": 0, + "endTime": 0, + "processStatus": "string", + "requestStatus": "string", + "errors": [ + "string" + ], + "warnings": [ + {} + ] + } + ], + "executionCount": 0, + "reportWasExecuted": true + } +""" diff --git a/plugins/modules/flexible_report_schedule.py b/plugins/modules/flexible_report_schedule.py new file mode 100644 index 0000000000..9d6e4ed8a5 --- /dev/null +++ b/plugins/modules/flexible_report_schedule.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: flexible_report_schedule +short_description: Resource module for Flexible Report Schedule +description: +- Manage operation update of the resource Flexible Report Schedule. +- Update schedule of flexible report. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + reportId: + description: ReportId path parameter. Id of the report. + type: str + schedule: + description: Schedule information. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Reports UpdateScheduleOfFlexibleReport + description: Complete reference of the UpdateScheduleOfFlexibleReport API. + link: https://developer.cisco.com/docs/dna-center/#!update-schedule-of-flexible-report +notes: + - SDK Method used are + reports.Reports.update_schedule_of_flexible_report, + + - Paths used are + put /dna/data/api/v1/flexible-report/schedule/{reportId}, + +""" + +EXAMPLES = r""" +- name: Update by id + cisco.dnac.flexible_report_schedule: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + reportId: string + schedule: {} + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "schedule": {} + } +""" diff --git a/plugins/modules/flexible_report_schedule_info.py b/plugins/modules/flexible_report_schedule_info.py new file mode 100644 index 0000000000..47f589a07a --- /dev/null +++ b/plugins/modules/flexible_report_schedule_info.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: flexible_report_schedule_info +short_description: Information module for Flexible Report Schedule +description: +- Get Flexible Report Schedule by id. +- Get flexible report schedule by report id. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + reportId: + description: + - ReportId path parameter. Id of the report. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Reports GetFlexibleReportScheduleByReportId + description: Complete reference of the GetFlexibleReportScheduleByReportId API. + link: https://developer.cisco.com/docs/dna-center/#!get-flexible-report-schedule-by-report-id +notes: + - SDK Method used are + reports.Reports.get_flexible_report_schedule_by_report_id, + + - Paths used are + get /dna/data/api/v1/flexible-report/schedule/{reportId}, + +""" + +EXAMPLES = r""" +- name: Get Flexible Report Schedule by id + cisco.dnac.flexible_report_schedule_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + reportId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: + - {} +""" diff --git a/plugins/modules/flexible_report_schedules_info.py b/plugins/modules/flexible_report_schedules_info.py new file mode 100644 index 0000000000..46a7fe2fc7 --- /dev/null +++ b/plugins/modules/flexible_report_schedules_info.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: flexible_report_schedules_info +short_description: Information module for Flexible Report Schedules +description: +- Get all Flexible Report Schedules. +- Get all flexible report schedules. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Reports GetAllFlexibleReportSchedules + description: Complete reference of the GetAllFlexibleReportSchedules API. + link: https://developer.cisco.com/docs/dna-center/#!get-all-flexible-report-schedules +notes: + - SDK Method used are + reports.Reports.get_all_flexible_report_schedules, + + - Paths used are + get /dna/data/api/v1/flexible-report/schedules, + +""" + +EXAMPLES = r""" +- name: Get all Flexible Report Schedules + cisco.dnac.flexible_report_schedules_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "reportId": "string", + "schedule": { + "type": "string", + "dateTime": 0 + }, + "reportName": "string" + } + ] +""" diff --git a/plugins/modules/global_credential_delete.py b/plugins/modules/global_credential_delete.py index 3dd9ad1d1d..34581241bb 100644 --- a/plugins/modules/global_credential_delete.py +++ b/plugins/modules/global_credential_delete.py @@ -20,8 +20,8 @@ description: GlobalCredentialId path parameter. ID of global-credential. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery DeleteGlobalCredentialsById description: Complete reference of the DeleteGlobalCredentialsById API. @@ -48,7 +48,6 @@ globalCredentialId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/global_credential_info.py b/plugins/modules/global_credential_info.py index 2d46ca10ff..2fd59e6407 100644 --- a/plugins/modules/global_credential_info.py +++ b/plugins/modules/global_credential_info.py @@ -29,19 +29,19 @@ type: str sortBy: description: - - SortBy query parameter. + - SortBy query parameter. Field to sort the results by. Sorts by 'instanceId' if no value is provided. type: str order: description: - - Order query parameter. + - Order query parameter. Order of sorting. 'asc' or 'des'. type: str id: description: - Id path parameter. Global Credential ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetCredentialSubTypeByCredentialId description: Complete reference of the GetCredentialSubTypeByCredentialId API. @@ -90,7 +90,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/global_credential_update.py b/plugins/modules/global_credential_update.py index 8f2ea144af..720273fea4 100644 --- a/plugins/modules/global_credential_update.py +++ b/plugins/modules/global_credential_update.py @@ -20,12 +20,12 @@ description: GlobalCredentialId path parameter. Global credential Uuid. type: str siteUuids: - description: Global Credential Update's siteUuids. + description: List of siteUuids where credential is to be updated. elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery UpdateGlobalCredentials description: Complete reference of the UpdateGlobalCredentials API. @@ -54,7 +54,6 @@ - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/global_credential_v2.py b/plugins/modules/global_credential_v2.py index 2d27cca33d..5677ae7842 100644 --- a/plugins/modules/global_credential_v2.py +++ b/plugins/modules/global_credential_v2.py @@ -17,7 +17,7 @@ - > API to update device credentials. Multiple credentials can be passed at once, but only a single credential of a given type can be passed at once. Please refer sample Request Body for more information. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -26,57 +26,57 @@ description: Global Credential V2's cliCredential. suboptions: description: - description: Description. + description: Description for CLI credential. type: str enablePassword: - description: Enable Password. + description: CLI Enable Password. type: str id: - description: Id. + description: Id of the CLI Credential in UUID format. type: str password: - description: Password. + description: CLI Password. type: str username: - description: Username. + description: CLI Username. type: str type: dict httpsRead: description: Global Credential V2's httpsRead. suboptions: - id: - description: Id. + description: + description: Description for HTTP(S) Read Credentials. type: str - name: - description: Name. + id: + description: Id of the HTTP(S) Read Credential in UUID format. type: str password: - description: Password. + description: HTTP(S) Read Password. type: str port: - description: Port. + description: HTTP(S) Port. type: int username: - description: Username. + description: HTTP(S) Read Username. type: str type: dict httpsWrite: description: Global Credential V2's httpsWrite. suboptions: - id: - description: Id. + description: + description: Description for HTTP(S) Write Credentials. type: str - name: - description: Name. + id: + description: Id of the HTTP(S) Read Credential in UUID format. type: str password: - description: Password. + description: HTTP(S) Write Password. type: str port: - description: Port. + description: HTTP(S) Port. type: int username: - description: Username. + description: HTTP(S) Write Username. type: str type: dict id: @@ -86,59 +86,59 @@ description: Global Credential V2's snmpV2cRead. suboptions: description: - description: Description. + description: Description for Snmp RO community. type: str id: - description: Id. + description: Id of the SNMP Read Credential in UUID format. type: str readCommunity: - description: Read Community. + description: Snmp RO community. type: str type: dict snmpV2cWrite: description: Global Credential V2's snmpV2cWrite. suboptions: description: - description: Description. + description: Description for Snmp RW community. type: str id: - description: Id. + description: Id of the SNMP Write Credential in UUID format. type: str writeCommunity: - description: Write Community. + description: Snmp RW community. type: str type: dict snmpV3: description: Global Credential V2's snmpV3. suboptions: authPassword: - description: Auth Password. + description: Auth Password for SNMP V3. type: str authType: - description: Auth Type. + description: SNMP auth protocol. SHA' or 'MD5'. type: str description: - description: Description. + description: Description for Snmp V3 Credential. type: str id: - description: Id. + description: Id of the SNMP V3 Credential in UUID format. type: str privacyPassword: - description: Privacy Password. + description: Privacy Password for SNMP privacy. type: str privacyType: - description: Privacy Type. + description: SNMP privacy protocol. 'AES128','AES192','AES256'. type: str snmpMode: - description: Snmp Mode. + description: Mode of SNMP. 'AUTHPRIV' or 'AUTHNOPRIV' or 'NOAUTHNOPRIV'. type: str username: - description: Username. + description: SNMP V3 Username. type: str type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateGlobalCredentialsV2 description: Complete reference of the CreateGlobalCredentialsV2 API. @@ -180,14 +180,14 @@ password: string username: string httpsRead: + description: string id: string - name: string password: string port: 0 username: string httpsWrite: + description: string id: string - name: string password: string port: 0 username: string @@ -225,12 +225,12 @@ password: string username: string httpsRead: - - name: string + - description: string password: string port: 0 username: string httpsWrite: - - name: string + - description: string password: string port: 0 username: string @@ -262,7 +262,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/global_credential_v2_info.py b/plugins/modules/global_credential_v2_info.py index 6b0bffd4db..37db95a46f 100644 --- a/plugins/modules/global_credential_v2_info.py +++ b/plugins/modules/global_credential_v2_info.py @@ -13,7 +13,7 @@ - > API to get device credentials' details. It fetches all global credentials of all types at once, without the need to pass any input parameters. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -22,8 +22,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetAllGlobalCredentialsV2 description: Complete reference of the GetAllGlobalCredentialsV2 API. @@ -51,7 +51,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/global_pool.py b/plugins/modules/global_pool.py index f52c316d6a..9f53f8cafa 100644 --- a/plugins/modules/global_pool.py +++ b/plugins/modules/global_pool.py @@ -48,8 +48,8 @@ type: list type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings CreateGlobalPool description: Complete reference of the CreateGlobalPool API. @@ -129,7 +129,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/global_pool_info.py b/plugins/modules/global_pool_info.py index 4d95ba9eac..7d8a908f11 100644 --- a/plugins/modules/global_pool_info.py +++ b/plugins/modules/global_pool_info.py @@ -10,7 +10,7 @@ short_description: Information module for Global Pool description: - Get all Global Pool. -- API to get global pool. +- API to get the global pool. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -21,15 +21,15 @@ type: dict offset: description: - - Offset query parameter. Offset/starting row. - type: int + - Offset query parameter. Offset/starting row. Indexed from 1. Default value of 1. + type: float limit: description: - - Limit query parameter. No of Global Pools to be retrieved. - type: int + - Limit query parameter. Number of Global Pools to be retrieved. Default is 25 if not specified. + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings GetGlobalPool description: Complete reference of the GetGlobalPool API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -76,20 +75,26 @@ "gateways": [ "string" ], - "createTime": "string", - "lastUpdateTime": "string", - "totalIpAddressCount": "string", - "usedIpAddressCount": "string", + "createTime": 0, + "lastUpdateTime": 0, + "totalIpAddressCount": 0, + "usedIpAddressCount": 0, "parentUuid": "string", "owner": "string", - "shared": "string", - "overlapping": "string", - "configureExternalDhcp": "string", + "shared": true, + "overlapping": true, + "configureExternalDhcp": true, "usedPercentage": "string", "clientOptions": {}, + "ipPoolType": "string", + "unavailableIpAddressCount": 0, + "availableIpAddressCount": 0, + "totalAssignableIpAddressCount": 0, "dnsServerIps": [ "string" ], + "hasSubpools": true, + "defaultAssignedIpAddressCount": 0, "context": [ { "owner": "string", @@ -97,7 +102,7 @@ "contextValue": "string" } ], - "ipv6": "string", + "ipv6": true, "id": "string", "ipPoolCidr": "string" } diff --git a/plugins/modules/golden_image_create.py b/plugins/modules/golden_image_create.py index 95385c59d8..91d7d7b222 100644 --- a/plugins/modules/golden_image_create.py +++ b/plugins/modules/golden_image_create.py @@ -30,8 +30,8 @@ description: SiteId in uuid format. For Global Site "-1" to be used. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) TagAsGoldenImage description: Complete reference of the TagAsGoldenImage API. @@ -61,7 +61,6 @@ siteId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/golden_tag_image_delete.py b/plugins/modules/golden_tag_image_delete.py index 392165663b..e3010ea7c3 100644 --- a/plugins/modules/golden_tag_image_delete.py +++ b/plugins/modules/golden_tag_image_delete.py @@ -32,8 +32,8 @@ Global site. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) RemoveGoldenTagForImage description: Complete reference of the RemoveGoldenTagForImage API. @@ -63,7 +63,6 @@ siteId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/golden_tag_image_details_info.py b/plugins/modules/golden_tag_image_details_info.py index c92ed95039..a6aebf1195 100644 --- a/plugins/modules/golden_tag_image_details_info.py +++ b/plugins/modules/golden_tag_image_details_info.py @@ -38,8 +38,8 @@ - ImageId path parameter. Image Id in uuid format. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) GetGoldenTagStatusOfAnImage description: Complete reference of the GetGoldenTagStatusOfAnImage API. @@ -71,7 +71,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/http_read_credential.py b/plugins/modules/http_read_credential.py index 89a5f7f47f..a99555fc00 100644 --- a/plugins/modules/http_read_credential.py +++ b/plugins/modules/http_read_credential.py @@ -18,38 +18,39 @@ author: Rafael Campos (@racampos) options: comments: - description: Http Read Credential's comments. + description: Comments to identify the HTTP(S) Read credential. type: str credentialType: - description: Http Read Credential's credentialType. + description: Credential type to identify the application that uses the HTTP(S) Read + credential. type: str description: - description: Http Read Credential's description. + description: Description for HTTP(S) Read Credential. type: str id: - description: Http Read Credential's id. + description: Id of the HTTP(S) Read Credential in UUID format. type: str instanceTenantId: - description: Http Read Credential's instanceTenantId. + description: Deprecated. type: str instanceUuid: - description: Http Read Credential's instanceUuid. + description: Deprecated. type: str password: - description: Http Read Credential's password. + description: HTTP(S) Read Password. type: str port: - description: Http Read Credential's port. + description: HTTP(S) Port. Valid port should be in the range of 1 to 65535. type: int secure: - description: Secure flag. + description: Flag for HTTPS Read. type: bool username: - description: Http Read Credential's username. + description: HTTP(S) Read Username. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateHTTPReadCredentials description: Complete reference of the CreateHTTPReadCredentials API. @@ -112,7 +113,6 @@ username: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/http_write_credential.py b/plugins/modules/http_write_credential.py index 611f40716d..d22a4d4207 100644 --- a/plugins/modules/http_write_credential.py +++ b/plugins/modules/http_write_credential.py @@ -18,38 +18,39 @@ author: Rafael Campos (@racampos) options: comments: - description: Http Write Credential's comments. + description: Comments to identify the HTTP(S) Write credential. type: str credentialType: - description: Http Write Credential's credentialType. + description: Credential type to identify the application that uses the HTTP(S) Write + credential. type: str description: - description: Http Write Credential's description. + description: Description for HTTP(S) Write Credential. type: str id: - description: Http Write Credential's id. + description: Id of the HTTP(S) Write Credential in UUID format. type: str instanceTenantId: - description: Http Write Credential's instanceTenantId. + description: Deprecated. type: str instanceUuid: - description: Http Write Credential's instanceUuid. + description: Deprecated. type: str password: - description: Http Write Credential's password. + description: HTTP(S) Write Password. type: str port: - description: Http Write Credential's port. + description: HTTP(S) Port. Valid port should be in the range of 1 to 65535. type: int secure: - description: Secure flag. + description: Flag for HTTPS Write. type: bool username: - description: Http Write Credential's username. + description: HTTP(S) Write Username. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateHTTPWriteCredentials description: Complete reference of the CreateHTTPWriteCredentials API. @@ -112,7 +113,6 @@ username: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/integration_settings_instances_itsm.py b/plugins/modules/integration_settings_instances_itsm.py index 86fa8bd762..991dccb6b6 100644 --- a/plugins/modules/integration_settings_instances_itsm.py +++ b/plugins/modules/integration_settings_instances_itsm.py @@ -13,7 +13,7 @@ - Creates ITSM Integration setting. - Deletes the ITSM Integration setting. - Updates the ITSM Integration setting. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -39,7 +39,7 @@ description: Description of the setting instance. type: str dypName: - description: It should be ServiceNowConnection. + description: It can be ServiceNowConnection. type: str instanceId: description: InstanceId path parameter. Instance Id of the Integration setting instance. @@ -48,8 +48,8 @@ description: Name of the setting instance. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for ITSM Integration CreateITSMIntegrationSetting description: Complete reference of the CreateITSMIntegrationSetting API. @@ -126,7 +126,6 @@ instanceId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/integration_settings_instances_itsm_info.py b/plugins/modules/integration_settings_instances_itsm_info.py index 0519f5e5a1..f0c3958b90 100644 --- a/plugins/modules/integration_settings_instances_itsm_info.py +++ b/plugins/modules/integration_settings_instances_itsm_info.py @@ -11,7 +11,7 @@ description: - Get Integration Settings Instances Itsm by id. - Fetches ITSM Integration setting by ID. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -24,8 +24,8 @@ - InstanceId path parameter. Instance Id of the Integration setting instance. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for ITSM Integration GetITSMIntegrationSettingById description: Complete reference of the GetITSMIntegrationSettingById API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/integration_settings_itsm_instances_info.py b/plugins/modules/integration_settings_itsm_instances_info.py new file mode 100644 index 0000000000..dd81cd6b56 --- /dev/null +++ b/plugins/modules/integration_settings_itsm_instances_info.py @@ -0,0 +1,78 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: integration_settings_itsm_instances_info +short_description: Information module for Integration Settings Itsm Instances +description: +- Get all Integration Settings Itsm Instances. +- Fetches all ITSM Integration settings. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for ITSM Integration GetAllITSMIntegrationSettings + description: Complete reference of the GetAllITSMIntegrationSettings API. + link: https://developer.cisco.com/docs/dna-center/#!get-all-itsm-integration-settings +notes: + - SDK Method used are + itsm_integration.ItsmIntegration.get_all_itsm_integration_settings, + + - Paths used are + get /dna/intent/api/v1/integration-settings/itsm/instances, + +""" + +EXAMPLES = r""" +- name: Get all Integration Settings Itsm Instances + cisco.dnac.integration_settings_itsm_instances_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "id": "string", + "dypId": "string", + "dypName": "string", + "name": "string", + "uniqueKey": "string", + "dypMajorVersion": 0, + "description": "string", + "createdDate": 0, + "createdBy": "string", + "updatedBy": "string", + "softwareVersionLog": [ + {} + ], + "schemaVersion": 0, + "tenantId": "string" + } + ] +""" diff --git a/plugins/modules/integration_settings_status_info.py b/plugins/modules/integration_settings_status_info.py new file mode 100644 index 0000000000..141e9f3091 --- /dev/null +++ b/plugins/modules/integration_settings_status_info.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: integration_settings_status_info +short_description: Information module for Integration Settings Status +description: +- Get all Integration Settings Status. +- Fetches ITSM Integration status. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for ITSM Integration GetITSMIntegrationStatus + description: Complete reference of the GetITSMIntegrationStatus API. + link: https://developer.cisco.com/docs/dna-center/#!get-itsm-integration-status +notes: + - SDK Method used are + itsm_integration.ItsmIntegration.get_itsm_integration_status, + + - Paths used are + get /dna/intent/api/v1/integration-settings/status, + +""" + +EXAMPLES = r""" +- name: Get all Integration Settings Status + cisco.dnac.integration_settings_status_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "name": "string", + "status": "string", + "configurations": [ + { + "dypSchemaName": "string", + "dypInstanceId": "string" + } + ] + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/interface_info.py b/plugins/modules/interface_info.py index a6f0706ade..7c57b98123 100644 --- a/plugins/modules/interface_info.py +++ b/plugins/modules/interface_info.py @@ -24,8 +24,8 @@ - InterfaceUuid path parameter. Interface ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices LegitOperationsForInterface description: Complete reference of the LegitOperationsForInterface API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -63,62 +62,22 @@ sample: > { "response": { - "type": "string", - "properties": { - "interfaceUuid": { - "type": "string" - }, - "properties": { - "type": "string", - "items": [ - { - "type": "string", - "properties": { - "name": { - "type": "string" - }, - "applicable": { - "type": "string" - }, - "failureReason": { - "type": "string" - } - }, - "required": [ - "string" - ] - } - ] - }, - "operations": { - "type": "string", - "items": [ - { - "type": "string", - "properties": { - "name": { - "type": "string" - }, - "applicable": { - "type": "string" - }, - "failureReason": { - "type": "string" - } - }, - "required": [ - "string" - ] - } - ] + "interfaceUuid": "string", + "properties": [ + { + "name": "string", + "applicable": "string", + "failureReason": "string" + } + ], + "operations": [ + { + "name": "string", + "applicable": "string", + "failureReason": "string" } - }, - "required": [ - "string" ] }, - "version": { - "type": "string" - } + "version": "string" } """ diff --git a/plugins/modules/interface_network_device_detail_info.py b/plugins/modules/interface_network_device_detail_info.py index 81a3203d65..259b68ed31 100644 --- a/plugins/modules/interface_network_device_detail_info.py +++ b/plugins/modules/interface_network_device_detail_info.py @@ -28,8 +28,8 @@ - Name query parameter. Interface name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetInterfaceDetailsByDeviceIdAndInterfaceName description: Complete reference of the GetInterfaceDetailsByDeviceIdAndInterfaceName API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -68,9 +67,24 @@ sample: > { "response": { + "addresses": [ + { + "address": { + "ipAddress": { + "address": "string" + }, + "ipMask": { + "address": "string" + }, + "isInverseMask": true + }, + "type": "string" + } + ], "adminStatus": "string", "className": "string", "description": "string", + "name": "string", "deviceId": "string", "duplex": "string", "id": "string", @@ -81,11 +95,14 @@ "ipv4Address": "string", "ipv4Mask": "string", "isisSupport": "string", + "lastOutgoingPacketTime": 0, + "lastIncomingPacketTime": 0, "lastUpdated": "string", "macAddress": "string", "mappedPhysicalInterfaceId": "string", "mappedPhysicalInterfaceName": "string", "mediaType": "string", + "mtu": "string", "nativeVlanId": "string", "ospfSupport": "string", "pid": "string", @@ -97,7 +114,13 @@ "speed": "string", "status": "string", "vlanId": "string", - "voiceVlan": "string" + "voiceVlan": "string", + "poweroverethernet": "string", + "networkdevice_id": "string", + "managedComputeElement": "string", + "managedNetworkElement": "string", + "managedNetworkElementUrl": "string", + "managedComputeElementUrl": "string" }, "version": "string" } diff --git a/plugins/modules/interface_network_device_info.py b/plugins/modules/interface_network_device_info.py index 62bb64e03c..6437313265 100644 --- a/plugins/modules/interface_network_device_info.py +++ b/plugins/modules/interface_network_device_info.py @@ -24,8 +24,8 @@ - DeviceId path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetInterfaceInfoById description: Complete reference of the GetInterfaceInfoById API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -64,9 +63,24 @@ { "response": [ { + "addresses": [ + { + "address": { + "ipAddress": { + "address": "string" + }, + "ipMask": { + "address": "string" + }, + "isInverseMask": true + }, + "type": "string" + } + ], "adminStatus": "string", "className": "string", "description": "string", + "name": "string", "deviceId": "string", "duplex": "string", "id": "string", @@ -77,11 +91,14 @@ "ipv4Address": "string", "ipv4Mask": "string", "isisSupport": "string", + "lastOutgoingPacketTime": 0, + "lastIncomingPacketTime": 0, "lastUpdated": "string", "macAddress": "string", "mappedPhysicalInterfaceId": "string", "mappedPhysicalInterfaceName": "string", "mediaType": "string", + "mtu": "string", "nativeVlanId": "string", "ospfSupport": "string", "pid": "string", diff --git a/plugins/modules/interface_network_device_range_info.py b/plugins/modules/interface_network_device_range_info.py index 2f2e3a6ea6..ce832dcbe9 100644 --- a/plugins/modules/interface_network_device_range_info.py +++ b/plugins/modules/interface_network_device_range_info.py @@ -32,8 +32,8 @@ - RecordsToReturn path parameter. Number of records to return. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceInterfacesBySpecifiedRange description: Complete reference of the GetDeviceInterfacesBySpecifiedRange API. @@ -64,7 +64,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -74,9 +73,24 @@ { "response": [ { + "addresses": [ + { + "address": { + "ipAddress": { + "address": "string" + }, + "ipMask": { + "address": "string" + }, + "isInverseMask": true + }, + "type": "string" + } + ], "adminStatus": "string", "className": "string", "description": "string", + "name": "string", "deviceId": "string", "duplex": "string", "id": "string", @@ -87,11 +101,14 @@ "ipv4Address": "string", "ipv4Mask": "string", "isisSupport": "string", + "lastOutgoingPacketTime": 0, + "lastIncomingPacketTime": 0, "lastUpdated": "string", "macAddress": "string", "mappedPhysicalInterfaceId": "string", "mappedPhysicalInterfaceName": "string", "mediaType": "string", + "mtu": "string", "nativeVlanId": "string", "ospfSupport": "string", "pid": "string", diff --git a/plugins/modules/interface_operation_create.py b/plugins/modules/interface_operation_create.py index 1bc065c317..6272bcd8c6 100644 --- a/plugins/modules/interface_operation_create.py +++ b/plugins/modules/interface_operation_create.py @@ -27,14 +27,14 @@ description: InterfaceUuid path parameter. Interface Id. type: str operation: - description: Operation. + description: Operation needs to be specified as 'ClearMacAddress'. type: str payload: - description: Payload. + description: Payload is not applicable. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices ClearMacAddressTable description: Complete reference of the ClearMacAddressTable API. @@ -64,7 +64,6 @@ payload: {} """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/interface_update.py b/plugins/modules/interface_update.py index 261703d48c..5c6c198291 100644 --- a/plugins/modules/interface_update.py +++ b/plugins/modules/interface_update.py @@ -19,7 +19,7 @@ author: Rafael Campos (@racampos) options: adminStatus: - description: Admin Status. + description: Admin status as ('UP'/'DOWN'). type: str deploymentMode: description: DeploymentMode query parameter. Preview/Deploy 'Preview' means the @@ -27,20 +27,20 @@ to the device. type: str description: - description: Description. + description: Description for the Interface. type: str interfaceUuid: description: InterfaceUuid path parameter. Interface ID. type: str vlanId: - description: Vlan Id. + description: VLAN Id to be Updated. type: int voiceVlanId: - description: Voice Vlan Id. + description: Voice Vlan Id to be Updated. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices UpdateInterfaceDetails description: Complete reference of the UpdateInterfaceDetails API. @@ -72,7 +72,6 @@ voiceVlanId: 0 """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/inventory_intent.py b/plugins/modules/inventory_intent.py index af25724868..cada74a18b 100644 --- a/plugins/modules/inventory_intent.py +++ b/plugins/modules/inventory_intent.py @@ -57,7 +57,7 @@ default: "NETWORK_DEVICE" cli_transport: description: The essential prerequisite for adding Network devices is the specification of the transport - protocol (either SSH or Telnet) used by the device. + protocol (either ssh or telnet) used by the device. type: str compute_device: description: Indicates whether a device is a compute device. @@ -307,7 +307,7 @@ version_added: 6.12.0 requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco Catalyst Center documentation for Devices AddDevice2 @@ -775,6 +775,7 @@ def validate_input(self): 'clean_config': {'type': 'bool'}, 'add_user_defined_field': { 'type': 'list', + 'elements': 'dict', 'name': {'type': 'str'}, 'description': {'type': 'str'}, 'value': {'type': 'str'}, @@ -797,6 +798,7 @@ def validate_input(self): }, 'provision_wired_device': { 'type': 'list', + 'elements': 'dict', 'device_ip': {'type': 'str'}, 'site_name': {'type': 'str'}, 'resync_retry_count': {'default': 200, 'type': 'int'}, @@ -1586,6 +1588,21 @@ def provisioned_wired_device(self): 'siteNameHierarchy': site_name } + # Check the provisioning status of device + device_prov_status = self.get_provision_wired_device(device_ip) + if device_prov_status == 2: + self.status = "success" + already_provision_count += 1 + self.result['changed'] = False + self.msg = "Device '{0}' is already provisioned in the Cisco Catalyst Center".format(device_ip) + self.log(self.msg, "INFO") + continue + if device_prov_status == 3: + self.status = "failed" + error_msg = "Cannot do Provisioning for device {0}.".format(device_ip) + self.log(error_msg, "ERROR") + continue + # Check till device comes into managed state while resync_retry_count: response = self.get_device_response(device_ip) @@ -1629,7 +1646,7 @@ def provisioned_wired_device(self): if response.get("status") == "failed": description = response.get("description") error_msg = "Cannot do Provisioning for device {0} beacuse of {1}".format(device_ip, description) - self.log(error_msg) + self.log(error_msg, "ERROR") continue task_id = response.get("taskId") @@ -1650,9 +1667,6 @@ def provisioned_wired_device(self): # Not returning from here as there might be possiblity that for some devices it comes into exception # but for others it gets provision successfully or If some devices are already provsioned self.handle_provisioning_exception(device_ip, e, device_type) - if "already provisioned" in str(e): - self.log(str(e), "INFO") - already_provision_count += 1 # Check If all the devices are already provsioned, return from here only if already_provision_count == total_devices_to_provisioned: @@ -2465,18 +2479,24 @@ def get_provision_wired_device(self, device_ip): logs the response. """ - response = self.dnac._exec( - family="sda", - function='get_provisioned_wired_device', - op_modifies=True, - params={"device_management_ip_address": device_ip} - ) + try: + flag = 3 + response = self.dnac._exec( + family="sda", + function='get_provisioned_wired_device', + op_modifies=True, + params={"device_management_ip_address": device_ip} + ) - if response.get("status") == "failed": - self.log("Cannot do provisioning for wired device {0} because of {1}.".format(device_ip, response.get('description')), "ERROR") - return False + if response.get("status") == "success" and "Wired Provisioned device detail retrieved successfully." in response.get("description"): + flag = 2 + self.log("Wired device '{0}' already provisioned in the Cisco Catalyst Center.".format(device_ip), "INFO") - return True + except Exception as e: + if "not provisioned to any site" in str(e): + flag = 1 + + return flag def clear_mac_address(self, interface_id, deploy_mode, interface_name): """ @@ -2879,10 +2899,26 @@ def get_diff_merged(self, config): credential_update = self.config[0].get("credential_update", False) config['type'] = device_type + config['ip_address_list'] = devices_to_add if device_type == "FIREPOWER_MANAGEMENT_SYSTEM": config['http_port'] = self.config[0].get("http_port", "443") - config['ip_address_list'] = devices_to_add + if self.config[0].get('provision_wired_device'): + provision_wired_list = self.config[0]['provision_wired_device'] + device_not_available = [] + device_in_ccc = self.device_exists_in_dnac() + + for prov_dict in provision_wired_list: + device_ip = prov_dict['device_ip'] + if device_ip not in device_in_ccc: + device_not_available.append(device_ip) + if device_not_available: + self.status = "failed" + self.msg = """Unable to Provision Wired Device(s) because the device(s) listed: {0} are not present in the + Cisco Catalyst Center.""".format(str(device_not_available)) + self.result['response'] = self.msg + self.log(self.msg, "ERROR") + return self if self.config[0].get('update_mgmt_ipaddresslist'): device_ip = self.config[0].get('update_mgmt_ipaddresslist')[0].get('existMgmtIpAddress') @@ -3032,6 +3068,7 @@ def get_diff_merged(self, config): devices_to_update_role = self.get_device_ips_from_config_priority() device_role = self.config[0].get('role') role_update_count = 0 + role_updated_list = [] for device_ip in devices_to_update_role: device_id = self.get_device_ids([device_ip]) @@ -3076,10 +3113,8 @@ def get_diff_merged(self, config): if 'successfully' in progress or 'succesfully' in progress: self.status = "success" - self.result['changed'] = True - self.msg = "Device(s) '{0}' role updated successfully to '{1}'".format(str(devices_to_update_role), device_role) - self.result['response'] = self.msg - self.log(self.msg, "INFO") + self.log("Device '{0}' role updated successfully to '{1}'".format(device_ip, device_role), "INFO") + role_updated_list.append(device_ip) break elif execution_details.get("isError"): self.status = "failed" @@ -3100,10 +3135,17 @@ def get_diff_merged(self, config): self.status = "success" self.result['changed'] = False self.msg = """The device role '{0}' is already set in Cisco Catalyst Center, no device role update is needed for the - devices {1}.""".format(device_role, str(devices_to_update_role)) + device(s) {1}.""".format(device_role, str(devices_to_update_role)) self.log(self.msg, "INFO") self.result['response'] = self.msg + if role_updated_list: + self.status = "success" + self.result['changed'] = True + self.msg = "Device(s) '{0}' role updated successfully to '{1}'".format(str(role_updated_list), device_role) + self.result['response'] = self.msg + self.log(self.msg, "INFO") + if credential_update: device_to_update = self.get_device_ips_from_config_priority() # Update Device details and credentails @@ -3229,6 +3271,10 @@ def get_diff_merged(self, config): if not playbook_params['httpPort']: playbook_params['httpPort'] = device_data.get('http_port', None) + for key, value in playbook_params.items(): + if value == " ": + playbook_params[key] = None + try: if playbook_params['updateMgmtIPaddressList']: new_mgmt_ipaddress = playbook_params['updateMgmtIPaddressList'][0]['newMgmtIpAddress'] @@ -3598,7 +3644,8 @@ def verify_diff_merged(self, config): for prov_dict in provision_wired_list: device_ip = prov_dict['device_ip'] provision_device_list.append(device_ip) - if not self.get_provision_wired_device(device_ip): + device_prov_status = self.get_provision_wired_device(device_ip) + if device_prov_status == 1 or device_prov_status == 3: provision_wired_flag = False break diff --git a/plugins/modules/inventory_workflow_manager.py b/plugins/modules/inventory_workflow_manager.py index 17f63f475b..9af856ba64 100644 --- a/plugins/modules/inventory_workflow_manager.py +++ b/plugins/modules/inventory_workflow_manager.py @@ -57,7 +57,7 @@ default: "NETWORK_DEVICE" cli_transport: description: The essential prerequisite for adding Network devices is the specification of the transport - protocol (either SSH or Telnet) used by the device. + protocol (either ssh or telnet) used by the device. type: str compute_device: description: Indicates whether a device is a compute device. @@ -307,7 +307,7 @@ version_added: 6.12.0 requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco Catalyst Center documentation for Devices AddDevice2 @@ -774,6 +774,7 @@ def validate_input(self): 'clean_config': {'type': 'bool'}, 'add_user_defined_field': { 'type': 'list', + 'elements': 'dict', 'name': {'type': 'str'}, 'description': {'type': 'str'}, 'value': {'type': 'str'}, @@ -796,6 +797,7 @@ def validate_input(self): }, 'provision_wired_device': { 'type': 'list', + 'elements': 'dict', 'device_ip': {'type': 'str'}, 'site_name': {'type': 'str'}, 'resync_retry_count': {'default': 200, 'type': 'int'}, @@ -1584,6 +1586,21 @@ def provisioned_wired_device(self): 'siteNameHierarchy': site_name } + # Check the provisioning status of device + device_prov_status = self.get_provision_wired_device(device_ip) + if device_prov_status == 2: + self.status = "success" + already_provision_count += 1 + self.result['changed'] = False + self.msg = "Device '{0}' is already provisioned in the Cisco Catalyst Center".format(device_ip) + self.log(self.msg, "INFO") + continue + if device_prov_status == 3: + self.status = "failed" + error_msg = "Cannot do Provisioning for device {0}.".format(device_ip) + self.log(error_msg, "ERROR") + continue + # Check till device comes into managed state while resync_retry_count: response = self.get_device_response(device_ip) @@ -1626,7 +1643,7 @@ def provisioned_wired_device(self): if response.get("status") == "failed": description = response.get("description") error_msg = "Cannot do Provisioning for device {0} beacuse of {1}".format(device_ip, description) - self.log(error_msg) + self.log(error_msg, "ERROR") continue task_id = response.get("taskId") @@ -1647,9 +1664,6 @@ def provisioned_wired_device(self): # Not returning from here as there might be possiblity that for some devices it comes into exception # but for others it gets provision successfully or If some devices are already provsioned self.handle_provisioning_exception(device_ip, e, device_type) - if "already provisioned" in str(e): - self.log(str(e), "INFO") - already_provision_count += 1 # Check If all the devices are already provsioned, return from here only if already_provision_count == total_devices_to_provisioned: @@ -2457,18 +2471,24 @@ def get_provision_wired_device(self, device_ip): logs the response. """ - response = self.dnac._exec( - family="sda", - function='get_provisioned_wired_device', - op_modifies=True, - params={"device_management_ip_address": device_ip} - ) + try: + flag = 3 + response = self.dnac._exec( + family="sda", + function='get_provisioned_wired_device', + op_modifies=True, + params={"device_management_ip_address": device_ip} + ) - if response.get("status") == "failed": - self.log("Cannot do provisioning for wired device {0} because of {1}.".format(device_ip, response.get('description')), "ERROR") - return False + if response.get("status") == "success" and "retrieved successfully" in response.get("description"): + flag = 2 + self.log("Wired device '{0}' already provisioned in the Cisco Catalyst Center.".format(device_ip), "INFO") - return True + except Exception as e: + if "not provisioned to any site" in str(e): + flag = 1 + + return flag def clear_mac_address(self, interface_id, deploy_mode, interface_name): """ @@ -2870,10 +2890,26 @@ def get_diff_merged(self, config): credential_update = self.config[0].get("credential_update", False) config['type'] = device_type + config['ip_address_list'] = devices_to_add if device_type == "FIREPOWER_MANAGEMENT_SYSTEM": config['http_port'] = self.config[0].get("http_port", "443") - config['ip_address_list'] = devices_to_add + if self.config[0].get('provision_wired_device'): + provision_wired_list = self.config[0]['provision_wired_device'] + device_not_available = [] + device_in_ccc = self.device_exists_in_ccc() + + for prov_dict in provision_wired_list: + device_ip = prov_dict['device_ip'] + if device_ip not in device_in_ccc: + device_not_available.append(device_ip) + if device_not_available: + self.status = "failed" + self.msg = """Unable to Provision Wired Device(s) because the device(s) listed: {0} are not present in the + Cisco Catalyst Center.""".format(str(device_not_available)) + self.result['response'] = self.msg + self.log(self.msg, "ERROR") + return self if self.config[0].get('update_mgmt_ipaddresslist'): device_ip = self.config[0].get('update_mgmt_ipaddresslist')[0].get('existMgmtIpAddress') @@ -3023,6 +3059,7 @@ def get_diff_merged(self, config): devices_to_update_role = self.get_device_ips_from_config_priority() device_role = self.config[0].get('role') role_update_count = 0 + role_updated_list = [] for device_ip in devices_to_update_role: device_id = self.get_device_ids([device_ip]) @@ -3067,10 +3104,8 @@ def get_diff_merged(self, config): if 'successfully' in progress or 'succesfully' in progress: self.status = "success" - self.result['changed'] = True - self.msg = "Device(s) '{0}' role updated successfully to '{1}'".format(str(devices_to_update_role), device_role) - self.result['response'] = self.msg - self.log(self.msg, "INFO") + self.log("Device '{0}' role updated successfully to '{1}'".format(device_ip, device_role), "INFO") + role_updated_list.append(device_ip) break elif execution_details.get("isError"): self.status = "failed" @@ -3091,10 +3126,17 @@ def get_diff_merged(self, config): self.status = "success" self.result['changed'] = False self.msg = """The device role '{0}' is already set in Cisco Catalyst Center, no device role update is needed for the - devices {1}.""".format(device_role, str(devices_to_update_role)) + device(s) {1}.""".format(device_role, str(devices_to_update_role)) self.log(self.msg, "INFO") self.result['response'] = self.msg + if role_updated_list: + self.status = "success" + self.result['changed'] = True + self.msg = "Device(s) '{0}' role updated successfully to '{1}'".format(str(role_updated_list), device_role) + self.result['response'] = self.msg + self.log(self.msg, "INFO") + if credential_update: device_to_update = self.get_device_ips_from_config_priority() @@ -3221,6 +3263,10 @@ def get_diff_merged(self, config): if not playbook_params['httpPort']: playbook_params['httpPort'] = device_data.get('http_port', None) + for key, value in playbook_params.items(): + if value == " ": + playbook_params[key] = None + try: if playbook_params['updateMgmtIPaddressList']: new_mgmt_ipaddress = playbook_params['updateMgmtIPaddressList'][0]['newMgmtIpAddress'] @@ -3591,7 +3637,8 @@ def verify_diff_merged(self, config): for prov_dict in provision_wired_list: device_ip = prov_dict['device_ip'] provision_device_list.append(device_ip) - if not self.get_provision_wired_device(device_ip): + device_prov_status = self.get_provision_wired_device(device_ip) + if device_prov_status == 1 or device_prov_status == 3: provision_wired_flag = False break diff --git a/plugins/modules/ise_integration_status_info.py b/plugins/modules/ise_integration_status_info.py new file mode 100644 index 0000000000..d76eb0e012 --- /dev/null +++ b/plugins/modules/ise_integration_status_info.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: ise_integration_status_info +short_description: Information module for Ise Integration Status +description: +- Get all Ise Integration Status. +- API to check Cisco ISE server integration status. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for System Settings CiscoISEServerIntegrationStatus + description: Complete reference of the CiscoISEServerIntegrationStatus API. + link: https://developer.cisco.com/docs/dna-center/#!cisco-ise-server-integration-status +notes: + - SDK Method used are + system_settings.SystemSettings.cisco_ise_server_integration_status, + + - Paths used are + get /dna/intent/api/v1/ise-integration-status, + +""" + +EXAMPLES = r""" +- name: Get all Ise Integration Status + cisco.dnac.ise_integration_status_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "aaaServerSettingId": "string", + "overallStatus": "string", + "overallErrorMessage": "string", + "steps": [ + { + "stepId": "string", + "stepOrder": 0, + "stepName": "string", + "stepDescription": "string", + "stepStatus": "string", + "certAcceptedByUser": true, + "stepTime": 0 + } + ] + } +""" diff --git a/plugins/modules/ise_radius_integration_workflow_manager.py b/plugins/modules/ise_radius_integration_workflow_manager.py new file mode 100644 index 0000000000..c5a62715a5 --- /dev/null +++ b/plugins/modules/ise_radius_integration_workflow_manager.py @@ -0,0 +1,1474 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright (c) 2024, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +"""Ansible module to operate the Authentication and Policy Servers in Cisco Catalyst Center.""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type +__author__ = ["Muthu Rakesh, Madhan Sankaranarayanan"] + +DOCUMENTATION = r""" +--- +module: ise_radius_integration_workflow_manager +short_description: Resource module for Authentication and Policy Servers +description: +- Manage operations on Authentication and Policy Servers. +- API to create Authentication and Policy Server Access Configuration. +- API to update Authentication and Policy Server Access Configuration. +- API to delete Authentication and Policy Server Access Configuration. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.workflow_manager_params +author: Muthu Rakesh (@MUTHU-RAKESH-27) + Madhan Sankaranarayanan (@madhansansel) +options: + config_verify: + description: Set to True to verify the Cisco Catalyst Center after applying the playbook config. + type: bool + default: False + state: + description: The state of Cisco Catalyst Center after module completion. + type: str + choices: [ "merged", "deleted" ] + default: merged + config: + description: + - List of details of Authentication and Policy Servers being managed. + type: list + elements: dict + required: true + suboptions: + authentication_policy_server: + description: Manages the Authentication and Policy Servers. + type: dict + suboptions: + server_type: + description: + - Type of the Authentication and Policy Server. + - ISE for Cisco ISE servers. + - AAA for Non-Cisco ISE servers. + type: str + choices: [ "AAA", "ISE" ] + default: AAA + server_ip_address: + description: IP Address of the Authentication and Policy Server. + type: str + required: True + shared_secret: + description: + - Shared secret between devices and authentication and policy server. + - Shared secret must have 4 to 100 characters with no spaces or the following characters - ["<", "?"]. + - Shared secret is a Read-Only parameter. + type: str + protocol: + description: + - Type of protocol for authentication and policy server. + - RADIUS provides centralized services (AAA) for users in remote access scenarios. + - TACACS focuses on access control and administrative authentication for network devices. + type: str + choices: [ "TACACS", "RADIUS", "RADIUS_TACACS" ] + default: RADIUS + encryption_scheme: + description: + - Type of encryption scheme for additional security. + - If encryption scheme is given, then message authenticator code and encryption keys need to be required. + - Updation of encryption scheme is not possible. + - > + KEYWRAP is used for securely wrapping and unwrapping encryption keys, + ensuring their confidentiality during transmission or storage. + - > + RADSEC is an extension of RADIUS that provides secure communication + between RADIUS clients and servers over TLS/SSL. Enhances enhancing the + confidentiality and integrity of authentication and accounting data exchange. + type: str + choices: [ "KEYWRAP", "RADSEC" ] + encryption_key: + description: + - Encryption key used to encrypt shared secret. + - Updation of encryption scheme is not possible. + - Required when encryption_scheme is provided. + - > + When ASCII format is selected, Encryption Key may contain + alphanumeric and special characters. Key must be 16 char long. + type: str + message_authenticator_code_key: + description: + - Message key used to encrypt shared secret. + - Updation of message key is not possible. + - Required when encryption_scheme is provided. + - > + Message Authentication Code Key may contain alphanumeric and special characters. + Key must be 20 char long. + type: str + authentication_port: + description: + - Authentication port of RADIUS server. + - Updation of authentication port is not possible. + - Authentication port should be from 1 to 65535. + type: str + default: "1812" + accounting_port: + description: + - Accounting port of RADIUS server. + - Updation of accounting port is not possible. + - Accounting port should be from 1 to 65535. + type: str + default: "1813" + port: + description: + - Port of TACACS server. + - Updation of port is not possible. + - Port should be from 1 to 65535. + type: str + default: "49" + retries: + description: + - Number of communication retries between devices and authentication and policy server. + - Retries should be from 1 to 3. + type: str + default: "3" + timeout: + description: + - Number of seconds before timing out between devices and authentication and policy server. + - Timeout should be from 2 to 20. + type: str + default: "4" + role: + description: + - Role of authentication and policy server. + - Updation of role is not possible + type: str + default: secondary + pxgrid_enabled: + description: + - Set True to enable the Pxgrid and False to disable the Pxgrid. + - Pxgrid is available only for the Cisco ISE Servers. + - > + PxGrid facilitates seamless integration and information sharing across products, + enhancing threat detection and response capabilities within the network ecosystem. + type: bool + default: True + use_dnac_cert_for_pxgrid: + description: Set True to use the Cisco Catalyst Center certificate for the Pxgrid. + type: bool + default: False + cisco_ise_dtos: + description: + - List of Cisco ISE Data Transfer Objects (DTOs). + - Required when server_type is set to ISE. + type: list + elements: dict + suboptions: + user_name: + description: + - User name of the Cisco ISE server. + - Required for passing the cisco_ise_dtos. + type: str + password: + description: + - Password of the Cisco ISE server. + - Password must have 4 to 127 characters with no spaces or the following characters - "<". + - Required for passing the cisco_ise_dtos. + type: str + fqdn: + description: + - Fully-qualified domain name of the Cisco ISE server. + - Required for passing the cisco_ise_dtos. + type: str + ip_address: + description: + - IP Address of the Cisco ISE Server. + - Required for passing the cisco_ise_dtos. + type: str + subscriber_name: + description: + - Subscriber name of the Cisco ISE server. + - Required for passing the cisco_ise_dtos. + type: str + description: + description: Description about the Cisco ISE server. + type: str + ssh_key: + description: SSH key of the Cisco ISE server. + type: str + external_cisco_ise_ip_addr_dtos: + description: External Cisco ISE IP address data transfer objects for future use. + type: list + elements: dict + suboptions: + external_cisco_ise_ip_addresses: + description: External Cisco ISE IP addresses. + type: list + elements: dict + suboptions: + external_ip_address: + description: External Cisco ISE IP address. + type: str + ise_type: + description: Type of the Authentication and Policy Server. + type: str + trusted_server: + description: + - Indicates whether the certificate is trustworthy for the server. + - Serves as a validation of its authenticity and reliability in secure connections. + type: bool +requirements: +- dnacentersdk >= 2.7.1 +- python >= 3.9 +notes: + - SDK Method used are + system_settings.SystemSettings.add_authentication_and_policy_server_access_configuration, + system_settings.SystemSettings.edit_authentication_and_policy_server_access_configuration, + system_settings.SystemSettings.accept_cisco_ise_server_certificate_for_cisco_ise_server_integration, + system_settings.SystemSettings.delete_authentication_and_policy_server_access_configuration, + + - Paths used are + post /dna/intent/api/v1/authentication-policy-servers, + put /dna/intent/api/v1/authentication-policy-servers/${id}, + put /dna/intent/api/v1/integrate-ise/${id}, + delete /dna/intent/api/v1/authentication-policy-servers/${id} + +""" + +EXAMPLES = r""" +- name: Create an AAA server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - authentication_policy_server: + server_type: AAA + server_ip_address: 10.0.0.1 + shared_secret: 12345 + protocol: RADIUS_TACACS + encryption_scheme: KEYWRAP + encryption_key: 1234567890123456 + message_authenticator_code_key: asdfghjklasdfghjklas + authentication_port: 1812 + accounting_port: 1813 + port: 49 + retries: 3 + timeout: 4 + role: secondary + +- name: Create an Cisco ISE server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - authentication_policy_server: + server_type: ISE + server_ip_address: 10.0.0.2 + shared_secret: 12345 + protocol: RADIUS_TACACS + encryption_scheme: KEYWRAP + encryption_key: 1234567890123456 + message_authenticator_code_key: asdfghjklasdfghjklas + authentication_port: 1812 + accounting_port: 1813 + port: 49 + retries: 3 + timeout: 4 + role: primary + use_dnac_cert_for_pxgrid: False + pxgrid_enabled: True + cisco_ise_dtos: + - user_name: Cisco ISE + password: 12345 + fqdn: abs.cisco.com + ip_address: 10.0.0.2 + subscriber_name: px-1234 + description: Cisco ISE + +- name: Update an AAA server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - authentication_policy_server: + server_type: AAA + server_ip_address: 10.0.0.1 + protocol: RADIUS_TACACS + authentication_port: 1812 + accounting_port: 1813 + port: 49 + retries: 3 + timeout: 5 + role: secondary + +- name: Update an Cisco ISE server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - authentication_policy_server: + server_type: ISE + server_ip_address: 10.0.0.2 + protocol: RADIUS_TACACS + authentication_port: 1812 + accounting_port: 1813 + port: 49 + retries: 3 + timeout: 5 + role: primary + use_dnac_cert_for_pxgrid: False + pxgrid_enabled: True + cisco_ise_dtos: + - user_name: Cisco ISE + password: 12345 + fqdn: abs.cisco.com + ip_address: 10.0.0.2 + subscriber_name: px-1234 + description: Cisco ISE + +- name: Delete an Authentication and Policy server. + cisco.dnac.ise_radius_integration_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - authentication_policy_server: + server_ip_address: 10.0.0.1 +""" + +RETURN = r""" +# Case_1: Successful creation of Authentication and Policy Server. +response_1: + description: A dictionary or list with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } + +# Case_2: Successful updation of Authentication and Policy Server. +response_2: + description: A dictionary or list with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } + +# Case_3: Successful creation/updation of network +response_3: + description: A dictionary or list with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" + +import copy +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.dnac.plugins.module_utils.dnac import ( + DnacBase, + validate_list_of_dicts, + get_dict_result, + dnac_compare_equality, +) + + +class IseRadiusIntegration(DnacBase): + """Class containing member attributes for ise_radius_integration_workflow_manager module""" + + def __init__(self, module): + super().__init__(module) + self.result["response"] = [ + {"authenticationPolicyServer": {"response": {}, "msg": {}}} + ] + self.authentication_policy_server_obj_params = \ + self.get_obj_params("authenticationPolicyServer") + + def validate_input(self): + """ + Checks if the configuration parameters provided in the playbook + meet the expected structure and data types, + as defined in the 'temp_spec' dictionary. + + Parameters: + None + + Returns: + self + + """ + + if not self.config: + self.msg = "config not available in playbook for validation" + self.status = "success" + return self + + # temp_spec is the specification for the expected structure of configuration parameters + temp_spec = { + "authentication_policy_server": { + "type": "dict", + "server_type": {"type": 'string', "choices": ["AAA", "ISE"]}, + "server_ip_address": {"type": 'string'}, + "shared_secret": {"type": 'string'}, + "protocol": {"type": 'string', "choices": ["TACACS", "RADIUS", "RADIUS_TACACS"]}, + "encryption_scheme": {"type": 'string'}, + "message_authenticator_code_key": {"type": 'string'}, + "encryption_key": {"type": 'string'}, + "authentication_port": {"type": 'string'}, + "accounting_port": {"type": 'string'}, + "port": {"type": 'string'}, + "retries": {"type": 'string'}, + "timeout": {"type": 'string'}, + "role": {"type": 'string'}, + "pxgrid_enabled": {"type": 'bool'}, + "use_dnac_cert_for_pxgrid": {"type": 'bool'}, + "cisco_ise_dtos": { + "type": 'list', + "user_name": {"type": 'string'}, + "password": {"type": 'string'}, + "fqdn": {"type": 'string'}, + "ip_address": {"type": 'string'}, + "subscriber_name": {"type": 'string'}, + "description": {"type": 'string'}, + "ssh_key": {"type": 'string'}, + }, + "external_cisco_ise_ip_addr_dtos": { + "type": 'list', + "external_cisco_ise_ip_addresses": { + "type": 'list', + "external_ip_address": {"type": 'string'}, + }, + "ise_type": {"type": 'string'}, + } + } + } + + # Validate playbook params against the specification (temp_spec) + valid_temp, invalid_params = validate_list_of_dicts(self.config, temp_spec) + if invalid_params: + self.msg = "Invalid parameters in playbook: {0}".format("\n".join(invalid_params)) + self.status = "failed" + return self + + self.validated_config = valid_temp + self.log("Successfully validated playbook config params: {0}".format(valid_temp), "INFO") + self.msg = "Successfully validated input from the playbook" + self.status = "success" + return self + + def requires_update(self, have, want, obj_params): + """ + Check if the template config given requires update by comparing + current information wih the requested information. + + This method compares the current global pool, reserve pool, + or network details from Cisco Catalyst Center with the user-provided details + from the playbook, using a specified schema for comparison. + + Parameters: + have (dict) - Current information from the Cisco Catalyst Center + (global pool, reserve pool, network details) + want (dict) - Users provided information from the playbook + obj_params (list of tuples) - A list of parameter mappings specifying which + Cisco Catalyst Center parameters (dnac_param) + correspond to the user-provided + parameters (ansible_param). + + Returns: + bool - True if any parameter specified in obj_params differs between + current_obj and requested_obj, indicating that an update is required. + False if all specified parameters are equal. + + """ + + current_obj = have + requested_obj = want + self.log("Current State (have): {0}".format(current_obj), "DEBUG") + self.log("Desired State (want): {0}".format(requested_obj), "DEBUG") + + return any(not dnac_compare_equality(current_obj.get(dnac_param), + requested_obj.get(ansible_param)) + for (dnac_param, ansible_param) in obj_params) + + def get_obj_params(self, get_object): + """ + Get the required comparison obj_params value + + Parameters: + get_object (str) - identifier for the required obj_params + + Returns: + obj_params (list) - obj_params value for comparison. + """ + + try: + obj_params = [] + if get_object == "authenticationPolicyServer": + obj_params = [ + ("pxgridEnabled", "pxgridEnabled"), + ("useDnacCertForPxgrid", "useDnacCertForPxgrid"), + ("protocol", "protocol"), + ("retries", "retries"), + ("timeoutSeconds", "timeoutSeconds"), + ("externalCiscoIseIpAddrDtos", "externalCiscoIseIpAddrDtos") + ] + else: + raise ValueError("Received an unexpected value for 'get_object': {0}" + .format(get_object)) + except Exception as msg: + self.log("Received exception: {0}".format(msg), "CRITICAL") + + return obj_params + + def get_auth_server_params(self, auth_server_info): + """ + Process Authentication and Policy Server params from playbook data for + Authentication and Policy Server config in Cisco Catalyst Center. + + Parameters: + auth_server_info (dict) - Cisco Catalyst Center data containing + information about the Authentication and Policy Server. + + Returns: + dict or None - Processed Authentication and Policy Server data in a format suitable + for Cisco Catalyst Center configuration, or None if auth_server_info is empty. + """ + + if not auth_server_info: + self.log("Authentication and Policy Server data is empty", "INFO") + return None + + self.log("Authentication and Policy Server Details: {0}".format(auth_server_info), "DEBUG") + auth_server = { + "authenticationPort": auth_server_info.get("authenticationPort"), + "accountingPort": auth_server_info.get("accountingPort"), + "isIseEnabled": auth_server_info.get("iseEnabled"), + "ipAddress": auth_server_info.get("ipAddress"), + "pxgridEnabled": auth_server_info.get("pxgridEnabled"), + "useDnacCertForPxgrid": auth_server_info.get("useDnacCertForPxgrid"), + "port": auth_server_info.get("port"), + "protocol": auth_server_info.get("protocol"), + "retries": str(auth_server_info.get("retries")), + "role": auth_server_info.get("role"), + "timeoutSeconds": str(auth_server_info.get("timeoutSeconds")), + "encryptionScheme": auth_server_info.get("encryptionScheme") + } + self.log("Formated Authentication and Policy Server details: {0}" + .format(auth_server), "DEBUG") + if auth_server.get("isIseEnabled") is True: + auth_server_ise_info = auth_server_info.get("ciscoIseDtos") + auth_server.update({"ciscoIseDtos": []}) + for ise_credential in auth_server_ise_info: + auth_server.get("ciscoIseDtos").append({ + "userName": ise_credential.get("userName"), + "fqdn": ise_credential.get("fqdn"), + "ipAddress": ise_credential.get("ipAddress"), + "subscriberName": ise_credential.get("subscriberName"), + "description": ise_credential.get("description") + }) + + return auth_server + + def auth_server_exists(self, ipAddress): + """ + Check if the Authentication and Policy Server with the given ipAddress exists + + Parameters: + ipAddress (str) - The ipAddress of the Authentication and + Policy Server to check for existence. + + Returns: + dict - A dictionary containing information about the + Authentication and Policy Server's existence: + - 'exists' (bool): True if the Authentication and Policy Server exists, False otherwise. + - 'id' (str or None): The ID of the Authentication and Policy Server if it exists + or None if it doesn't. + - 'details' (dict or None): Details of the Authentication and Policy Server if it exists + else None. + """ + + AuthServer = { + "exists": False, + "details": None, + "id": None + } + response = self.dnac._exec( + family="system_settings", + function='get_authentication_and_policy_servers', + ) + if not isinstance(response, dict): + self.log("Failed to retrieve the Authentication and Policy Server details - " + "Response is not a dictionary", "CRITICAL") + return AuthServer + + all_auth_server_details = response.get("response") + auth_server_details = get_dict_result(all_auth_server_details, "ipAddress", ipAddress) + self.log("Authentication and Policy Server Ip Address: {0}" + .format(ipAddress), "DEBUG") + self.log("Authentication and Policy Server details: {0}" + .format(auth_server_details), "DEBUG") + if not auth_server_details: + self.log("Global pool {0} does not exist".format(ipAddress), "INFO") + return AuthServer + + AuthServer.update({"exists": True}) + AuthServer.update({"id": auth_server_details.get("instanceUuid")}) + AuthServer["details"] = self.get_auth_server_params(auth_server_details) + + self.log("Formatted global pool details: {0}".format(AuthServer), "DEBUG") + return AuthServer + + def get_have_authentication_policy_server(self, config): + """ + Get the current Authentication and Policy Server information from + Cisco Catalyst Center based on the provided playbook details. + check this API using check_return_status. + + Parameters: + config (dict) - Playbook details containing + Authentication and Policy Server configuration. + + Returns: + self - The current object with updated + Authentication and Policy Server information. + """ + + AuthServer = { + "exists": False, + "details": None, + "id": None + } + authentication_policy_server = config.get("authentication_policy_server") + if authentication_policy_server is None: + self.msg = "authentication_policy_server in config is missing in the playbook" + self.status = "failed" + return self + + ip_address = authentication_policy_server.get("server_ip_address") + if ip_address is None: + self.msg = "Mandatory Parameter server_ip_address required" + self.status = "failed" + return self + + AuthServer = self.auth_server_exists(ip_address) + self.log("Authentication and Policy Server exists: {0}" + .format(AuthServer.get("exists")), "DEBUG") + self.log("Authentication and Policy Server details: {0}" + .format(AuthServer.get("details")), "DEBUG") + self.log("Authentication and Policy Server Id: {0}" + .format(AuthServer.get("id")), "DEBUG") + self.have.update({"authenticationPolicyServer": AuthServer}) + self.msg = "Collecting the Authentication and Policy Server " + \ + "details from the Cisco Catalyst Center." + self.status = "success" + return self + + def get_have(self, config): + """ + Get the current Authentication and Policy Server details from Cisco Catalyst Center + + Parameters: + config (dict) - Playbook details containing + Authentication and Policy Server configuration. + + Returns: + self - The current object with updated + Authentication and Policy Server information. + """ + + if config.get("authentication_policy_server") is not None: + self.get_have_authentication_policy_server(config).check_return_status() + + self.log("Current State (have): {0}".format(self.have), "INFO") + self.msg = "Successfully retrieved the details from the Cisco Catalyst Center" + self.status = "success" + return self + + def get_want_authentication_policy_server(self, auth_policy_server): + """ + Get all the Authentication Policy Server information from playbook + Set the status and the msg before returning from the API + Check the return value of the API with check_return_status() + + Parameters: + auth_policy_server (dict) - Playbook authentication policy server details + containing IpAddress, authentication port, accounting port, Cisco ISE Details, + protocol, port, retries, role, timeout seconds, encryption details. + + Returns: + self - The current object with updated desired Authentication Policy Server information. + """ + + auth_server = {} + trusted_server = False + server_type = auth_policy_server.get("server_type") + if server_type not in ["ISE", "AAA", None]: + self.msg = "server_type should either be ISE or AAA but not {0}.".format(server_type) + self.status = "failed" + return self + + if server_type == "ISE": + auth_server.update({"isIseEnabled": True}) + else: + auth_server.update({"isIseEnabled": False}) + + auth_server.update({"ipAddress": auth_policy_server.get("server_ip_address")}) + + auth_server_exists = self.have.get("authenticationPolicyServer").get("exists") + shared_secret = auth_policy_server.get("shared_secret") + if not (shared_secret or auth_server_exists): + self.msg = "shared_secret is mandatory parameter" + self.status = "failed" + return self + + if not (4 <= len(shared_secret) <= 100) or shared_secret.isspace(): + self.msg = "The 'shared_secret' should contain between 4 and 100 characters." + self.status = "failed" + return self + + if "?" in shared_secret or "<" in shared_secret: + self.msg = "The 'shared_secret' should not contain '?' or '<' characters." + self.status = "failed" + return self + + auth_server.update({"sharedSecret": shared_secret}) + + protocol = auth_policy_server.get("protocol") + if protocol not in ["RADIUS", "TACACS", "RADIUS_TACACS", None]: + self.msg = "protocol should either be ['RADIUS', 'TACACS', 'RADIUS_TACACS']." + \ + "It should not be {0}".format(protocol) + self.status = "failed" + return self + + if protocol is not None: + auth_server.update({"protocol": protocol}) + else: + auth_server.update({"protocol": "RADIUS"}) + + encryption_scheme = str(auth_policy_server.get("encryption_scheme")) + if encryption_scheme not in ["KEYWRAP", "RADSEC", None]: + self.msg = "encryption_scheme should be in ['KEYWRAP', 'RADSEC']. " + \ + "It should not be {0}.".format(encryption_scheme) + self.status = "failed" + return self + + if encryption_scheme: + auth_server.update({"encryptionScheme": encryption_scheme}) + + if encryption_scheme == "KEYWRAP": + message_key = str(auth_policy_server.get("message_authenticator_code_key")) + if not message_key: + self.msg = "The 'message_authenticator_code_key' should not be empty if the encryption_scheme is 'KEYWRAP'." + self.status = "failed" + return self + + if len(message_key) != 20: + self.msg = "The 'message_authenticator_code_key' should be exactly 20 characters." + self.status = "failed" + return self + + auth_server.update({"messageKey": message_key}) + + encryption_key = auth_policy_server.get("encryption_key") + if not encryption_key: + self.msg = "encryption_key should not be empty if encryption_scheme is 'KEYWRAP'." + self.status = "failed" + return self + + if len(encryption_key) != 16: + self.msg = "The 'encryption_key' must be 16 characters long. It may contain alphanumeric and special characters." + self.status = "failed" + return self + + auth_server.update({"encryptionKey": encryption_key}) + + authentication_port = int(auth_policy_server.get("authentication_port")) + if not 1 <= int(authentication_port) <= 65535: + self.msg = "authentication_port should be from 1 to 65535." + self.status = "failed" + return self + + if authentication_port: + auth_server.update({"authenticationPort": authentication_port}) + else: + auth_server.update({"authenticationPort": "1812"}) + + accounting_port = int(auth_policy_server.get("accounting_port")) + if not 1 <= int(accounting_port) <= 65535: + self.msg = "accounting_port should be from 1 to 65535." + self.status = "failed" + return self + + if accounting_port: + auth_server.update({"accountingPort": accounting_port}) + else: + auth_server.update({"accountingPort": "1813"}) + + port = int(auth_policy_server.get("port")) + if port: + auth_server.update({"port": port}) + else: + auth_server.update({"port": "49"}) + + retries = str(auth_policy_server.get("retries")) + if not retries.isdigit(): + self.msg = "retries should contain only from 0-9." + self.status = "failed" + return self + + if not 1 <= int(retries) <= 3: + self.msg = "retries should be from 1 to 3." + self.status = "failed" + return self + + if retries: + auth_server.update({"retries": retries}) + else: + auth_server.update({"retries": "3"}) + + timeout = str(auth_policy_server.get("timeout")) + if not timeout.isdigit(): + self.msg = "timeout should contain only from 0-9." + self.status = "failed" + return self + + if not 2 <= int(timeout) <= 20: + self.msg = "timeout should be from 2 to 20." + self.status = "failed" + return self + + if timeout: + auth_server.update({"timeoutSeconds": timeout}) + else: + auth_server.update({"timeoutSeconds": "4"}) + + role = auth_policy_server.get("role") + if role: + auth_server.update({"role": role}) + else: + auth_server.update({"role": "secondary"}) + + if auth_server.get("isIseEnabled"): + cisco_ise_dtos = auth_policy_server.get("cisco_ise_dtos") + if not cisco_ise_dtos: + self.msg = "Mandatory parameter cisco_ise_dtos " + \ + "required when server_type is 'ISE'." + self.status = "failed" + return self + + auth_server.update({"ciscoIseDtos": []}) + position_ise_creds = 0 + for ise_credential in cisco_ise_dtos: + auth_server.get("ciscoIseDtos").append({}) + user_name = ise_credential.get("user_name") + if not user_name: + self.msg = "Mandatory parameter user_name required for ISE." + self.status = "failed" + return self + + auth_server.get("ciscoIseDtos")[position_ise_creds].update({ + "userName": user_name + }) + + password = ise_credential.get("password") + if not password: + self.msg = "Mandatory paramter password required for ISE." + self.status = "failed" + return self + + if not 4 <= len(password) <= 127: + self.msg = "" + self.status = "failed" + return self + + auth_server.get("ciscoIseDtos")[position_ise_creds].update({ + "password": password + }) + + fqdn = ise_credential.get("fqdn") + if not fqdn: + self.msg = "Mandatory parameter required for ISE." + self.status = "failed" + return self + + auth_server.get("ciscoIseDtos")[position_ise_creds].update({"fqdn": fqdn}) + + ip_address = ise_credential.get("ip_address") + if not ip_address: + self.msg = "Mandatory parameter ip_address required for ISE." + self.status = "failed" + return self + + auth_server.get("ciscoIseDtos")[position_ise_creds].update({ + "ipAddress": ip_address + }) + + subscriber_name = ise_credential.get("subscriber_name") + if not subscriber_name: + self.msg = "Mandatory parameter subscriber_name required for ISE." + self.status = "failed" + return self + + auth_server.get("ciscoIseDtos")[position_ise_creds].update({ + "subscriberName": subscriber_name + }) + + description = ise_credential.get("description") + if description: + auth_server.get("ciscoIseDtos")[position_ise_creds].update({ + "description": description + }) + + ssh_key = str(ise_credential.get("ssh_key")) + if ssh_key: + auth_server.get("ciscoIseDtos")[position_ise_creds].update({ + "sshkey": ssh_key + }) + + position_ise_creds += 1 + + pxgrid_enabled = auth_policy_server.get("pxgrid_enabled") + if pxgrid_enabled: + auth_server.update({"pxgridEnabled": pxgrid_enabled}) + else: + auth_server.update({"pxgridEnabled": True}) + + use_dnac_cert_for_pxgrid = auth_policy_server.get("use_dnac_cert_for_pxgrid") + if use_dnac_cert_for_pxgrid: + auth_server.update({"useDnacCertForPxgrid": use_dnac_cert_for_pxgrid}) + else: + auth_server.update({"useDnacCertForPxgrid": False}) + + external_cisco_ise_ip_addr_dtos = auth_policy_server \ + .get("external_cisco_ise_ip_addr_dtos") + if external_cisco_ise_ip_addr_dtos: + auth_server.update({"externalCiscoIseIpAddrDtos": []}) + position_ise_addresses = 0 + for external_cisco_ise in external_cisco_ise_ip_addr_dtos: + external_cisco_ise_ip_addresses = external_cisco_ise \ + .get("external_cisco_ise_ip_addresses") + if external_cisco_ise_ip_addresses: + auth_server.get("externalCiscoIseIpAddrDtos").append({}) + auth_server.get("externalCiscoIseIpAddrDtos")[position_ise_addresses] \ + .update({"externalCiscoIseIpAddresses": []}) + position_ise_address = 0 + for external_ip_address in external_cisco_ise_ip_addresses: + auth_server.get("externalCiscoIseIpAddrDtos")[position_ise_addresses] \ + .get("externalCiscoIseIpAddresses").append({}) + auth_server.get("externalCiscoIseIpAddrDtos")[position_ise_addresses] \ + .get("externalCiscoIseIpAddresses")[position_ise_address].update({ + "externalIpAddress": external_ip_address.get("external_ip_address") + }) + position_ise_address += 1 + ise_type = external_cisco_ise.get("ise_type") + if ise_type: + auth_server.get("externalCiscoIseIpAddrDtos")[position_ise_addresses] \ + .update({"type": ise_type}) + position_ise_addresses += 1 + + if auth_policy_server.get("trusted_server"): + trusted_server = True + + self.log("Authentication and Policy Server playbook details: {0}" + .format(auth_server), "DEBUG") + self.want.update({"authenticationPolicyServer": auth_server}) + self.want.update({"trusted_server": trusted_server}) + self.msg = "Collecting the Authentication and Policy Server details from the playbook" + self.status = "success" + return self + + def get_want(self, config): + """ + Get all the Authentication Policy Server related information from playbook + + Parameters: + config (list of dict) - Playbook details + + Returns: + None + """ + + if config.get("authentication_policy_server"): + auth_policy_server = config.get("authentication_policy_server") + self.get_want_authentication_policy_server(auth_policy_server).check_return_status() + + self.log("Desired State (want): {0}".format(self.want), "INFO") + self.msg = "Successfully retrieved details from the playbook" + self.status = "success" + return self + + def accept_cisco_ise_server_certificate(self, ipAddress, trusted_server): + """ + Accept the Cisco ISE server certificate in Cisco Catalyst + Center provided in the playbook. + + Parameters: + ipAddress (str) - The Ip address of the Authentication and Policy Server to be deleted. + trusted_server (bool) - Indicates whether the certificate is trustworthy for the server. + + Returns: + None + """ + + try: + AuthServer = self.auth_server_exists(ipAddress) + if not AuthServer: + self.msg = "Error while retrieving the Authentication and Policy Server {0} \ + details.".format(ipAddress) + self.log(str(self.msg, "CRITICAL")) + self.status = "failed" + return self + + cisco_ise_id = AuthServer.get("id") + if not cisco_ise_id: + self.msg = "Error while retrieving the Authentication and Policy Server {0} id." \ + .format(ipAddress) + self.log(str(self.msg, "CRITICAL")) + self.status = "failed" + return self + + response = self.dnac._exec( + family="system_settings", + function="accept_cisco_ise_server_certificate_for_cisco_ise_server_integration", + params={ + "id": cisco_ise_id, + "isCertAcceptedByUser": trusted_server + }, + ) + self.log("Received API response for 'accept_cisco_ise_server_certificate_" + "for_cisco_ise_server_integration': {0}".format(response), "DEBUG") + except Exception as msg: + self.log("Exception occurred while accepting the certificate of {0}: {1}" + .format(ipAddress, msg)) + return None + return + + def format_payload_for_update(self, have_auth_server, want_auth_server): + """ + Format the parameter of the payload for updating the authentication and policy server + in accordance with the information in the Cisco Catalyst Ceter. + + Parameters: + have_auth_server (dict) - Authentication and policy server information from the Cisco Catalyst Center. + want_auth_server (dict) - Authentication and policy server information from the Playbook. + + Returns: + self - The current object with updated desired Authentication Policy Server information. + """ + + if want_auth_server.get("sharedSecret") is not None: + del want_auth_server["sharedSecret"] + if want_auth_server.get("encryptionScheme") is not None: + del want_auth_server["encryptionScheme"] + if want_auth_server.get("messageKey") is not None: + del want_auth_server["messageKey"] + if want_auth_server.get("encryptionKey") is not None: + del want_auth_server["encryptionKey"] + + update_params = ["authenticationPort", "accountingPort", "port", "role"] + for item in update_params: + have_auth_server_item = have_auth_server.get(item) + want_auth_server_item = want_auth_server.get(item) + if want_auth_server_item is None: + want_auth_server.update({item: have_auth_server_item}) + + elif have_auth_server_item != want_auth_server_item: + self.msg = "Update does not support modifying '{0}'. Here you are trying to update '{1}'." \ + .format(update_params, item) + self.status = "failed" + return self + + have_auth_server_protocol = have_auth_server.get("protocol") + want_auth_server_protocol = want_auth_server.get("protocol") + if have_auth_server_protocol != want_auth_server_protocol: + if want_auth_server_protocol != "RADIUS_TACACS": + self.msg = "'protocol' can only be updated to 'RADIUS_TACACS' not from '{0}' to '{1}'" \ + .format(have_auth_server_protocol, want_auth_server_protocol) + self.status = "failed" + return self + + self.log("Successfully formatted the parameter of the payload for updating the authentication and policy server.") + self.msg = "Successfully formatted the parameter of the payload for updating the authentication and policy server." + self.status = "success" + return self + + def update_auth_policy_server(self, ipAddress): + """ + Update/Create Authentication and Policy Server in Cisco + Catalyst Center with fields provided in playbook. + + Parameters: + ipAddress (str) - The Ip address of the Authentication and Policy Server to be deleted. + + Returns: + None + """ + + result_auth_server = self.result.get("response")[0].get("authenticationPolicyServer") + result_auth_server.get("response").update({ipAddress: {}}) + + # Check Authentication and Policy Server exist, if not create and return + is_ise_server = self.want.get("authenticationPolicyServer").get("isIseEnabled") + if not self.have.get("authenticationPolicyServer").get("exists"): + auth_server_params = self.want.get("authenticationPolicyServer") + self.log("Desired State for Authentication and Policy Server (want): {0}" + .format(auth_server_params), "DEBUG") + response = self.dnac._exec( + family="system_settings", + function="add_authentication_and_policy_server_access_configuration", + params=auth_server_params, + ) + if not is_ise_server: + validation_string = "successfully created aaa settings" + else: + validation_string = "operation sucessful" + + self.check_task_response_status(response, validation_string).check_return_status() + if is_ise_server: + trusted_server = self.want.get("trusted_server") + self.accept_cisco_ise_server_certificate(ipAddress, trusted_server) + + self.log("Successfully created Authentication and Policy Server '{0}'." + .format(ipAddress), "INFO") + result_auth_server.get("response").get(ipAddress) \ + .update({ + "authenticationPolicyServer Details": self.want + .get("authenticationPolicyServer") + }) + result_auth_server.get("msg").update({ + ipAddress: "Authentication and Policy Server Created Successfully" + }) + return + + # Authentication and Policy Server exists, check update is required + # Edit API not working, remove this + self.format_payload_for_update(self.have.get("authenticationPolicyServer").get("details"), + self.want.get("authenticationPolicyServer")).check_return_status() + if not self.requires_update(self.have.get("authenticationPolicyServer").get("details"), + self.want.get("authenticationPolicyServer"), + self.authentication_policy_server_obj_params): + self.log("Authentication and Policy Server '{0}' doesn't require an update" + .format(ipAddress), "INFO") + result_auth_server.get("response").get(ipAddress).update({ + "Cisco Catalyst Center params": + self.have.get("authenticationPolicyServer").get("details") + }) + result_auth_server.get("response").get(ipAddress).update({ + "Id": self.have.get("authenticationPolicyServer").get("id") + }) + result_auth_server.get("msg").update({ + ipAddress: "Authentication and Policy Server doesn't require an update" + }) + return + + self.log("Authentication and Policy Server requires update", "DEBUG") + + # Authenticaiton and Policy Server Exists + auth_server_params = copy.deepcopy(self.want.get("authenticationPolicyServer")) + auth_server_params.update({"id": self.have.get("authenticationPolicyServer").get("id")}) + self.log("Desired State for Authentication and Policy Server (want): {0}" + .format(auth_server_params), "DEBUG") + self.log("Current State for Authentication and Policy Server (have): {0}" + .format(self.have.get("authenticationPolicyServer").get("details")), "DEBUG") + response = self.dnac._exec( + family="system_settings", + function="edit_authentication_and_policy_server_access_configuration", + params=auth_server_params, + ) + validation_string = "successfully updated aaa settings" + self.check_task_response_status(response, validation_string).check_return_status() + self.log("Authentication and Policy Server '{0}' updated successfully" + .format(ipAddress), "INFO") + result_auth_server.get("response").get(ipAddress) \ + .update({"Id": self.have.get("authenticationPolicyServer").get("id")}) + result_auth_server.get("msg").update({ + ipAddress: "Authentication and Policy Server Updated Successfully" + }) + return + + def get_diff_merged(self, config): + """ + Update or create Authentication and Policy Server in + Cisco Catalyst Center based on the playbook details. + + Parameters: + config (list of dict) - Playbook details containing + Authentication and Policy Server information. + + Returns: + self + """ + + if config.get("authentication_policy_server") is not None: + ipAddress = config.get("authentication_policy_server").get("server_ip_address") + self.update_auth_policy_server(ipAddress) + + return self + + def delete_auth_policy_server(self, ipAddress): + """ + Delete a Authentication and Policy Server by server Ip address in Cisco Catalyst Center. + + Parameters: + ipAddress (str) - The Ip address of the Authentication and Policy Server to be deleted. + + Returns: + self + """ + + auth_server_exists = self.have.get("authenticationPolicyServer").get("exists") + result_auth_server = self.result.get("response")[0].get("authenticationPolicyServer") + if not auth_server_exists: + result_auth_server.get("response").update({ + ipAddress: "Authentication and Policy Server not found" + }) + self.msg = "Authentication and Policy Server not found." + self.status = "success" + return self + + response = self.dnac._exec( + family="system_settings", + function="delete_authentication_and_policy_server_access_configuration", + params={"id": self.have.get("authenticationPolicyServer").get("id")}, + ) + + self.log("Received API response for 'delete_authentication_and_" + "policy_server_access_configuration': {0}".format(response), "DEBUG") + + # Check the task status + validation_string = "successfully deleted aaa settings" + self.check_task_response_status(response, validation_string).check_return_status() + taskid = response.get("response").get("taskId") + + # Update result information + result_auth_server.get("response").update({ipAddress: {}}) + result_auth_server.get("response").get(ipAddress).update({"Task Id": taskid}) + result_auth_server.get("msg").update({ + ipAddress: "Authentication and Policy Server deleted successfully." + }) + self.msg = "Authentication and Policy Server - {0} deleted successfully.".format(ipAddress) + self.status = "success" + return self + + def get_diff_deleted(self, config): + """ + Delete Authentication and Policy Server from the Cisco Catalyst Center. + + Parameters: + config (list of dict) - Playbook details + + Returns: + self + """ + + if config.get("authentication_policy_server") is not None: + ipAddress = config.get("authentication_policy_server").get("server_ip_address") + self.delete_auth_policy_server(ipAddress).check_return_status() + + return self + + def verify_diff_merged(self, config): + """ + Validating the Cisco Catalyst Center configuration with the playbook details + when state is merged (Create/Update). + + Parameters: + config (dict) - Playbook details containing + Authentication and Policy Server configuration. + + Returns: + self + """ + + self.get_have(config) + self.log("Current State (have): {0}".format(self.have), "INFO") + self.log("Requested State (want): {0}".format(self.want), "INFO") + if config.get("authentication_policy_server") is not None: + self.log("Desired State of Authentication and Policy Server (want): {0}" + .format(self.want.get("authenticationPolicyServer")), "DEBUG") + self.log("Current State of Authentication and Policy Server (have): {0}" + .format(self.have.get("authenticationPolicyServer") + .get("details")), "DEBUG") + check_list = ["isIseEnabled", "ipAddress", "pxgridEnabled", + "useDnacCertForPxgrid", "port", "protocol", + "retries", "role", "timeoutSeconds", "encryptionScheme"] + auth_server_have = self.have.get("authenticationPolicyServer").get("details") + auth_server_want = self.want.get("authenticationPolicyServer") + for item in check_list: + if auth_server_have.get(item) and auth_server_want.get(item) and \ + auth_server_have.get(item) != auth_server_want.get(item): + self.msg = "Authentication and Policy Server " + \ + "Config is not applied to the Cisco Catalyst Center." + self.status = "failed" + return self + + self.log("Successfully validated Authentication and Policy Server '{0}'." + .format(self.want.get("authenticationPolicyServer").get("ipAddress")), "INFO") + self.result.get("response")[0].get("authenticationPolicyServer").update({ + "Validation": "Success" + }) + + self.msg = "Successfully validated the Authentication and Policy Server." + self.status = "success" + return self + + def verify_diff_deleted(self, config): + """ + Validating the Cisco Catalyst Center configuration with the playbook details + when state is deleted (delete). + + Parameters: + config (dict) - Playbook details containing + Authentication and Policy Server configuration. + + Returns: + self + """ + + self.get_have(config) + ipAddress = config.get("authentication_policy_server").get("server_ip_address") + self.log("Current State (have): {0}".format(self.have), "INFO") + self.log("Authentication and Policy Server deleted from the Cisco Catalyst Center: {0}" + .format(ipAddress), "INFO") + if config.get("authentication_policy_server") is not None: + auth_server_exists = self.have.get("authenticationPolicyServer").get("exists") + if auth_server_exists: + self.msg = "Authentication and Policy Server " + \ + "Config is not applied to the Cisco Catalyst Center." + self.status = "failed" + return self + + self.log("Successfully validated absence of Authentication and Policy Server '{0}'." + .format(config.get("authentication_policy_server").get("ip_address")), "INFO") + self.result.get("response")[0].get("authenticationPolicyServer").update({ + "Validation": "Success" + }) + + self.msg = "Successfully validated the absence of Authentication and Policy Server." + self.status = "success" + return self + + def reset_values(self): + """ + Reset all neccessary attributes to default values + + Parameters: + None + + Returns: + None + """ + + self.have.clear() + self.want.clear() + return + + +def main(): + """main entry point for module execution""" + + # Define the specification for module arguments + element_spec = { + "dnac_host": {"type": 'str', "required": True}, + "dnac_port": {"type": 'str', "default": '443'}, + "dnac_username": {"type": 'str', "default": 'admin', "aliases": ['user']}, + "dnac_password": {"type": 'str', "no_log": True}, + "dnac_verify": {"type": 'bool', "default": 'True'}, + "dnac_version": {"type": 'str', "default": '2.2.3.3'}, + "dnac_debug": {"type": 'bool', "default": False}, + "dnac_log": {"type": 'bool', "default": False}, + "dnac_log_level": {"type": 'str', "default": 'WARNING'}, + "dnac_log_file_path": {"type": 'str', "default": 'dnac.log'}, + "dnac_log_append": {"type": 'bool', "default": True}, + "config_verify": {"type": 'bool', "default": False}, + 'dnac_api_task_timeout': {'type': 'int', "default": 1200}, + 'dnac_task_poll_interval': {'type': 'int', "default": 2}, + "config": {"type": 'list', "required": True, "elements": 'dict'}, + "state": {"default": 'merged', "choices": ['merged', 'deleted']}, + "validate_response_schema": {"type": 'bool', "default": True}, + } + + # Create an AnsibleModule object with argument specifications + module = AnsibleModule(argument_spec=element_spec, supports_check_mode=False) + ccc_ise_radius = IseRadiusIntegration(module) + state = ccc_ise_radius.params.get("state") + config_verify = ccc_ise_radius.params.get("config_verify") + if state not in ccc_ise_radius.supported_states: + ccc_ise_radius.status = "invalid" + ccc_ise_radius.msg = "State {0} is invalid".format(state) + ccc_ise_radius.check_return_status() + + ccc_ise_radius.validate_input().check_return_status() + + for config in ccc_ise_radius.config: + ccc_ise_radius.reset_values() + ccc_ise_radius.get_have(config).check_return_status() + if state != "deleted": + ccc_ise_radius.get_want(config).check_return_status() + ccc_ise_radius.get_diff_state_apply[state](config).check_return_status() + if config_verify: + ccc_ise_radius.verify_diff_state_apply[state](config).check_return_status() + + module.exit_json(**ccc_ise_radius.result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/issues_enrichment_details_info.py b/plugins/modules/issues_enrichment_details_info.py index 58d5c787cc..44359fb858 100644 --- a/plugins/modules/issues_enrichment_details_info.py +++ b/plugins/modules/issues_enrichment_details_info.py @@ -22,8 +22,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Issues GetIssueEnrichmentDetails description: Complete reference of the GetIssueEnrichmentDetails API. @@ -51,7 +51,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/issues_info.py b/plugins/modules/issues_info.py index f6131d2b88..61882040a2 100644 --- a/plugins/modules/issues_info.py +++ b/plugins/modules/issues_info.py @@ -24,11 +24,11 @@ startTime: description: - StartTime query parameter. Starting epoch time in milliseconds of query time window. - type: int + type: float endTime: description: - EndTime query parameter. Ending epoch time in milliseconds of query time window. - type: int + type: float siteId: description: - SiteId query parameter. Assurance UUID value of the site in the issue content. @@ -44,22 +44,22 @@ priority: description: - > - Priority query parameter. The issue's priority value (One of P1, P2, P3, or P4)(Use only when macAddress and - deviceId are not provided). + Priority query parameter. The issue's priority value P1, P2, P3, or P4 (case insensitive) (Use only when + macAddress and deviceId are not provided). type: str - aiDriven: + issueStatus: description: - - > - AiDriven query parameter. The issue's AI driven value (Yes or No)(Use only when macAddress and deviceId are - not provided). + - IssueStatus query parameter. The issue's status value ACTIVE, IGNORED, RESOLVED (case insensitive). type: str - issueStatus: + aiDriven: description: - - IssueStatus query parameter. The issue's status value (One of ACTIVE, IGNORED, RESOLVED). + - > + AiDriven query parameter. The issue's AI driven value YES or NO (case insensitive) (Use only when macAddress + and deviceId are not provided). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Issues Issues description: Complete reference of the Issues API. @@ -90,12 +90,11 @@ deviceId: string macAddress: string priority: string - aiDriven: string issueStatus: string + aiDriven: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -104,7 +103,7 @@ sample: > { "version": "string", - "totalCount": 0, + "totalCount": "string", "response": [ { "issueId": "string", @@ -112,7 +111,7 @@ "siteId": "string", "deviceId": "string", "deviceRole": "string", - "aiDriven": true, + "aiDriven": "string", "clientMac": "string", "issue_occurence_count": 0, "status": "string", diff --git a/plugins/modules/itsm_cmdb_sync_status_info.py b/plugins/modules/itsm_cmdb_sync_status_info.py index 2b3a47ea2b..ce064e7e37 100644 --- a/plugins/modules/itsm_cmdb_sync_status_info.py +++ b/plugins/modules/itsm_cmdb_sync_status_info.py @@ -34,8 +34,8 @@ - Date query parameter. Provide date in "YYYY-MM-DD" format. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for ITSM GetCMDBSyncStatus description: Complete reference of the GetCMDBSyncStatus API. @@ -65,7 +65,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/itsm_integration_events_failed_info.py b/plugins/modules/itsm_integration_events_failed_info.py index c2a6dca63b..8fe853b890 100644 --- a/plugins/modules/itsm_integration_events_failed_info.py +++ b/plugins/modules/itsm_integration_events_failed_info.py @@ -24,8 +24,8 @@ - InstanceId query parameter. Instance Id of the failed event as in the Runtime Dashboard. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for ITSM GetFailedITSMEvents description: Complete reference of the GetFailedITSMEvents API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/itsm_integration_events_retry.py b/plugins/modules/itsm_integration_events_retry.py index 64c97fe80e..2e45a0e399 100644 --- a/plugins/modules/itsm_integration_events_retry.py +++ b/plugins/modules/itsm_integration_events_retry.py @@ -24,8 +24,8 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for ITSM RetryIntegrationEvents description: Complete reference of the RetryIntegrationEvents API. @@ -53,7 +53,6 @@ - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/lan_automation_count_info.py b/plugins/modules/lan_automation_count_info.py index e275eaf2c8..3fff392e80 100644 --- a/plugins/modules/lan_automation_count_info.py +++ b/plugins/modules/lan_automation_count_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationSessionCount description: Complete reference of the LANAutomationSessionCount API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/lan_automation_create.py b/plugins/modules/lan_automation_create.py index b9c04f38d6..385a37e8c2 100644 --- a/plugins/modules/lan_automation_create.py +++ b/plugins/modules/lan_automation_create.py @@ -63,8 +63,8 @@ type: bool type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationStart description: Complete reference of the LANAutomationStart API. @@ -104,7 +104,6 @@ redistributeIsisToBgp: true """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/lan_automation_delete.py b/plugins/modules/lan_automation_delete.py index d31484c673..92b1eab287 100644 --- a/plugins/modules/lan_automation_delete.py +++ b/plugins/modules/lan_automation_delete.py @@ -20,8 +20,8 @@ description: Id path parameter. LAN Automation id can be obtained from /dna/intent/api/v1/lan-automation/status. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationStop description: Complete reference of the LANAutomationStop API. @@ -48,7 +48,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/lan_automation_log_by_serial_number_info.py b/plugins/modules/lan_automation_log_by_serial_number_info.py index fa75bec891..2af368cb43 100644 --- a/plugins/modules/lan_automation_log_by_serial_number_info.py +++ b/plugins/modules/lan_automation_log_by_serial_number_info.py @@ -13,7 +13,7 @@ - > Invoke this API to get the LAN Automation session logs for individual devices based on the given LAN Automation session id and device serial number. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -37,8 +37,8 @@ the remaining logs, please leave the query parameter blank. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationLogsForIndividualDevices description: Complete reference of the LANAutomationLogsForIndividualDevices API. @@ -69,7 +69,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/lan_automation_log_info.py b/plugins/modules/lan_automation_log_info.py index 6a8aa12919..d1fcde896b 100644 --- a/plugins/modules/lan_automation_log_info.py +++ b/plugins/modules/lan_automation_log_info.py @@ -24,18 +24,18 @@ offset: description: - Offset query parameter. Starting index of the LAN Automation session. Minimum value is 1. - type: int + type: float limit: description: - Limit query parameter. Number of LAN Automation sessions to be retrieved. Limit value can range between 1 to 10. - type: int + type: float id: description: - Id path parameter. LAN Automation session identifier. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationLog description: Complete reference of the LANAutomationLog API. @@ -83,7 +83,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/lan_automation_sessions_info.py b/plugins/modules/lan_automation_sessions_info.py new file mode 100644 index 0000000000..2b30d87322 --- /dev/null +++ b/plugins/modules/lan_automation_sessions_info.py @@ -0,0 +1,68 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: lan_automation_sessions_info +short_description: Information module for Lan Automation Sessions +description: +- Get all Lan Automation Sessions. +- Invoke this API to get the LAN Automation active session information. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for LAN Automation LANAutomationActiveSessions + description: Complete reference of the LANAutomationActiveSessions API. + link: https://developer.cisco.com/docs/dna-center/#!l-an-automation-active-sessions +notes: + - SDK Method used are + lan_automation.LanAutomation.lan_automation_active_sessions, + + - Paths used are + get /dna/intent/api/v1/lan-automation/sessions, + +""" + +EXAMPLES = r""" +- name: Get all Lan Automation Sessions + cisco.dnac.lan_automation_sessions_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "maxSupportedCount": "string", + "activeSessions": "string", + "activeSessionIds": [ + "string" + ] + }, + "version": "string" + } +""" diff --git a/plugins/modules/lan_automation_status_info.py b/plugins/modules/lan_automation_status_info.py index 3680a97ebb..3468d6bc20 100644 --- a/plugins/modules/lan_automation_status_info.py +++ b/plugins/modules/lan_automation_status_info.py @@ -24,18 +24,18 @@ offset: description: - Offset query parameter. Starting index of the LAN Automation session. Minimum value is 1. - type: int + type: float limit: description: - Limit query parameter. Number of LAN Automation sessions to be retrieved. Limit value can range between 1 to 10. - type: int + type: float id: description: - Id path parameter. LAN Automation session identifier. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for LAN Automation LANAutomationStatus description: Complete reference of the LANAutomationStatus API. @@ -83,7 +83,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -96,7 +95,7 @@ "id": "string", "discoveredDeviceSiteNameHierarchy": "string", "primaryDeviceManagmentIPAddress": "string", - "ipPoolList": [ + "ipPools": [ { "ipPoolName": "string", "ipPoolRole": "string" @@ -120,7 +119,12 @@ ] } ], - "redistributeIsisToBgp": true + "redistributeIsisToBgp": true, + "discoveryLevel": 0, + "discoveryTimeout": 0, + "discoveryDevices": [ + {} + ] } ], "version": "string" diff --git a/plugins/modules/lan_automation_update.py b/plugins/modules/lan_automation_update.py new file mode 100644 index 0000000000..fe63bf454e --- /dev/null +++ b/plugins/modules/lan_automation_update.py @@ -0,0 +1,78 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: lan_automation_update +short_description: Resource module for Lan Automation Update +description: +- Manage operation update of the resource Lan Automation Update. +- Invoke this API to stop LAN Automation and Update Loopback0 IP Address of Devices, discovered in the current session. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. LAN Automation id can be obtained from /dna/intent/api/v1/lan-automation/status. + type: str + payload: + description: Lan Automation Update's payload. + elements: dict + suboptions: + deviceManagementIPAddress: + description: Device Management IP Address. + type: str + newLoopback0IPAddress: + description: New Loopback0 IP Address from LAN pool of Device Discovery Site. + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for LAN Automation LANAutomationStopAndUpdateDevices + description: Complete reference of the LANAutomationStopAndUpdateDevices API. + link: https://developer.cisco.com/docs/dna-center/#!l-an-automation-stop-and-update-devices +notes: + - SDK Method used are + lan_automation.LanAutomation.lan_automation_stop_and_update_devices, + + - Paths used are + put /dna/intent/api/v1/lan-automation/{id}, + +""" + +EXAMPLES = r""" +- name: Update by id + cisco.dnac.lan_automation_update: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + id: string + payload: + - deviceManagementIPAddress: string + newLoopback0IPAddress: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/lan_automation_update_device.py b/plugins/modules/lan_automation_update_device.py new file mode 100644 index 0000000000..efcfcf90ec --- /dev/null +++ b/plugins/modules/lan_automation_update_device.py @@ -0,0 +1,122 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: lan_automation_update_device +short_description: Resource module for Lan Automation Updatedevice +description: +- Manage operation update of the resource Lan Automation Updatedevice. +- > + Invoke this API to perform a DAY-N update on LAN Automation-related devices. Supported features include Loopback0 + IP update, hostname update, link addition, and link deletion. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + feature: + description: Feature query parameter. Feature ID for the update. Supported feature + IDs include LOOPBACK0_IPADDRESS_UPDATE, HOSTNAME_UPDATE, LINK_ADD, and LINK_DELETE. + type: str + hostnameUpdateDevices: + description: Lan Automation Update Device's hostnameUpdateDevices. + elements: dict + suboptions: + deviceManagementIPAddress: + description: Device Management IP Address. + type: str + newHostName: + description: New hostname for the device. + type: str + type: list + linkUpdate: + description: Lan Automation Update Device's linkUpdate. + suboptions: + destinationDeviceInterfaceName: + description: Destination Device Interface Name. + type: str + destinationDeviceManagementIPAddress: + description: Destination Device Management IP Address. + type: str + ipPoolName: + description: Name of the IP LAN Pool, required for Link Add should be from discovery + site of source and destination device. + type: str + sourceDeviceInterfaceName: + description: Source Device Interface Name. + type: str + sourceDeviceManagementIPAddress: + description: Source Device Management IP Address. + type: str + type: dict + loopbackUpdateDeviceList: + description: Lan Automation Update Device's loopbackUpdateDeviceList. + elements: dict + suboptions: + deviceManagementIPAddress: + description: Device Management IP Address. + type: str + newLoopback0IPAddress: + description: New Loopback0 IP Address from LAN Pool of Device Discovery Site(Shared + pool should not be used). + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for LAN Automation LANAutomationDeviceUpdate + description: Complete reference of the LANAutomationDeviceUpdate API. + link: https://developer.cisco.com/docs/dna-center/#!l-an-automation-device-update +notes: + - SDK Method used are + lan_automation.LanAutomation.lan_automation_device_update, + + - Paths used are + put /dna/intent/api/v1/lan-automation/updateDevice, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.lan_automation_updateDevice: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + feature: string + hostnameUpdateDevices: + - deviceManagementIPAddress: string + newHostName: string + linkUpdate: + destinationDeviceInterfaceName: string + destinationDeviceManagementIPAddress: string + ipPoolName: string + sourceDeviceInterfaceName: string + sourceDeviceManagementIPAddress: string + loopbackUpdateDeviceList: + - deviceManagementIPAddress: string + newLoopback0IPAddress: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/lan_automation_update_v2.py b/plugins/modules/lan_automation_update_v2.py new file mode 100644 index 0000000000..1c56e63c49 --- /dev/null +++ b/plugins/modules/lan_automation_update_v2.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: lan_automation_update_v2 +short_description: Resource module for Lan Automation Update V2 +description: +- Manage operation update of the resource Lan Automation Update V2. +- > + Invoke this API to stop LAN Automation and update device parameters such as Loopback0 IP address and/or hostname + discovered in the current session. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. LAN Automation id can be obtained from /dna/intent/api/v1/lan-automation/status. + type: str + payload: + description: Lan Automation Update V2's payload. + elements: dict + suboptions: + deviceManagementIPAddress: + description: Device Management IP Address. + type: str + newHostName: + description: New hostname to be assigned to the device. + type: str + newLoopback0IPAddress: + description: New Loopback0 IP Address from LAN pool of Device Discovery Site. + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for LAN Automation LANAutomationStopAndUpdateDevicesV2 + description: Complete reference of the LANAutomationStopAndUpdateDevicesV2 API. + link: https://developer.cisco.com/docs/dna-center/#!l-an-automation-stop-and-update-devices-v-2 +notes: + - SDK Method used are + lan_automation.LanAutomation.lan_automation_stop_and_update_devices_v2, + + - Paths used are + put /dna/intent/api/v2/lan-automation/{id}, + +""" + +EXAMPLES = r""" +- name: Update by id + cisco.dnac.lan_automation_update_v2: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + id: string + payload: + - deviceManagementIPAddress: string + newHostName: string + newLoopback0IPAddress: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/lan_automation_v2.py b/plugins/modules/lan_automation_v2.py new file mode 100644 index 0000000000..65477319ec --- /dev/null +++ b/plugins/modules/lan_automation_v2.py @@ -0,0 +1,166 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: lan_automation_v2 +short_description: Resource module for Lan Automation V2 +description: +- Manage operation create of the resource Lan Automation V2. +- > + Invoke V2 LAN Automation Start API, which supports optional auto-stop processing feature based on the provided + timeout or a specific device list, or both. The stop processing will be executed automatically when either of the + cases is satisfied, without specifically calling the stop API. The V2 API behaves similarly to V1 if no timeout or + device list is provided, and the user needs to call the stop API for LAN Automation stop processing. With the V2 + API, the user can also specify the level up to which the devices can be LAN automated. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + payload: + description: Lan Automation V2's payload. + elements: dict + suboptions: + discoveredDeviceSiteNameHierarchy: + description: Discovered device site name. + type: str + discoveryDevices: + description: Lan Automation V2's discoveryDevices. + elements: dict + suboptions: + deviceHostName: + description: Hostname of the device. + type: str + deviceManagementIPAddress: + description: Management IP Address of the device. + type: str + deviceSerialNumber: + description: Serial number of the device. + type: str + deviceSiteNameHierarchy: + description: "Site name hierarchy for the device, must be a child site of\ + \ the discoveredDeviceSiteNameHierarchy or same if it\u2019s not area\ + \ type." + type: str + type: list + discoveryLevel: + description: Level below primary seed device upto which the new devices will + be LAN Automated by this session, level + seed = tier. Supported range for + level is 1-5, default level is 2. + type: int + discoveryTimeout: + description: Discovery timeout in minutes. Until this time, the stop processing + will not be triggered. Any device contacting after the provided discovery + timeout will not be processed, and a device reset and reload will be attempted + to bring it back to the PnP agent state before process completion. The supported + timeout range is in minutes 20-10080. If both timeout and discovery devices + list are provided, the stop processing will be attempted whichever happens + earlier. Users can always use the LAN Automation delete API to force stop + processing. + type: int + hostNameFileId: + description: Use /dna/intent/api/v1/file/namespace/nw_orch API to get the file + ID for the already uploaded file in the nw_orch namespace. + type: str + hostNamePrefix: + description: Host name prefix assigned to the discovered device. + type: str + ipPools: + description: Lan Automation V2's ipPools. + elements: dict + suboptions: + ipPoolName: + description: Name of the IP pool. + type: str + ipPoolRole: + description: Role of the IP pool. Supported roles are MAIN_POOL and PHYSICAL_LINK_POOL. + type: str + type: list + isisDomainPwd: + description: IS-IS domain password in plain text. + type: str + multicastEnabled: + description: Enable underlay native multicast. + type: bool + peerDeviceManagmentIPAddress: + description: Peer seed management IP address. + type: str + primaryDeviceInterfaceNames: + description: The list of interfaces on primary seed via which the discovered + devices are connected. + elements: str + type: list + primaryDeviceManagmentIPAddress: + description: Primary seed management IP address. + type: str + redistributeIsisToBgp: + description: Advertise LAN Automation summary route into BGP. + type: bool + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for LAN Automation LANAutomationStartV2 + description: Complete reference of the LANAutomationStartV2 API. + link: https://developer.cisco.com/docs/dna-center/#!l-an-automation-start-v-2 +notes: + - SDK Method used are + lan_automation.LanAutomation.lan_automation_start_v2, + + - Paths used are + post /dna/intent/api/v2/lan-automation, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.lan_automation_v2: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + payload: + - discoveredDeviceSiteNameHierarchy: string + discoveryDevices: + - deviceHostName: string + deviceManagementIPAddress: string + deviceSerialNumber: string + deviceSiteNameHierarchy: string + discoveryLevel: 0 + discoveryTimeout: 0 + hostNameFileId: string + hostNamePrefix: string + ipPools: + - ipPoolName: string + ipPoolRole: string + isisDomainPwd: string + multicastEnabled: true + peerDeviceManagmentIPAddress: string + primaryDeviceInterfaceNames: + - string + primaryDeviceManagmentIPAddress: string + redistributeIsisToBgp: true + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/license_device_count_info.py b/plugins/modules/license_device_count_info.py index 0ec3976ac0..56db9d1ad9 100644 --- a/plugins/modules/license_device_count_info.py +++ b/plugins/modules/license_device_count_info.py @@ -40,15 +40,15 @@ - Smart_account_id query parameter. Smart account id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses DeviceCountDetails2 - description: Complete reference of the DeviceCountDetails2 API. - link: https://developer.cisco.com/docs/dna-center/#!device-count-details-2 +- name: Cisco DNA Center documentation for Licenses DeviceCountDetails + description: Complete reference of the DeviceCountDetails API. + link: https://developer.cisco.com/docs/dna-center/#!device-count-details notes: - SDK Method used are - licenses.Licenses.device_count_details2, + licenses.Licenses.device_count_details, - Paths used are get /dna/intent/api/v1/licenses/device/count, @@ -74,7 +74,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/license_device_deregistration.py b/plugins/modules/license_device_deregistration.py index ddf70df119..3d99685f1a 100644 --- a/plugins/modules/license_device_deregistration.py +++ b/plugins/modules/license_device_deregistration.py @@ -21,15 +21,15 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses DeviceDeregistration2 - description: Complete reference of the DeviceDeregistration2 API. - link: https://developer.cisco.com/docs/dna-center/#!device-deregistration-2 +- name: Cisco DNA Center documentation for Licenses DeviceDeregistration + description: Complete reference of the DeviceDeregistration API. + link: https://developer.cisco.com/docs/dna-center/#!device-deregistration notes: - SDK Method used are - licenses.Licenses.device_deregistration2, + licenses.Licenses.device_deregistration, - Paths used are put /dna/intent/api/v1/licenses/smartAccount/virtualAccount/deregister, @@ -50,7 +50,6 @@ - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/license_device_license_details_info.py b/plugins/modules/license_device_license_details_info.py index 965c577e36..0b5dc7050a 100644 --- a/plugins/modules/license_device_license_details_info.py +++ b/plugins/modules/license_device_license_details_info.py @@ -24,15 +24,15 @@ - Device_uuid path parameter. Id of device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses DeviceLicenseDetails2 - description: Complete reference of the DeviceLicenseDetails2 API. - link: https://developer.cisco.com/docs/dna-center/#!device-license-details-2 +- name: Cisco DNA Center documentation for Licenses DeviceLicenseDetails + description: Complete reference of the DeviceLicenseDetails API. + link: https://developer.cisco.com/docs/dna-center/#!device-license-details notes: - SDK Method used are - licenses.Licenses.device_license_details2, + licenses.Licenses.device_license_details, - Paths used are get /dna/intent/api/v1/licenses/device/{device_uuid}/details, @@ -54,70 +54,66 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: list - elements: dict + type: dict sample: > - [ - { - "device_uuid": "string", - "site": "string", - "model": "string", - "license_mode": "string", - "is_license_expired": true, - "software_version": "string", - "network_license": "string", - "evaluation_license_expiry": "string", - "device_name": "string", - "device_type": "string", - "dna_level": "string", - "virtual_account_name": "string", - "ip_address": "string", - "mac_address": "string", - "sntc_status": "string", - "feature_license": [ - "string" - ], - "has_sup_cards": true, - "udi": "string", - "stacked_devices": [ + { + "device_uuid": "string", + "site": "string", + "model": "string", + "license_mode": "string", + "is_license_expired": true, + "software_version": "string", + "network_license": "string", + "evaluation_license_expiry": "string", + "device_name": "string", + "device_type": "string", + "dna_level": "string", + "virtual_account_name": "string", + "ip_address": "string", + "mac_address": "string", + "sntc_status": "string", + "feature_license": [ + "string" + ], + "has_sup_cards": true, + "udi": "string", + "stacked_devices": [ + { + "mac_address": "string", + "id": 0, + "role": "string", + "serial_number": "string" + } + ], + "is_stacked_device": true, + "access_points": [ + { + "ap_type": "string", + "count": "string" + } + ], + "chassis_details": { + "board_serial_number": "string", + "modules": [ { - "mac_address": "string", - "id": "string", - "role": "string", - "serial_number": "string" + "module_type": "string", + "module_name": "string", + "serial_number": "string", + "id": 0 } ], - "is_stacked_device": true, - "access_points": [ + "supervisor_cards": [ { - "ap_type": "string", - "count": "string" + "serial_number": "string", + "supervisor_card_type": "string", + "status": "string" } ], - "chassis_details": { - "board_serial_number": "string", - "modules": [ - { - "module_type": "string", - "module_name": "string", - "serial_number": "string", - "id": "string" - } - ], - "supervisor_cards": [ - { - "serial_number": "string", - "supervisor_card_type": "string", - "status": "string" - } - ], - "port": 0 - } + "port": 0 } - ] + } """ diff --git a/plugins/modules/license_device_license_summary_info.py b/plugins/modules/license_device_license_summary_info.py index c2806d39a1..6c6f29f64f 100644 --- a/plugins/modules/license_device_license_summary_info.py +++ b/plugins/modules/license_device_license_summary_info.py @@ -22,7 +22,7 @@ page_number: description: - Page_number query parameter. Page number of response. - type: int + type: float order: description: - Order query parameter. Sorting order. @@ -33,19 +33,22 @@ type: str dna_level: description: - - Dna_level query parameter. Device Cisco DNA license level. + - Dna_level query parameter. Device Cisco DNA license level. The valid values are Advantage, Essentials. type: str device_type: description: - - Device_type query parameter. Type of device. + - Device_type query parameter. Type of device. The valid values are Routers, Switches and Hubs, Wireless Controller. type: str limit: description: - Limit query parameter. - type: int + type: float registration_status: description: - - Registration_status query parameter. Smart license registration status of device. + - > + Registration_status query parameter. Smart license registration status of device. The valid values are + Unknown, NA, Unregistered, Registered, Registration_expired, Reservation_in_progress, Registered_slr, + Registered_plr, Registered_satellite. type: str virtual_account_name: description: @@ -54,21 +57,21 @@ smart_account_id: description: - Smart_account_id query parameter. Id of smart account. - type: int + type: str device_uuid: description: - Device_uuid query parameter. Id of device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses DeviceLicenseSummary2 - description: Complete reference of the DeviceLicenseSummary2 API. - link: https://developer.cisco.com/docs/dna-center/#!device-license-summary-2 +- name: Cisco DNA Center documentation for Licenses DeviceLicenseSummary + description: Complete reference of the DeviceLicenseSummary API. + link: https://developer.cisco.com/docs/dna-center/#!device-license-summary notes: - SDK Method used are - licenses.Licenses.device_license_summary2, + licenses.Licenses.device_license_summary, - Paths used are get /dna/intent/api/v1/licenses/device/summary, @@ -94,56 +97,57 @@ limit: 0 registration_status: string virtual_account_name: string - smart_account_id: 0 + smart_account_id: string device_uuid: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: list - elements: dict + type: dict sample: > - [ - { - "authorization_status": "string", - "last_updated_time": "string", - "is_performance_allowed": true, - "sle_auth_code": "string", - "throughput_level": "string", - "hsec_status": "string", - "device_uuid": "string", - "site": "string", - "total_access_point_count": 0, - "model": "string", - "is_wireless_capable": true, - "registration_status": "string", - "sle_state": "string", - "performance_license": "string", - "license_mode": "string", - "is_license_expired": true, - "software_version": "string", - "reservation_status": "string", - "is_wireless": true, - "network_license": "string", - "evaluation_license_expiry": "string", - "wireless_capable_network_license": "string", - "device_name": "string", - "device_type": "string", - "dna_level": "string", - "virtual_account_name": "string", - "last_successful_rum_usage_upload_time": "string", - "ip_address": "string", - "wireless_capable_dna_license": "string", - "mac_address": "string", - "customer_tag1": "string", - "customer_tag2": "string", - "customer_tag3": "string", - "customer_tag4": "string", - "smart_account_name": "string" - } - ] + { + "response": [ + { + "authorization_status": "string", + "last_updated_time": "string", + "is_performance_allowed": true, + "sle_auth_code": "string", + "throughput_level": "string", + "hsec_status": "string", + "device_uuid": "string", + "site": "string", + "total_access_point_count": 0, + "model": "string", + "is_wireless_capable": true, + "registration_status": "string", + "sle_state": "string", + "performance_license": "string", + "license_mode": "string", + "is_license_expired": true, + "software_version": "string", + "reservation_status": "string", + "is_wireless": true, + "network_license": "string", + "evaluation_license_expiry": "string", + "wireless_capable_network_license": "string", + "device_name": "string", + "device_type": "string", + "dna_level": "string", + "virtual_account_name": "string", + "last_successful_rum_usage_upload_time": "string", + "ip_address": "string", + "wireless_capable_dna_license": "string", + "mac_address": "string", + "customer_tag1": "string", + "customer_tag2": "string", + "customer_tag3": "string", + "customer_tag4": "string", + "smart_account_name": "string" + } + ], + "version": "string" + } """ diff --git a/plugins/modules/license_device_registration.py b/plugins/modules/license_device_registration.py index de878f7908..19d485aec2 100644 --- a/plugins/modules/license_device_registration.py +++ b/plugins/modules/license_device_registration.py @@ -24,15 +24,15 @@ description: Virtual_account_name path parameter. Name of virtual account. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses DeviceRegistration2 - description: Complete reference of the DeviceRegistration2 API. - link: https://developer.cisco.com/docs/dna-center/#!device-registration-2 +- name: Cisco DNA Center documentation for Licenses DeviceRegistration + description: Complete reference of the DeviceRegistration API. + link: https://developer.cisco.com/docs/dna-center/#!device-registration notes: - SDK Method used are - licenses.Licenses.device_registration2, + licenses.Licenses.device_registration, - Paths used are put /dna/intent/api/v1/licenses/smartAccount/virtualAccount/{virtual_account_name}/register, @@ -54,7 +54,6 @@ virtual_account_name: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/license_smart_account_details_info.py b/plugins/modules/license_smart_account_details_info.py index 70685c2ed3..c0b031bce2 100644 --- a/plugins/modules/license_smart_account_details_info.py +++ b/plugins/modules/license_smart_account_details_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Licenses SmartAccountDetails description: Complete reference of the SmartAccountDetails API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/license_term_details_info.py b/plugins/modules/license_term_details_info.py index d0bf73d4de..04d53b5d2c 100644 --- a/plugins/modules/license_term_details_info.py +++ b/plugins/modules/license_term_details_info.py @@ -34,15 +34,15 @@ - Device_type query parameter. Type of device like router, switch, wireless or ise. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses LicenseTermDetails2 - description: Complete reference of the LicenseTermDetails2 API. - link: https://developer.cisco.com/docs/dna-center/#!license-term-details-2 +- name: Cisco DNA Center documentation for Licenses LicenseTermDetails + description: Complete reference of the LicenseTermDetails API. + link: https://developer.cisco.com/docs/dna-center/#!license-term-details notes: - SDK Method used are - licenses.Licenses.license_term_details2, + licenses.Licenses.license_term_details, - Paths used are get /dna/intent/api/v1/licenses/term/smartAccount/{smart_account_id}/virtualAccount/{virtual_account_name}, @@ -66,7 +66,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/license_usage_details_info.py b/plugins/modules/license_usage_details_info.py index 3fd4d54665..160d4decb2 100644 --- a/plugins/modules/license_usage_details_info.py +++ b/plugins/modules/license_usage_details_info.py @@ -34,15 +34,15 @@ - Device_type query parameter. Type of device like router, switch, wireless or ise. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses LicenseUsageDetails2 - description: Complete reference of the LicenseUsageDetails2 API. - link: https://developer.cisco.com/docs/dna-center/#!license-usage-details-2 +- name: Cisco DNA Center documentation for Licenses LicenseUsageDetails + description: Complete reference of the LicenseUsageDetails API. + link: https://developer.cisco.com/docs/dna-center/#!license-usage-details notes: - SDK Method used are - licenses.Licenses.license_usage_details2, + licenses.Licenses.license_usage_details, - Paths used are get /dna/intent/api/v1/licenses/usage/smartAccount/{smart_account_id}/virtualAccount/{virtual_account_name}, @@ -66,7 +66,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -109,6 +108,24 @@ "license_count": 0 } ] + }, + "purchased_ise_license": { + "total_license_count": 0, + "license_count_by_type": [ + { + "license_type": "string", + "license_count": 0 + } + ] + }, + "used_ise_license": { + "total_license_count": 0, + "license_count_by_type": [ + { + "license_type": "string", + "license_count": 0 + } + ] } } """ diff --git a/plugins/modules/license_virtual_account_change.py b/plugins/modules/license_virtual_account_change.py index 762e015401..fd3a32793a 100644 --- a/plugins/modules/license_virtual_account_change.py +++ b/plugins/modules/license_virtual_account_change.py @@ -27,15 +27,15 @@ description: Virtual_account_name path parameter. Name of target virtual account. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses ChangeVirtualAccount2 - description: Complete reference of the ChangeVirtualAccount2 API. - link: https://developer.cisco.com/docs/dna-center/#!change-virtual-account-2 +- name: Cisco DNA Center documentation for Licenses ChangeVirtualAccount + description: Complete reference of the ChangeVirtualAccount API. + link: https://developer.cisco.com/docs/dna-center/#!change-virtual-account notes: - SDK Method used are - licenses.Licenses.change_virtual_account2, + licenses.Licenses.change_virtual_account, - Paths used are post /dna/intent/api/v1/licenses/smartAccount/{smart_account_id}/virtualAccount/{virtual_account_name}/device/transfer, @@ -58,7 +58,6 @@ virtual_account_name: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/license_virtual_account_details_info.py b/plugins/modules/license_virtual_account_details_info.py index 72a2f1041a..73e9e9b26d 100644 --- a/plugins/modules/license_virtual_account_details_info.py +++ b/plugins/modules/license_virtual_account_details_info.py @@ -24,15 +24,15 @@ - Smart_account_id path parameter. Id of smart account. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Licenses VirtualAccountDetails2 - description: Complete reference of the VirtualAccountDetails2 API. - link: https://developer.cisco.com/docs/dna-center/#!virtual-account-details-2 +- name: Cisco DNA Center documentation for Licenses VirtualAccountDetails + description: Complete reference of the VirtualAccountDetails API. + link: https://developer.cisco.com/docs/dna-center/#!virtual-account-details notes: - SDK Method used are - licenses.Licenses.virtual_account_details2, + licenses.Licenses.virtual_account_details, - Paths used are get /dna/intent/api/v1/licenses/smartAccount/{smart_account_id}/virtualAccounts, @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/maps_export.py b/plugins/modules/maps_export.py new file mode 100644 index 0000000000..59301d0706 --- /dev/null +++ b/plugins/modules/maps_export.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: maps_export +short_description: Resource module for Maps Export +description: +- Manage operation create of the resource Maps Export. +- Allows exporting a Map archive in an XML interchange format along with the associated images. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + siteHierarchyUuid: + description: SiteHierarchyUuid path parameter. The site hierarchy element UUID to + export, all child elements starting at this hierarchy element will be included. + Limited to a hierarchy that contains 500 or fewer maps. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites ExportMapArchive + description: Complete reference of the ExportMapArchive API. + link: https://developer.cisco.com/docs/dna-center/#!export-map-archive +notes: + - SDK Method used are + sites.Sites.export_map_archive, + + - Paths used are + post /dna/intent/api/v1/maps/export/{siteHierarchyUuid}, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.maps_export: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + siteHierarchyUuid: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/maps_import.py b/plugins/modules/maps_import.py new file mode 100644 index 0000000000..4da87d4617 --- /dev/null +++ b/plugins/modules/maps_import.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: maps_import +short_description: Resource module for Maps Import +description: +- Manage operation delete of the resource Maps Import. +- > + Cancels a previously initatied import, allowing the system to cleanup cached resources about that import data, and + ensures the import cannot accidentally be performed / approved at a later time. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + importContextUuid: + description: ImportContextUuid path parameter. The unique import context UUID given + by a previous call to Start Import API. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites ImportMapArchiveCancelAnImport + description: Complete reference of the ImportMapArchiveCancelAnImport API. + link: https://developer.cisco.com/docs/dna-center/#!import-map-archive-cancel-an-import +notes: + - SDK Method used are + sites.Sites.import_map_archive_cancel_an_import, + + - Paths used are + delete /dna/intent/api/v1/maps/import/{importContextUuid}, + +""" + +EXAMPLES = r""" +- name: Delete by id + cisco.dnac.maps_import: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + importContextUuid: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + {} +""" diff --git a/plugins/modules/maps_import_perform.py b/plugins/modules/maps_import_perform.py new file mode 100644 index 0000000000..e3a0c13362 --- /dev/null +++ b/plugins/modules/maps_import_perform.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: maps_import_perform +short_description: Resource module for Maps Import Perform +description: +- Manage operation create of the resource Maps Import Perform. +- > + For a previously initatied import, approves the import to be performed, accepting that data loss may occur. A Map + import will fully replace existing Maps data for the sites defined in the archive. The Map Archive Import Status + API /maps/import/${contextUuid}/status should always be checked to validate the pre-import validation output prior + to performing the import. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + importContextUuid: + description: ImportContextUuid path parameter. The unique import context UUID given + by a previous call of Start Import API. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites ImportMapArchivePerformImport + description: Complete reference of the ImportMapArchivePerformImport API. + link: https://developer.cisco.com/docs/dna-center/#!import-map-archive-perform-import +notes: + - SDK Method used are + sites.Sites.import_map_archive_perform_import, + + - Paths used are + post /dna/intent/api/v1/maps/import/{importContextUuid}/perform, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.maps_import_perform: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + importContextUuid: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + {} +""" diff --git a/plugins/modules/maps_import_start.py b/plugins/modules/maps_import_start.py new file mode 100644 index 0000000000..3cca05d170 --- /dev/null +++ b/plugins/modules/maps_import_start.py @@ -0,0 +1,56 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: maps_import_start +short_description: Resource module for Maps Import Start +description: +- Manage operation create of the resource Maps Import Start. +- > + Initiates a map archive import of a tar.gz file. The archive must consist of one xmlDir/MapsImportExport.xml map + descriptor file, and 1 or more images for the map areas nested under /images folder. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: {} +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites ImportMapArchiveStartImport + description: Complete reference of the ImportMapArchiveStartImport API. + link: https://developer.cisco.com/docs/dna-center/#!import-map-archive-start-import +notes: + - SDK Method used are + sites.Sites.import_map_archive_start_import, + + - Paths used are + post /dna/intent/api/v1/maps/import/start, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.maps_import_start: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: str + sample: > + "'string'" +""" diff --git a/plugins/modules/maps_import_status_info.py b/plugins/modules/maps_import_status_info.py new file mode 100644 index 0000000000..c8004add60 --- /dev/null +++ b/plugins/modules/maps_import_status_info.py @@ -0,0 +1,117 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: maps_import_status_info +short_description: Information module for Maps Import Status +description: +- Get all Maps Import Status. +- > + Gets the status of a map archive import operation. For a map archive import that has just been initiated, will + provide the result of validation of the archive and a pre-import preview of what will be performed if the import + is performed. Once an import is requested to be performed, this API will give the status of the import and upon + completion a post-import summary of what was performed by the operation. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + importContextUuid: + description: + - > + ImportContextUuid path parameter. The unique import context UUID given by a previous and recent call to + maps/import/start API. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites ImportMapArchiveImportStatus + description: Complete reference of the ImportMapArchiveImportStatus API. + link: https://developer.cisco.com/docs/dna-center/#!import-map-archive-import-status +notes: + - SDK Method used are + sites.Sites.import_map_archive_import_status, + + - Paths used are + get /dna/intent/api/v1/maps/import/{importContextUuid}/status, + +""" + +EXAMPLES = r""" +- name: Get all Maps Import Status + cisco.dnac.maps_import_status_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + importContextUuid: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "auditLog": { + "children": [ + {} + ], + "entitiesCount": [ + { + "key": 0 + } + ], + "entityName": "string", + "entityType": "string", + "errorEntitiesCount": [ + { + "key": 0 + } + ], + "errors": [ + { + "message": "string" + } + ], + "infos": [ + { + "message": "string" + } + ], + "matchingEntitiesCount": [ + { + "key": 0 + } + ], + "subTasksRootTaskId": "string", + "successfullyImportedFloors": [ + "string" + ], + "warnings": [ + { + "message": "string" + } + ] + }, + "status": "string", + "uuid": { + "leastSignificantBits": 0, + "mostSignificantBits": 0 + } + } +""" diff --git a/plugins/modules/maps_supported_access_points_info.py b/plugins/modules/maps_supported_access_points_info.py new file mode 100644 index 0000000000..0e535f65a9 --- /dev/null +++ b/plugins/modules/maps_supported_access_points_info.py @@ -0,0 +1,72 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: maps_supported_access_points_info +short_description: Information module for Maps Supported Access Points +description: +- Get all Maps Supported Access Points. +- Gets the list of supported access point types as well as valid antenna pattern names that can be used for each. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites MapsSupportedAccessPoints + description: Complete reference of the MapsSupportedAccessPoints API. + link: https://developer.cisco.com/docs/dna-center/#!maps-supported-access-points +notes: + - SDK Method used are + sites.Sites.maps_supported_access_points, + + - Paths used are + get /dna/intent/api/v1/maps/supported-access-points, + +""" + +EXAMPLES = r""" +- name: Get all Maps Supported Access Points + cisco.dnac.maps_supported_access_points_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "antennaPatterns": [ + { + "band": "string", + "names": [ + "string" + ] + } + ], + "apType": "string" + } + ] +""" diff --git a/plugins/modules/netconf_credential.py b/plugins/modules/netconf_credential.py index d75908aa6f..8551a1cb61 100644 --- a/plugins/modules/netconf_credential.py +++ b/plugins/modules/netconf_credential.py @@ -18,29 +18,30 @@ author: Rafael Campos (@racampos) options: comments: - description: Netconf Credential's comments. + description: Comments to identify the netconf credential. type: str credentialType: - description: Netconf Credential's credentialType. + description: Credential type to identify the application that uses the netconf credential. type: str description: - description: Netconf Credential's description. + description: Description for Netconf Credentials. type: str id: - description: Netconf Credential's id. + description: Id of the Netconf Credential in UUID format. type: str instanceTenantId: - description: Netconf Credential's instanceTenantId. + description: Deprecated. type: str instanceUuid: - description: Netconf Credential's instanceUuid. + description: Deprecated. type: str netconfPort: - description: Netconf Credential's netconfPort. + description: Netconf port on the device. Valid port should be in the range of 1 + to 65535. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateNetconfCredentials description: Complete reference of the CreateNetconfCredentials API. @@ -98,7 +99,6 @@ netconfPort: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_compliance_workflow_manager.py b/plugins/modules/network_compliance_workflow_manager.py new file mode 100644 index 0000000000..d0b716d5c1 --- /dev/null +++ b/plugins/modules/network_compliance_workflow_manager.py @@ -0,0 +1,1391 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Copyright (c) 2024, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +"""Ansible module to perform Network Compliance Operations on devices in Cisco Catalyst Center.""" +from __future__ import absolute_import, division, print_function + +__metaclass__ = type +__author__ = ("Rugvedi Kapse, Madhan Sankaranarayanan") + +DOCUMENTATION = r""" +--- +module: network_compliance_workflow_manager +short_description: Network Compliance module for managing network compliance tasks on reachable device(s) in Cisco Catalyst Center. +description: +- Perform compliance checks or sync configurations on reachable devices using IP Address(s) or Site. +- API to perform full compliance checks or specific category checks on reachable device(s). +- API to sync device configuration on device(s). +version_added: "6.14.0" +extends_documentation_fragment: + - cisco.dnac.workflow_manager_params +author: Rugvedi Kapse (@rukapse) + Madhan Sankaranarayanan (@madhansansel) +options: + config_verify: + description: Set to True to verify the Cisco Catalyst Center config after applying the playbook config. + type: bool + default: False + state: + description: State of Cisco Catalyst Center after module completion. + type: str + choices: [ merged ] + default: merged + config: + description: List of device details for running a compliance check or synchronizing device configuration. + type: list + elements: dict + required: True + suboptions: + ip_address_list: + description: List of IP addresses of devices to run a compliance check on or synchronize device configurations. + Either "ip_address_list" or "site_name" is required for module to execute. + If both "site_name" and "ip_address_list" are provided, operations are performed on devices that are present in both the + "ip_address_list" and the specified site. + (e.g. ["204.1.2.2", "204.1.2.5", "204.1.2.4"]) + type: list + elements: str + site_name: + description: When "site_name" is specified, the module executes the operation on all the devices located within the specified site. + This is a string value that should represent the complete hierarchical path of the site. + Either "site_name" or "ip_address_list" is required for module to execute. + If both "site_name" and "ip_address_list" are provided, operations are performed on devices that are present in both the + "ip_address_list" and the specified site. + (e.g. "Global/USA/San Francisco/Building_2/floor_1") + type: str + run_compliance: + description: Determines if a full compliance check should be triggered on the devices specified in the "ip_address_list" and/or "site_name". + if it is True then compliance will be triggered for all categories. + If it is False then compliance will be not be triggered even if run_compliance categories are provided. + type: bool + default: True + run_compliance_categories: + description: Specifying compliance categories allows you to trigger compliance checks only for the mentioned categories. + Category can have one or more values from among the options "INTENT", "RUNNING_CONFIG", "IMAGE", "PSIRT", "EOX", "NETWORK_SETTINGS". + Category "INTENT" is mapped to compliance types "NETWORK_SETTINGS", "NETWORK_PROFILE", "WORKFLOW", "FABRIC", "APPLICATION_VISIBILITY". + If "run_compliance" is False then compliance will be not be triggered even if "run_compliance_categories" are provided. + (e.g. ["INTENT", "RUNNING_CONFIG", "IMAGE", "PSIRT", "EOX", "NETWORK_SETTINGS"]) + type: list + elements: str + sync_device_config: + description: Determines whether to synchronize the device configuration on the devices specified in the "ip_address_list" and/or "site_name". + Sync device configuration, primarily addresses the status of the `RUNNING_CONFIG`. + If set to True, and if `RUNNING_CONFIG` status is non-compliant this operation would commit device running configuration + to startup by issuing "write memory" to device. + type: bool + default: False + +requirements: +- dnacentersdk == 2.7.0 +- python >= 3.9 +notes: + - SDK Methods used are + compliance.Compliance.run_compliance + compliance.Compliance.commit_device_configuration + task.Task.get_task_by_id + task.Task.get_task_tree + compliance.Compliance.get_compliance_detail + + - Paths used are + post /dna/intent/api/v1/compliance/ + post /dna/intent/api/v1/network-device-config/write-memory + get /dna/intent/api/v1/task/{taskId} + get /dna/intent/api/v1/task/{taskId}/tree + get /dna/intent/api/v1/compliance/detail +""" + +EXAMPLES = r""" +- name: Run Compliance check on device(s) using IP address list (run_compliance by default is True) + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - ip_address_list: ["204.1.2.2", "204.1.2.5", "204.1.2.4"] + +- name: Run Compliance check on device(s) using IP address list + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - ip_address_list: ["204.1.2.2", "204.1.2.5", "204.1.2.4"] + run_compliance: True + +- name: Run Compliance check on device(s) using Site + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + +- name: Run Compliance check on device(s) using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - ip_address_list: ["204.1.2.2", "204.1.2.5", "204.1.2.4"] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + +- name: Run Compliance check with specific categories on device(s) using IP address list + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - ip_address_list: ["204.1.2.2", "204.1.2.5", "204.1.2.4"] + run_compliance: True + run_compliance_categories: ["INTENT", "RUNNING_CONFIG", "IMAGE", "PSIRT"] + +- name: Run Compliance check with specific categories on device(s) using Site + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + run_compliance_categories: ["INTENT", "RUNNING_CONFIG", "IMAGE", "PSIRT"] + +- name: Run Compliance check with specific categories on device(s) using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - ip_address_list: ["204.1.2.2", "204.1.2.5", "204.1.2.4"] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + run_compliance_categories: ["INTENT", "RUNNING_CONFIG", "IMAGE", "PSIRT"] + +- name: Sync Device Configuration on device(s) using IP address list + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - site_name: "Global" + sync_device_config: True + run_compliance: False + +- name: Sync Device Configuration on device(s) using Site + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - site_name: "Global/USA/San Francisco/Building_1/floor_1" + sync_device_config: True + run_compliance: False + +- name: Sync Device Configuration on device(s) using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - ip_address_list: ["204.1.2.2", "204.1.2.5", "204.1.2.4"] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + sync_device_config: True + run_compliance: False + +- name: Run Compliance and Sync Device Configuration using both IP address list and Site + cisco.dnac.network_compliance_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log_level: "{{dnac_log_level}}" + dnac_log: False + config: + - ip_address_list: ["204.1.2.2", "204.1.2.5", "204.1.2.4"] + site_name: "Global/USA/San Francisco/Building_1/floor_1" + run_compliance: True + run_compliance_categories: ["INTENT", "RUNNING_CONFIG", "IMAGE", "PSIRT"] + sync_device_config: True +""" + +RETURN = r""" +#Case_1: Response when Network Compliance operations are performed successfully on device/s. +sample_response_2: + description: A dictionary with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: dict + sample: > + { + "status": "string", + "changed": bool, + "msg": "string" + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } + +#Case_2: Response when Error Occurs in performing Run Compliance or Sync Device Configuration operation on device/s. +sample_response_3: + description: A dictionary with the response returned by the Cisco Catalyst Center Python SDK + returned: always + type: dict + sample: > + { + "changed": bool, + "msg": "string" + } +""" + +import time +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.dnac.plugins.module_utils.dnac import ( + DnacBase, + validate_list_of_dicts +) + + +class NetworkCompliance(DnacBase): + """Class containing member attributes for network_compliance_workflow_manager module""" + + def __init__(self, module): + """ + Initialize an instance of the class. + Parameters: + - module: The module associated with the class instance. + Returns: + The method does not return a value. + """ + + super().__init__(module) + + def validate_input(self): + """ + Validate the fields provided in the playbook against a predefined specification + to ensure they adhere to the expected structure and data types. + Parameters: + state (optional): A state parameter that can be used to customize validation + based on different conditions. + Returns: + object: An instance of the class with updated attributes: + - self.msg: A message describing the validation result. + - self.status: The status of the validation (either "success" or "failed"). + - self.validated_config: If successful, a validated version of the "config" parameter. + Description: + This method validates the fields provided in the playbook against a predefined specification. + It checks if the required fields are present and if their data types match the expected types. + If any parameter is found to be invalid, it logs an error message and sets the validation status to "failed". + If the validation is successful, it logs a success message and returns an instance of the class + with the validated configuration. + """ + + if not self.config: + self.msg = "config not available in playbook for validation" + self.status = "success" + self.log(self.msg, "ERROR") + return self + + temp_spec = { + "ip_address_list": {"type": "list", "elements": "str", "required": False}, + "site_name": {"type": "str", "required": False}, + "run_compliance": {"type": "bool", "required": False, "default": True}, + "run_compliance_categories": {"type": "list", "elements": "str", "required": False}, + "sync_device_config": {"type": "bool", "required": False, "default": False}, + } + + # Validate device params + valid_temp, invalid_params = validate_list_of_dicts( + self.config, temp_spec + ) + + if invalid_params: + self.msg = "Invalid parameters in playbook: {0}".format(invalid_params) + self.log(self.msg, "ERROR") + self.status = "failed" + return self + + self.validated_config = valid_temp + + self.msg = "Successfully validated playbook configuration parameters using 'validated_input': {0}".format(str(valid_temp)) + self.log(self.msg, "INFO") + self.status = "success" + + return self + + def validate_ip4_address_list(self, ip_address_list): + """ + Validates the list of IPv4 addresses provided in the playbook. + Parameters: + ip_address_list (list): A list of IPv4 addresses to be validated. + Description: + This method iterates through each IP address in the list and checks if it is a valid IPv4 address. + If any address is found to be invalid, it logs an error message and fails. + After validating all IP addresses, it logs a success message. + """ + + for ip in ip_address_list: + if not self.is_valid_ipv4(ip): + self.msg = "IP address {0} is not valid".format(ip) + self.log(self.msg, "ERROR") + self.module.fail_json(self.msg) + + self.log("Successfully validated the IP address/es: {0}".format(ip_address_list), "DEBUG") + + def validate_run_compliance_paramters(self, mgmt_ip_instance_id_map, run_compliance, run_compliance_categories): + """ + Validate and prepare parameters for running compliance checks. + Parameters: + - mgmt_ip_instance_id_map (dict): A dictionary mapping management IP addresses to device instance IDs. + - run_compliance (bool or None): A boolean indicating whether to run compliance checks. + - run_compliance_categories (list): A list of compliance categories to check. + Returns: + tuple: A tuple containing two dictionaries: + - run_compliance_params: Parameters for running compliance checks. + - compliance_detail_params: Parameters for compliance detail. + Notes: + - This method prepares parameters for running compliance checks based on the provided inputs. + - If invalid categories are provided in `run_compliance_categories`, a `ValueError` is raised. + - If `run_compliance_categories` is provided and neither `run_compliance` nor `run_compliance_categories` is set, an error + is logged and the method fails. + - If `run_compliance` is set and `run_compliance_categories` is not, full compliance checks are triggered. + - If both `run_compliance` and `run_compliance_categories` are set, compliance checks are triggered for specific categories. + """ + run_compliance_params = {} + compliance_detail_params = {} + valid_categories = ["INTENT", "RUNNING_CONFIG", "IMAGE", "PSIRT", "EOX", "NETWORK_SETTINGS"] + + if run_compliance_categories: + # Validate the categories provided + if not all(category.upper() in valid_categories for category in run_compliance_categories): + msg = "Invalid category provided. Valid categories are {0}.".format(valid_categories) + self.log(msg, "ERROR") + self.module.fail_json(msg) + + if run_compliance: + # run_compliance_params + run_compliance_params["deviceUuids"] = list(mgmt_ip_instance_id_map.values()) + run_compliance_params["triggerFull"] = False + categories_copy = run_compliance_categories.copy() + run_compliance_params["categories"] = categories_copy + + # compliance_detail_params + compliance_detail_params["deviceUuids"] = ",".join(list(mgmt_ip_instance_id_map.values())) + compliance_types = run_compliance_categories + if "INTENT" in compliance_types: + compliance_types.remove("INTENT") + compliance_types.extend(["NETWORK_PROFILE", "APPLICATION_VISIBILITY", "WORKFLOW", "FABRIC", "NETWORK_SETTINGS"]) + compliance_types = list(set(compliance_types)) + compliance_detail_params["complianceType"] = "', '".join(compliance_types) + compliance_detail_params["complianceType"] = "'" + compliance_detail_params['complianceType'] + "'" + # Case when run_compliance_categories provided but run_compliance = False + else: + msg = "Since run_compliance is set to {0}, even though run_compliance_categories are provided {1}, ".format( + run_compliance, run_compliance_categories) + msg += "Run Compliance Check will not be executed." + self.log(msg, "WARNING") + + elif run_compliance: + # run_compliance_params + run_compliance_params["deviceUuids"] = list(mgmt_ip_instance_id_map.values()) + run_compliance_params["triggerFull"] = True + + # compliance_detail_params + compliance_detail_params["deviceUuids"] = ",".join(list(mgmt_ip_instance_id_map.values())) + + return run_compliance_params, compliance_detail_params + + def site_exists(self, site_name): + """ + Checks the existence of a site in Cisco Catalyst Center. + Parameters: + site_name (str): The name of the site to be checked. + Returns: + tuple: A tuple containing two values: + - site_exists (bool): Indicates whether the site exists (True) or not (False). + - site_id (str or None): The ID of the site if it exists, or None if the site is not found. + Description: + This method queries Cisco Catalyst Center to determine if a site with the provided name exists. + If the site is found, it sets "site_exists" to True and retrieves the site"s ID. + If the site does not exist, "site_exists" is set to False, and "site_id" is None. + If an exception occurs during the site lookup, an error message is logged, and the module fails. + """ + + site_exists = False + site_id = None + response = None + + # Attempt to retrieve site information from Catalyst Center + try: + response = self.dnac._exec( + family="sites", + function="get_site", + op_modifies=True, + params={"name": site_name}, + ) + self.log("Response received post 'get_site' API call: {0}".format(str(response)), "DEBUG") + + # Process the response if available + if response: + site = response.get("response") + site_id = site[0].get("id") + site_exists = True + else: + self.log("No response received from the 'get_site' API call.", "ERROR") + + except Exception as e: + # Log an error message and fail if an exception occurs + self.log("An error occurred while retrieving site details for Site '{0}' using 'get_site' API call: {1}".format(site_name, str(e)), "ERROR") + + if not site_exists: + msg = "An error occurred while retrieving site details for Site '{0}'. Please verify that the site exists.".format(site_name) + self.log(msg, "ERROR") + self.module.fail_json(msg=msg) + + return (site_exists, site_id) + + def get_device_ids_from_ip(self, ip_address_list): + """ + Retrieves the device IDs based on the provided list of IP addresses from Cisco Catalyst Center. + Parameters: + ip_address_list (list): A list of IP addresses of devices for which you want to retrieve the device IDs. + Returns: + dict: A dictionary mapping management IP addresses to their instance UUIDs. + Description: + This method queries Cisco Catalyst Center for device information using the provided IP addresses. + For each IP address in the list, it attempts to fetch the device information using the "get_device_list" API. + If the device is found and reachable, it extracts the device ID and maps it to the corresponding IP address. + If any error occurs during the process, it logs an error message and continues to the next IP address. + """ + + mgmt_ip_instance_id_map = {} + + # Iterate through the provided list of IP addresses + for device_ip in ip_address_list: + try: + # Query Cisco Catalyst Center for device information using the IP address + response = self.dnac._exec( + family="devices", + function="get_device_list", + op_modifies=True, + params={"managementIpAddress": device_ip} + ) + self.log("Response received post 'get_device_list' API call: {0} ".format(str(response)), "DEBUG") + + # Check if a valid response is received + if response.get("response"): + response = response.get("response") + if not response: + continue + for device_info in response: + if device_info["reachabilityStatus"] == "Reachable": + device_id = response[0]["id"] + mgmt_ip_instance_id_map[device_ip] = device_id + else: + # If unable to retrieve device information, log an error message + self.log("Unable to retrieve device information for {0}. Please ensure that the device exists and is reachable.".format(device_ip), "ERROR") + + except Exception as e: + # Log an error message if any exception occurs during the process + self.log("Error while fetching device ID for device: '{0}' from Cisco Catalyst Center: {1}".format(device_ip, str(e)), "ERROR") + + if not mgmt_ip_instance_id_map: + msg = "Error occurred while retrieving device details (Device UUID) using the 'get_device_list' API " + msg += "for the following device(s): {0}".format(ip_address_list) + self.log(msg, "ERROR") + self.module.fail_json(msg=msg) + + return mgmt_ip_instance_id_map + + def get_device_ids_from_site(self, site_name, site_id): + """ + Retrieves the management IP addresses and their corresponding instance UUIDs of devices associated with a specific site in Cisco Catalyst Center. + + Parameters: + site_name (str): The name of the site whose devices" information is to be retrieved. + site_id (str): The unique identifier of the site. + + Returns: + dict: A dictionary mapping management IP addresses to their instance UUIDs. + + Description: + This method queries Cisco Catalyst Center to fetch the list of devices associated with the provided site. + It then extracts the management IP addresses and their instance UUIDs from the response. + Devices that are not reachable are logged as critical errors, and the function fails. + If no reachable devices are found for the specified site, it logs an error message and fails. + + """ + mgmt_ip_instance_id_map = {} + + site_params = { + "site_id": site_id, + } + + # Attempt to retrieve device information associated with the site + try: + response = self.dnac._exec( + family="sites", + function="get_membership", + op_modifies=True, + params=site_params, + ) + self.log("Response received post 'get_membership' API Call: {0} ".format(str(response)), "DEBUG") + + # Process the response if available + if response: + response = response["device"] + # Iterate over the devices in the site membership + for item in response: + if item["response"]: + for item_dict in item["response"]: + # Check if the device is reachable + if item_dict["reachabilityStatus"] == "Reachable": + mgmt_ip_instance_id_map[item_dict["managementIpAddress"]] = item_dict["instanceUuid"] + else: + msg = "Unable to get deviceId for device {0} in site {1} as its status is {2}".format( + item["managementIpAddress"], site_name, item["reachabilityStatus"]) + self.log(msg, "CRITICAL") + self.module.fail_json(msg=msg) + else: + # If unable to retrieve device information, log an error message + self.log("No response received from API call to get membership information for site. {0}".format(site_name), "ERROR") + + except Exception as e: + # Log an error message if any exception occurs during the process + self.log("Unable to fetch the device(s) associated to the site '{0}' due to {1}".format(site_name, str(e)), "ERROR") + + if not mgmt_ip_instance_id_map: + msg = "Error retrieving device details using the 'get_membership' API from Site: {0}".format(site_name) + self.log(msg, "ERROR") + self.module.fail_json(msg=msg) + + return mgmt_ip_instance_id_map + + def get_device_id_list(self, ip_address_list, site_name): + """ + Get the list of unique device IDs for a specified list of management IP addresses or devices associated with a site + in Cisco Catalyst Center. + Parameters: + ip_address_list (list): The management IP addresses of devices for which you want to retrieve the device IDs. + site_name (str): The name of the site for which you want to retrieve the device IDs. + Returns: + dict: A dictionary mapping management IP addresses to device IDs for the specified devices. + Description: + This method queries Cisco Catalyst Center to retrieve the unique device IDs associated with devices having the + specified IP addresses or belonging to the specified site. + """ + + # Initialize a dictionary to store management IP addresses and their corresponding device IDs + mgmt_ip_instance_id_map = {} + + # Check if both site name and IP address list are provided + if site_name: + (site_exists, site_id) = self.site_exists(site_name) + if site_exists: + # Retrieve device IDs associated with devices in the site + site_mgmt_ip_instance_id_map = self.get_device_ids_from_site(site_name, site_id) + mgmt_ip_instance_id_map.update(site_mgmt_ip_instance_id_map) + + if ip_address_list: + # Retrieve device IDs associated with devices having specified IP addresses + iplist_mgmt_ip_instance_id_map = self.get_device_ids_from_ip(ip_address_list) + mgmt_ip_instance_id_map.update(iplist_mgmt_ip_instance_id_map) + + return mgmt_ip_instance_id_map + + def is_sync_required(self, modified_response, mgmt_ip_instance_id_map): + """ + Determine if synchronization of device configurations is required. + + Args: + modified_response (dict): A dictionary containing modified responses for each device. + mgmt_ip_instance_id_map (dict): A dictionary mapping management IP addresses to instance IDs. + + Returns: + tuple: A tuple containing a boolean indicating whether synchronization is required + and a message explaining the result. + + Note: + This method categorizes devices based on compliance status ("COMPLIANT", "NON_COMPLIANT", "OTHER") + and checks if synchronization is necessary. If all devices are "COMPLIANT", synchronization is not + required. If there are devices that are not "NON_COMPLIANT", synchronization is also not required. + """ + task_name = "Sync Device Configuration" + required = True + msg = "" + + # Validate if sync is required + self.log("Compliance Report for {0} operation for device(s) {1} : {2}".format( + task_name, list(mgmt_ip_instance_id_map.keys()), modified_response), "INFO") + + # Categorize the devices based on status - "COMPLIANT", "NON_COMPLIANT", "OTHER"(status other than COMPLIANT and NON_COMPLIANT) + categorized_devices = {"COMPLIANT": {}, "NON_COMPLIANT": {}, "OTHER": {}} + for ip_address, compliance_type in modified_response.items(): + status = compliance_type[0]["status"] + if status == "NON_COMPLIANT": + categorized_devices["NON_COMPLIANT"][ip_address] = compliance_type + elif status == "COMPLIANT": + categorized_devices["COMPLIANT"][ip_address] = compliance_type + else: + categorized_devices["OTHER"][ip_address] = compliance_type + + self.log("Devices Categorized based on Compliance status: {0}".format(categorized_devices), "INFO") + + # Validate if all devices are "COMPLIANT" - then sync not required + if len(categorized_devices["COMPLIANT"]) == len(mgmt_ip_instance_id_map): + msg = "Device(s) {0} are already compliant with the RUNNING_CONFIG compliance type. Therefore, {1} is not required.".format( + list(mgmt_ip_instance_id_map.keys()), task_name) + required = False + elif len(categorized_devices["NON_COMPLIANT"]) != len(mgmt_ip_instance_id_map): + required = False + msg = ("The operation {0} cannot be performed on one or more of the devices " + "{1} because the status of the RUNNING_CONFIG compliance type is not " + "as expected; it should be NON_COMPLIANT." + ).format(task_name, list(mgmt_ip_instance_id_map.keys())) + + return required, msg + + def get_want(self, config): + """ + Determines the desired state based on the provided configuration. + Parameters: + config (dict): The configuration specifying the desired state. + Returns: + dict: A dictionary containing the desired state parameters. + Description: + This method processes the provided configuration to determine the desired state. It validates the presence of + either "ip_address_list" or "site_name" and constructs parameters for running compliance checks and syncing + device configurations based on the provided configuration. It also logs the desired state for reference. + """ + + # Initialize parameters + run_compliance_params = {} + sync_device_config_params = {} + compliance_detail_params = {} + compliance_detail_params_sync = {} + compliance_details = {} + + # Store input parameters + ip_address_list = config.get("ip_address_list") + site_name = config.get("site_name") + run_compliance = config.get("run_compliance") + run_compliance_categories = config.get("run_compliance_categories") + sync_device_config = config.get("sync_device_config") + + # Validate either ip_address_list OR site_name is present + if not any([ip_address_list, site_name]): + msg = "ip_address_list is {0} and site_name is {1}. Either the ip_address_list or the site_name must be provided.".format( + ip_address_list, site_name) + self.log(msg, "ERROR") + self.module.fail_json(msg=msg) + + # Validate if a network compliance operation is present + if not any([run_compliance, run_compliance_categories, sync_device_config]): + msg = "No actions were requested. This network compliance module can perform the following tasks: Run Compliance Check or Sync Device Config." + self.log(msg, "ERROR") + self.module.fail_json(msg) + return self + + # Validate valid ip_addresses + if ip_address_list: + self.validate_ip4_address_list(ip_address_list) + # Remove Duplicates from list + ip_address_list = list(set(ip_address_list)) + + # Retrieve device ID list + mgmt_ip_instance_id_map = self.get_device_id_list(ip_address_list, site_name) + if not mgmt_ip_instance_id_map: + # Log an error message if mgmt_ip_instance_id_map is empty + msg = "Failed to retrieve device IDs for the provided IP addresses: {0} or site name: {1}.".format(ip_address_list, site_name) + self.log(msg, "ERROR") + self.module.fail_json(msg) + + # Run Compliance Paramters + run_compliance_params, compliance_detail_params = self.validate_run_compliance_paramters( + mgmt_ip_instance_id_map, run_compliance, run_compliance_categories) + + # Sync Device Configuration Parameters + if sync_device_config: + sync_device_config_params = { + "deviceId": list(mgmt_ip_instance_id_map.values()) + } + + compliance_detail_params_sync = { + "deviceUuid": ",".join(list(mgmt_ip_instance_id_map.values())), + "complianceType": "RUNNING_CONFIG" + } + + # Validate if Sync Device Configuration is required on the device(s) + response = self.get_compliance_detail(compliance_detail_params_sync) + if not response: + msg = "Error occurred when retrieving Compliance Report to identify if Sync Device Config Operation " + msg += "is required on device(s): {0}".format(list(mgmt_ip_instance_id_map.keys())) + self.log(msg) + self.module.fail_json(msg) + + compliance_details = self.modify_compliance_response(response, mgmt_ip_instance_id_map) + required, msg = self.is_sync_required(compliance_details, mgmt_ip_instance_id_map) + if not required: + self.log(msg, "ERROR") + self.module.fail_json(msg) + + # Construct the "want" dictionary containing the desired state parameters + want = {} + want = dict( + ip_address_list=ip_address_list, + site_name=site_name, + mgmt_ip_instance_id_map=mgmt_ip_instance_id_map, + run_compliance_params=run_compliance_params, + sync_device_config_params=sync_device_config_params, + compliance_detail_params=compliance_detail_params, + compliance_detail_params_sync=compliance_detail_params_sync, + compliance_details=compliance_details + ) + self.want = want + self.log("Desired State (want): {0}".format(str(self.want)), "INFO") + + return self + + def get_compliance_detail(self, compliance_detail_params): + """ + Execute the GET compliance detail operation. + Args: + compliance_detail_params (dict): A dictionary containing parameters for the compliance detail operation. + Returns: + dict: A dictionary containing details of the compliance detail response. + Returns None if there is an error. + """ + # Execute the GET compliance detial operation + try: + response = self.dnac_apply["exec"]( + family="compliance", + function="get_compliance_detail", + params=compliance_detail_params, + op_modifies=True + ) + self.log("Response received post 'get_compliance_detail' API call: {0}".format(str(response)), "DEBUG") + + if response: + response = response.response + else: + self.log("No response received from the 'get_compliance_detail' API call.", "ERROR") + return response + + # Log and handle any exceptions that occur during the execution + except Exception as e: + self.msg = "An error occurred while retrieving Compliance Details using 'get_compliance_detail' API call " + self.msg += "for {0}: {1}".format(compliance_detail_params, str(e)) + self.update_result("failed", False, self.msg, "ERROR") + self.check_return_status() + + def modify_compliance_response(self, response, mgmt_ip_instance_id_map): + """ + Modifies the compliance response by mapping device UUIDs to management IP addresses. + Parameters: + response (list of dict): The original compliance response. + mgmt_ip_instance_id_map (dict): Mapping of management IP addresses to instance IDs. + Returns: + dict: Modified compliance response with management IP addresses as keys. + Description: + This method takes the original compliance response and maps device UUIDs to their corresponding management + IP addresses using the provided mapping. It then constructs a modified response where each IP address is a key + associated with a list of compliance items related to that device. + """ + modified_response = {} + ip_address = None + + for item in response: + device_uuid = item.get("deviceUuid") + + # Find the corresponding management IP address for the device UUID + for ip, uuid in mgmt_ip_instance_id_map.items(): + if uuid == device_uuid: + ip_address = ip + break + + # If the IP address is found, add the item to the modified response + # If ip_address and item.get("status")!= "NOT_APPLICABLE": + if ip_address: + if ip_address not in modified_response: + modified_response[ip_address] = [] + modified_response[ip_address].append(item) + + return modified_response + + def run_compliance(self, run_compliance_params): + """ + Executes a compliance check operation in Cisco DNA Center. + Parameters: + run_compliance_params (dict): Parameters for running the compliance check. + Returns: + str or None: Task ID of the API task created, or None if unsuccessful. + Description: + This method initiates a compliance check operation in Cisco DNA Center by calling the "run_compliance" function + from the "compliance" family of APIs. It passes the provided parameters and updates the result accordingly. + """ + + # Execute the compliance check operation + try: + response = self.dnac_apply["exec"]( + family="compliance", + function="run_compliance", + params=run_compliance_params, + op_modifies=True, + ) + self.log("Response received post 'run_compliancee' API call is {0}".format(str(response)), "DEBUG") + + if response: + self.result.update(dict(response=response["response"])) + self.log("Task Id for the 'run_compliance' task is {0}".format(response.response.get("taskId")), "INFO") + return response.response.get("taskId") + else: + self.log("No response received from the 'run_compliance' API call.", "ERROR") + return None + + # Log and handle any exceptions that occur during the execution + except Exception as e: + self.msg = "An error occurred while executing the 'run_compliance' operation for {0}: {1}".format(run_compliance_params, str(e)) + self.update_result("failed", False, self.msg, "ERROR") + self.check_return_status() + + def sync_device_config(self, sync_device_config_params): + """ + Synchronize the device configuration using the specified parameters. + Parameters: + - sync_device_config_params (dict): Parameters for synchronizing the device configuration. + Returns: + task_id (str): The ID of the task created for the synchronization operation. + Note: + This method initiates the synchronization of device configurations by making an API call to the Cisco DNA Center. + It logs the response received from the API call and extracts the task ID from the response for further monitoring. + If an error occurs during the API call, it will be caught and logged. + """ + # Make an API call to synchronize device configuration + try: + response = self.dnac_apply["exec"]( + family="compliance", + function="commit_device_configuration", + params=sync_device_config_params, + op_modifies=True, + ) + self.log("Response received post 'commit_device_configuration' API call is {0}".format(str(response)), "DEBUG") + + if response: + self.result.update(dict(response=response["response"])) + self.log("Task Id for the 'commit_device_configuration' task is {0}".format(response.response.get("taskId")), "INFO") + # Return the task ID + return response.response.get("taskId") + else: + self.log("No response received from the 'commit_device_configuration' API call.", "ERROR") + return None + + # Log the error if an exception occurs during the API call + except Exception as e: + self.msg = "Error occurred while synchronizing device configuration for {0}: {1}".format(sync_device_config_params, str(e)) + self.update_result("failed", False, self.msg, "ERROR") + self.check_return_status() + + def get_task_status(self, task_id, task_name): + """ + Retrieve the status of a task by its ID. + Parameters: + - task_id (str): The ID of the task whose status is to be retrieved. + - task_name (str): The name of the task. + Returns: + response (dict): The response containing the status of the task. + Note: + This method makes an API call to retrieve the task status and logs the status information. + If an error occurs during the API call, it will be caught and logged. + """ + + # Make an API call to retrieve the task tree + try: + response = self.dnac_apply["exec"]( + family="task", + function="get_task_by_id", + params=dict(task_id=task_id), + op_modifies=True, + ) + self.log("Response received post 'get_task_by_id' API Call for the Task {0} with Task id {1} " + "is {2}".format(task_name, str(task_id), str(response)), "DEBUG") + + if response: + response = response.response + else: + self.log("No response received from the 'get_task_by_id' API call.", "CRITICAL") + return response + + # Log the error if an exception occurs during the API call + except Exception as e: + self.msg = "Error occurred while retrieving 'get_task_by_id' for Task {0} with Task id {1}: {2}".format(task_name, task_id, str(e)) + self.update_result("failed", False, self.msg, "ERROR") + self.check_return_status() + + def get_task_tree(self, task_id, task_name): + """ + Retrieve the tree of a task by its ID. + Parameters: + - task_id (str): The ID of the task whose status is to be retrieved. + - task_name (str): The name of the task. + Returns: + response (dict): The response containing the status of the task. + Note: + This method makes an API call to retrieve the task status and logs the status information. + If an error occurs during the API call, it will be caught and logged. + """ + + # Make an API call to retrieve the task status + try: + response = self.dnac_apply["exec"]( + family="task", + function="get_task_tree", + params=dict(task_id=task_id), + op_modifies=True, + ) + self.log("Response received post 'get_task_tree' API call for the Task {0} with Task id {1} " + "is {2}".format(task_name, str(task_id), str(response)), "DEBUG") + if response: + response = response.response + else: + self.log("No response received from the 'get_task_tree' API call.", "CRITICAL") + return response + + # Log the error if an exception occurs during the API call + except Exception as e: + self.msg = "Error occurred while retrieving 'get_task_tree' for Task {0} with task id {1}: {2}".format(task_name, task_id, str(e)) + self.update_result("failed", False, self.msg, "ERROR") + self.check_return_status() + + def update_result(self, status, changed, msg, log_level, data=None): + """ + Update the result of the operation with the provided status, message, and log level. + Parameters: + - status (str): The status of the operation ("success" or "failed"). + - changed (bool): Indicates whether the operation caused changes. + - msg (str): The message describing the result of the operation. + - log_level (str): The log level at which the message should be logged ("INFO", "ERROR", "CRITICAL", etc.). + - data (dict, optional): Additional data related to the operation result. + Returns: + self (object): An instance of the class. + Note: + - If the status is "failed", the "failed" key in the result dictionary will be set to True. + - If data is provided, it will be included in the result dictionary. + """ + + # Update the result attributes with the provided values + self.status = status + self.result["status"] = status + self.result["msg"] = msg + self.result["changed"] = changed + + # Log the message at the specified log level + self.log(msg, log_level) + + # If the status is "failed", set the "failed" key to True + if status == "failed": + self.result["failed"] = True + + # If additional data is provided, include it in the result dictionary + if data: + self.result["data"] = data + + return self + + def exit_while_loop(self, start_time, task_id, task_name, response): + """ + Check if the elapsed time exceeds the specified timeout period and exit the while loop if it does. + Parameters: + - start_time (float): The time when the while loop started. + - task_id (str): ID of the task being monitored. + - task_name (str): Name of the task being monitored. + - response (dict): Response received from the task status check. + Returns: + bool: True if the elapsed time exceeds the timeout period, False otherwise. + """ + + # If the elapsed time exceeds the timeout period + if time.time() - start_time > 360: + if response.get("data"): + # If there is data in the response, include it in the error message + self.msg = "Task {0} with task id {1} has not completed within the timeout period. Task Status: {2} ".format( + task_name, task_id, response.get("data")) + else: + # If there is no data in the response, generate a generic error message + self.msg = "Task {0} with task id {1} has not completed within the timeout period.".format( + task_name, task_id) + + # Update the result with failure status and log the error message + self.update_result("failed", False, self.msg, "ERROR") + return True + + return False + + def handle_error(self, task_name, mgmt_ip_instance_id_map, failure_reason=None): + """ + Handle error encountered during task execution. + Parameters: + - task_name (str): Name of the task being performed. + - mgmt_ip_instance_id_map (dict): Mapping of management IP addresses to instance IDs. + - failure_reason (str, optional): Reason for the failure, if available. + Returns: + self (object): An instance of the class used for interacting with Cisco Catalyst Center. + """ + + # If failure reason is provided, include it in the error message + if failure_reason: + self.msg = "An error occurred while performing {0} on device(s): {1}. The operation failed due to the following reason: {2}".format( + task_name, list(mgmt_ip_instance_id_map.keys()), failure_reason) + # If no failure reason is provided, generate a generic error message + else: + self.msg = "An error occurred while performing {0} on device(s): {1}".format( + task_name, list(mgmt_ip_instance_id_map.keys())) + + # Update the result with failure status and log the error message + self.update_result("failed", False, self.msg, "ERROR") + + return self + + def get_compliance_task_status(self, task_id, mgmt_ip_instance_id_map): + """ + This function retrieves the status of compliance check tasks in Cisco Catalyst Center. + Parameters: + - task_id: The ID of the compliance check task. + - mgmt_ip_instance_id_map: A mapping of management IP addresses to instance IDs. + Returns: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Description: + This function continuously checks the status of a compliance check task until completion. + It handles various scenarios such as task completion, task failure, or errors during execution. + Upon successful completion, it logs the modified compliance response and updates the result accordingly. + """ + + task_name = "Run Compliance Check" + start_time = time.time() + + while True: + response = self.get_task_status(task_id, task_name) + + # Check if response returned + if not response: + self.msg = "Error retrieving Task status for {0} with Task Id: {1}".format(task_name, task_id) + self.update_result("failed", False, self.msg, "ERROR") + break + + # Check if the elapsed time exceeds the timeout + if self.exit_while_loop(start_time, task_id, task_name, response): + break + + # Handle error if task execution encounters an error + if response.get("isError"): + failure_reason = response.get("failureReason") + self.handle_error(task_name, mgmt_ip_instance_id_map, failure_reason) + break + + # Check if task completed successfully + elif not response.get("isError") and "success" in response.get("progress").lower(): + # Task completed successfully + self.msg = "{0} has completed successfully on device(s): {1}".format(task_name, list(mgmt_ip_instance_id_map.keys())) + + # Retrieve and modify compliance check details + response = self.get_compliance_detail(self.want.get("compliance_detail_params")) + if not response: + self.msg = "Error Occurred when retrieving Compliance Report after {0} with Task Id {1} for device(s) {2}".format( + task_name, task_id, list(mgmt_ip_instance_id_map.keys())) + self.update_result("failed", False, self.msg, "ERROR") + break + + modified_response = self.modify_compliance_response(response, mgmt_ip_instance_id_map) + self.log("Compliance Report for {0} operation for device(s) {1} : {2}".format( + task_name, list(mgmt_ip_instance_id_map.keys()), modified_response), "INFO") + + # Update result with modified response + self.update_result("success", True, self.msg, "INFO") + break + + # Check if task failed + elif "failed" in response.get("progress").lower(): + self.msg = "Failed to {0} on the following device(s): {1}".format(task_name, list(mgmt_ip_instance_id_map.keys())) + self.update_result("failed", False, self.msg, "CRITICAL") + break + + return self + + def get_sync_config_task_status(self, task_id, mgmt_ip_instance_id_map): + """ + This function manages the status of device configuration synchronization tasks in Cisco Catalyst Center. + Parameters: + - task_id: ID of the synchronization task + - mgmt_ip_instance_id_map: Mapping of management IP addresses to instance IDs + Returns: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Description: + It validates if synchronization is required, categorizes devices based on compliance status, and checks task completion status. + If all devices are already compliant, it logs a success message. If some devices have unexpected statuses, it logs an error. + It continuously checks the task status until completion, updating the result accordingly. + """ + + task_name = "Sync Device Configuration" + start_time = time.time() + + while True: + success_devices = [] + failed_devices = [] + + response = self.get_task_tree(task_id, task_name) + + # Check if response returned + if not response: + self.msg = "Error retrieving Task Tree for the task_name {0} task_id {1}".format(task_name, task_id) + self.update_result("failed", False, self.msg, "ERROR") + break + + # Check if the elapsed time exceeds the timeout + if self.exit_while_loop(start_time, task_id, task_name, response): + break + + # Handle error if task execution encounters an error + if response[0].get("isError"): + failure_reason = response.get("failureReason") + self.handle_error(task_name, mgmt_ip_instance_id_map, failure_reason) + break + + for item in response[1:]: + progress = item["progress"] + for ip, device_id in mgmt_ip_instance_id_map.items(): + if device_id in progress and "copy_Running_To_Startup=Success" in progress: + success_devices.append(ip) + elif device_id in progress and "copy_Running_To_Startup=Failed" in progress: + failed_devices.append(ip) + + success_devices = set(success_devices) + failed_devices = set(failed_devices) + + # Check conditions and print messages accordingly + if len(set(success_devices)) == len(mgmt_ip_instance_id_map): + self.msg = "{0} has completed successfully on device(s): {1}".format(task_name, success_devices) + self.update_result("success", True, self.msg, "INFO") + break + elif (failed_devices and + len(success_devices) < len(mgmt_ip_instance_id_map) and + len(failed_devices) + len(success_devices) == len(mgmt_ip_instance_id_map)): + self.msg = "{0} task has failed on device(s): {1} and succeeded on device(s): {2}".format( + task_name, failed_devices, success_devices) + self.update_result("failed", True, self.msg, "CRITICAL") + break + elif len(failed_devices) == len(mgmt_ip_instance_id_map): + self.msg = "{0} task has failed on device(s): {1}".format(task_name, failed_devices) + self.update_result("failed", False, self.msg, "CRITICAL") + break + + return self + + def get_diff_merged(self): + """ + This method is designed to Perform Network Compliance Actions in Cisco Catalyst Center. + Parameters: None + Returns: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Description: + This method orchestrates compliance check operation and device configuration synchronization tasks specified in a playbook. + It ensures all required tasks are present, executes them, and checks their status, facilitating smooth playbook execution. + """ + + # Action map for different network compliance operations + action_map = { + "run_compliance_params": (self.run_compliance, self.get_compliance_task_status), + "sync_device_config_params": (self.sync_device_config, self.get_sync_config_task_status) + } + + # Iterate through the action map and execute specified actions + for action_param, (action_func, status_func) in action_map.items(): + + # Execute the action and check its status + if self.want.get(action_param): + result_task_id = action_func(self.want.get(action_param)) + self.log("Performing {0}".format(action_func.__name__), "DEBUG") + if not result_task_id: + self.msg = "An error occurred while retrieving the task_id of the {0} operation.".format(action_func.__name__) + self.update_result("failed", False, self.msg, "CRITICAL") + else: + status_func(result_task_id, self.want.get("mgmt_ip_instance_id_map")).check_return_status() + + return self + + def verify_diff_merged(self, config): + """ + Verify the success of the "Sync Device Configuration" operation. + Parameters: + config (dict): A dictionary containing the configuration details. + Returns: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Description: + This method verifies the success of the "Sync Device Configuration" operation in the context of network compliance management. + It checks if the configuration includes the option to synchronize device configurations (`sync_device_config`). + If this option is present, the function proceeds to compare compliance details before and after executing the synchronization operation. + It logs relevant information at each step and concludes by determining whether the synchronization was successful. + """ + if config.get("sync_device_config"): + # Get compliance details before running sync_device_config + compliance_details_before = self.want.get("compliance_details") + self.log("Compliance details before running sync_device_config: {0}".format(compliance_details_before), "INFO") + + # Get compliance details after running sync_device_config + response = self.get_compliance_detail(self.want.get("compliance_detail_params_sync")) + if not response: + self.msg = "Error occured when Retrieving Compliance Details after for verifying configuration." + self.update("failed", False, self.msg, "ERROR") + self.check_return_status() + + compliance_details_after = self.modify_compliance_response(response, self.want.get("mgmt_ip_instance_id_map")) + self.log("Compliance details after running sync_device_config: {0}.".format(compliance_details_after), "INFO") + + all_statuses_before = [] + all_statuses_after = [] + for ip_address, compliance_type in compliance_details_before.items(): + status = compliance_type[0]["status"] + all_statuses_before.append(status) + + if len(set(all_statuses_before)) == 1 and all_statuses_before[0] == "NON_COMPLIANT": + for ip_address, compliance_type in compliance_details_after.items(): + status = compliance_type[0]["status"] + all_statuses_after.append(status) + if len(set(all_statuses_after)) == 1 and all_statuses_after[0] == "COMPLIANT": + self.log("Verified the success of the Sync Device Configuration operation.") + else: + self.log( + "Sync Device Configuration operation may have been unsuccessful " + "since not all devices have 'COMPLIANT' status after the operation.", + "WARNING" + ) + else: + self.log("Sync_device_config may not have been performed since devices have status other than 'NON_COMPLIANT'.", "WARNING") + else: + self.log("Verification of configuration is not required.", "INFO") + return self + + +def main(): + """ + main entry point for module execution + """ + + # Define the specification for the module"s arguments + element_spec = {"dnac_host": {"required": True, "type": "str"}, + "dnac_port": {"type": "str", "default": "443"}, + "dnac_username": {"type": "str", "default": "admin", "aliases": ["user"]}, + "dnac_password": {"type": "str", "no_log": True}, + "dnac_verify": {"type": "bool", "default": "True"}, + "dnac_version": {"type": "str", "default": "2.2.3.3"}, + "dnac_debug": {"type": "bool", "default": False}, + "dnac_log_level": {"type": "str", "default": "WARNING"}, + "dnac_log_file_path": {"type": "str", "default": "dnac.log"}, + "dnac_log_append": {"type": "bool", "default": True}, + "dnac_log": {"type": "bool", "default": False}, + "validate_response_schema": {"type": "bool", "default": True}, + "config_verify": {"type": "bool", "default": False}, + "dnac_api_task_timeout": {"type": "int", "default": 1200}, + "dnac_task_poll_interval": {"type": "int", "default": 2}, + "config": {"required": True, "type": "list", "elements": "dict"}, + "state": {"default": "merged", "choices": ["merged"]} + } + + # Initialize the Ansible module with the provided argument specifications + module = AnsibleModule(argument_spec=element_spec, + supports_check_mode=False) + + # Initialize the NetworkCompliance object with the module + ccc_network_compliance = NetworkCompliance(module) + + # Get the state parameter from the provided parameters + state = ccc_network_compliance.params.get("state") + + # Check if the state is valid + if state not in ccc_network_compliance.supported_states: + ccc_network_compliance.status = "invalid" + ccc_network_compliance.msg = "State {0} is invalid".format(state) + ccc_network_compliance.check_return_status() + + # Validate the input parameters and check the return status + ccc_network_compliance.validate_input().check_return_status() + + # Get the config_verify parameter from the provided parameters + config_verify = ccc_network_compliance.params.get("config_verify") + + # Iterate over the validated configuration parameters + for config in ccc_network_compliance.validated_config: + ccc_network_compliance.get_want(config).check_return_status() + ccc_network_compliance.get_diff_state_apply[state]().check_return_status() + if config_verify: + ccc_network_compliance.verify_diff_state_apply[state](config).check_return_status() + + # Exit with the result obtained from the NetworkCompliance object + module.exit_json(**ccc_network_compliance.result) + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/network_create.py b/plugins/modules/network_create.py index 8bf553aba0..e747dc2340 100644 --- a/plugins/modules/network_create.py +++ b/plugins/modules/network_create.py @@ -78,7 +78,7 @@ type: str port: description: Port for NetFlow Collector (eg; 443). - type: int + type: float type: dict network_aaa: description: Network Create's network_aaa. @@ -134,8 +134,8 @@ the network settings. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings CreateNetwork description: Complete reference of the CreateNetwork API. @@ -199,7 +199,6 @@ siteId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device.py b/plugins/modules/network_device.py index 2fca16035c..f9693da44e 100644 --- a/plugins/modules/network_device.py +++ b/plugins/modules/network_device.py @@ -12,7 +12,9 @@ - Manage operations create, update and delete of the resource Network Device. - Adds the device with given credential. - Deletes the network device for the given Id. -- Sync the devices provided as input. +- > + Update the credentials, management IP address of a given device or a set of devices in Catalyst Center and trigger + an inventory sync. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -23,102 +25,106 @@ type: bool version_added: 4.0.0 cliTransport: - description: Network Device's cliTransport. + description: CLI transport. Supported values telnet, ssh2. type: str computeDevice: - description: ComputeDevice flag. + description: Compute Device or not. Options are TRUE / FALSE. type: bool enablePassword: - description: Network Device's enablePassword. + description: CLI enable password of the device. type: str extendedDiscoveryInfo: - description: Network Device's extendedDiscoveryInfo. + description: This field holds that info as whether to add device with canned data + or not. Supported values DISCOVER_WITH_CANNED_DATA. type: str httpPassword: - description: Network Device's httpPassword. + description: HTTP password of the device. type: str httpPort: - description: Network Device's httpPort. + description: HTTP port of the device. type: str httpSecure: - description: HttpSecure flag. + description: Flag to select HTTP / HTTPS protocol. Options are TRUE / FALSE. TRUE + for HTTPS and FALSE for HTTP. type: bool httpUserName: - description: Network Device's httpUserName. + description: HTTP Username of the device. type: str id: description: Id path parameter. Device ID. type: str ipAddress: - description: Network Device's ipAddress. + description: IP Address of the device. elements: str type: list merakiOrgId: - description: Network Device's merakiOrgId. + description: Selected meraki organization for which the devices needs to be imported. elements: str type: list netconfPort: - description: Network Device's netconfPort. + description: Netconf Port of the device. type: str password: - description: Network Device's password. + description: CLI Password of the device. type: str serialNumber: - description: Network Device's serialNumber. + description: Serial Number of the Device. type: str snmpAuthPassphrase: - description: Network Device's snmpAuthPassphrase. + description: SNMPV3 auth passphrase of the device. type: str snmpAuthProtocol: - description: Network Device's snmpAuthProtocol. + description: SNMPV3 auth protocol. Supported values sha, md5. type: str snmpMode: - description: Network Device's snmpMode. + description: SNMPV3 mode. Supported values noAuthnoPriv, authNoPriv, authPriv. type: str snmpPrivPassphrase: - description: Network Device's snmpPrivPassphrase. + description: SNMPV3 priv passphrase. type: str snmpPrivProtocol: - description: Network Device's snmpPrivProtocol. + description: SNMPV3 priv protocol. Supported values AES128. type: str snmpROCommunity: - description: Network Device's snmpROCommunity. + description: SNMP Read Community of the device. type: str snmpRWCommunity: - description: Network Device's snmpRWCommunity. + description: SNMP Write Community of the device. type: str snmpRetry: - description: Network Device's snmpRetry. + description: SNMP retry count. Max value supported is 3. Default is Global SNMP + retry (if exists) or 3. type: int snmpTimeout: - description: Network Device's snmpTimeout. + description: SNMP timeout in seconds. Max value supported is 300. Default is Global + SNMP timeout (if exists) or 5. type: int snmpUserName: - description: Network Device's snmpUserName. + description: SNMPV3 user name of the device. type: str snmpVersion: - description: Network Device's snmpVersion. + description: SNMP version. Values supported v2, v3. Default is v2. type: str type: - description: Network Device's type. + description: Type of device being added. type: str updateMgmtIPaddressList: description: Network Device's updateMgmtIPaddressList. elements: dict suboptions: existMgmtIpAddress: - description: Network Device's existMgmtIpAddress. + description: ExistMgmtIpAddress IP Address of the device. type: str newMgmtIpAddress: - description: Network Device's newMgmtIpAddress. + description: New IP Address to be Updated. type: str type: list userName: - description: Network Device's userName. + description: CLI user name of the device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices AddDevice2 description: Complete reference of the AddDevice2 API. @@ -126,9 +132,9 @@ - name: Cisco DNA Center documentation for Devices DeleteDeviceById description: Complete reference of the DeleteDeviceById API. link: https://developer.cisco.com/docs/dna-center/#!delete-device-by-id -- name: Cisco DNA Center documentation for Devices SyncDevices2 - description: Complete reference of the SyncDevices2 API. - link: https://developer.cisco.com/docs/dna-center/#!sync-devices +- name: Cisco DNA Center documentation for Devices UpdateDeviceDetails + description: Complete reference of the UpdateDeviceDetails API. + link: https://developer.cisco.com/docs/dna-center/#!update-device-details notes: - SDK Method used are devices.Devices.add_device, @@ -181,9 +187,6 @@ snmpUserName: string snmpVersion: string type: string - updateMgmtIPaddressList: - - existMgmtIpAddress: string - newMgmtIpAddress: string userName: string - name: Update all @@ -242,7 +245,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_by_ip_info.py b/plugins/modules/network_device_by_ip_info.py index 502db8ba4d..c9206c301c 100644 --- a/plugins/modules/network_device_by_ip_info.py +++ b/plugins/modules/network_device_by_ip_info.py @@ -24,8 +24,8 @@ - IpAddress path parameter. Device IP address. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetNetworkDeviceByIP description: Complete reference of the GetNetworkDeviceByIP API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -101,7 +100,19 @@ "tunnelUdpPort": "string", "type": "string", "upTime": "string", - "waasDeviceMode": "string" + "waasDeviceMode": "string", + "dnsResolvedManagementAddress": "string", + "apEthernetMacAddress": "string", + "vendor": "string", + "reasonsForPendingSyncRequests": "string", + "pendingSyncRequestsCount": "string", + "reasonsForDeviceResync": "string", + "lastDeviceResyncStartTime": "string", + "uptimeSeconds": 0, + "managedAtleastOnce": true, + "deviceSupportLevel": "string", + "managementState": "string", + "description": "string" }, "version": "string" } diff --git a/plugins/modules/network_device_by_serial_number_info.py b/plugins/modules/network_device_by_serial_number_info.py index d40497b17c..69e4d249ac 100644 --- a/plugins/modules/network_device_by_serial_number_info.py +++ b/plugins/modules/network_device_by_serial_number_info.py @@ -10,7 +10,7 @@ short_description: Information module for Network Device By Serial Number description: - Get Network Device By Serial Number by id. -- Returns the network device if the given serial number matches with any of the serial numbers collected. +- Returns the network device with given serial number. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -24,8 +24,8 @@ - SerialNumber path parameter. Device serial number. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceBySerialNumber description: Complete reference of the GetDeviceBySerialNumber API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -101,7 +100,19 @@ "tunnelUdpPort": "string", "type": "string", "upTime": "string", - "waasDeviceMode": "string" + "waasDeviceMode": "string", + "dnsResolvedManagementAddress": "string", + "apEthernetMacAddress": "string", + "vendor": "string", + "reasonsForPendingSyncRequests": "string", + "pendingSyncRequestsCount": "string", + "reasonsForDeviceResync": "string", + "lastDeviceResyncStartTime": "string", + "uptimeSeconds": 0, + "managedAtleastOnce": true, + "deviceSupportLevel": "string", + "managementState": "string", + "description": "string" }, "version": "string" } diff --git a/plugins/modules/network_device_chassis_details_info.py b/plugins/modules/network_device_chassis_details_info.py index c5b34a498b..d8fdb938fa 100644 --- a/plugins/modules/network_device_chassis_details_info.py +++ b/plugins/modules/network_device_chassis_details_info.py @@ -24,8 +24,8 @@ - DeviceId path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetChassisDetailsForDevice description: Complete reference of the GetChassisDetailsForDevice API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_config__info.py b/plugins/modules/network_device_config__info.py new file mode 100644 index 0000000000..fa2701582b --- /dev/null +++ b/plugins/modules/network_device_config__info.py @@ -0,0 +1,135 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_config__info +short_description: Information module for Network Device Config +description: +- Get all Network Device Config. +- > + Returns the historical device configurations running configuration , startup configuration , vlan if applicable by + specified criteria. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + deviceId: + description: + - > + DeviceId query parameter. Comma separated device id for example + cf35b0a1-407f-412f-b2f4-f0c3156695f9,aaa38191-0c22-4158-befd-779a09d7cec1. If device id is not provided it + will fetch for all devices. + type: str + fileType: + description: + - FileType query parameter. Config File Type can be RUNNINGCONFIG or STARTUPCONFIG. + type: str + createdTime: + description: + - CreatedTime query parameter. Supported with logical filters GT,GTE,LT,LTE & BT time in milliseconds (epoc format). + type: str + createdBy: + description: + - > + CreatedBy query parameter. Comma separated values for createdBy - SCHEDULED, USER, CONFIG_CHANGE_EVENT, + SCHEDULED_FIRST_TIME, DR_CALL_BACK, PRE_DEPLOY. + type: str + offset: + description: + - Offset query parameter. + type: float + limit: + description: + - Limit query parameter. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Configuration Archive GetConfigurationArchiveDetails + description: Complete reference of the GetConfigurationArchiveDetails API. + link: https://developer.cisco.com/docs/dna-center/#!get-configuration-archive-details +notes: + - SDK Method used are + configuration_archive.ConfigurationArchive.get_configuration_archive_details, + + - Paths used are + get /dna/intent/api/v1/network-device-config, + +""" + +EXAMPLES = r""" +- name: Get all Network Device Config + cisco.dnac.network_device_config__info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + deviceId: string + fileType: string + createdTime: string + createdBy: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "ipAddress": "string", + "deviceId": "string", + "versions": [ + { + "files": [ + { + "fileType": "string", + "fileId": "string", + "downloadPath": "string" + } + ], + "createdBy": "string", + "configChangeType": "string", + "syslogConfigEventDto": [ + { + "userName": "string", + "deviceUuid": "string", + "outOfBand": true, + "configMethod": "string", + "terminalName": "string", + "loginIpAddress": "string", + "processName": "string", + "syslogTime": 0 + } + ], + "createdTime": 0, + "startupRunningStatus": "string", + "id": "string", + "tags": [ + "string" + ], + "lastUpdatedTime": 0 + } + ], + "deviceName": "string" + } + ] +""" diff --git a/plugins/modules/network_device_config_count_info.py b/plugins/modules/network_device_config_count_info.py index 3d2c900b06..9e11e98671 100644 --- a/plugins/modules/network_device_config_count_info.py +++ b/plugins/modules/network_device_config_count_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceConfigCount description: Complete reference of the GetDeviceConfigCount API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_config_info.py b/plugins/modules/network_device_config_info.py index 6810fd6db0..751e2e598a 100644 --- a/plugins/modules/network_device_config_info.py +++ b/plugins/modules/network_device_config_info.py @@ -11,7 +11,9 @@ description: - Get all Network Device Config. - Get Network Device Config by id. -- Returns the config for all devices. +- > + Returns the config for all devices. This API has been deprecated and will not be available in a Cisco Catalyst + Center release after Nov 1st 2024 23 59 59 GMT. - Returns the device config by specified device ID. version_added: '3.1.0' extends_documentation_fragment: @@ -26,8 +28,8 @@ - NetworkDeviceId path parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceConfigById description: Complete reference of the GetDeviceConfigById API. @@ -73,7 +75,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_config_task_info.py b/plugins/modules/network_device_config_task_info.py new file mode 100644 index 0000000000..3a993da10c --- /dev/null +++ b/plugins/modules/network_device_config_task_info.py @@ -0,0 +1,82 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_config_task_info +short_description: Information module for Network Device Config Task +description: +- Get all Network Device Config Task. +- Returns a config task result details by specified id. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + parentTaskId: + description: + - ParentTaskId query parameter. Task Id. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Configuration Archive GetConfigTaskDetails + description: Complete reference of the GetConfigTaskDetails API. + link: https://developer.cisco.com/docs/dna-center/#!get-config-task-details +notes: + - SDK Method used are + configuration_archive.ConfigurationArchive.get_config_task_details, + + - Paths used are + get /dna/intent/api/v1/network-device-config/task, + +""" + +EXAMPLES = r""" +- name: Get all Network Device Config Task + cisco.dnac.network_device_config_task_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + parentTaskId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "version": "string", + "response": [ + { + "startTime": 0, + "errorCode": "string", + "deviceId": "string", + "taskId": "string", + "taskStatus": "string", + "parentTaskId": "string", + "deviceIpAddress": "string", + "detailMessage": "string", + "failureMessage": "string", + "taskType": "string", + "completionTime": 0, + "hostName": "string" + } + ] + } +""" diff --git a/plugins/modules/network_device_config_write_memory.py b/plugins/modules/network_device_config_write_memory.py new file mode 100644 index 0000000000..966f0c41db --- /dev/null +++ b/plugins/modules/network_device_config_write_memory.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_config_write_memory +short_description: Resource module for Network Device Config Write Memory +description: +- Manage operation create of the resource Network Device Config Write Memory. +- This operation would commit device running configuration to startup by issuing "write memory" to device. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + deviceId: + description: UUID of the device. + elements: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Configuration Archive CommitDeviceConfiguration + description: Complete reference of the CommitDeviceConfiguration API. + link: https://developer.cisco.com/docs/dna-center/#!commit-device-configuration +notes: + - SDK Method used are + configuration_archive.ConfigurationArchive.commit_device_configuration, + + - Paths used are + post /dna/intent/api/v1/network-device-config/write-memory, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.network_device_config_write_memory: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + deviceId: + - string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "version": "string", + "response": { + "url": "string", + "taskId": "string" + } + } +""" diff --git a/plugins/modules/network_device_count_info.py b/plugins/modules/network_device_count_info.py index cdcf87b7cc..e7bdab9c9a 100644 --- a/plugins/modules/network_device_count_info.py +++ b/plugins/modules/network_device_count_info.py @@ -27,16 +27,36 @@ description: - DeviceId path parameter. Device ID. type: str + hostname: + description: + - Hostname query parameter. + elements: str + type: list + managementIpAddress: + description: + - ManagementIpAddress query parameter. + elements: str + type: list + macAddress: + description: + - MacAddress query parameter. + elements: str + type: list + locationName: + description: + - LocationName query parameter. + elements: str + type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceCount2 description: Complete reference of the GetDeviceCount2 API. link: https://developer.cisco.com/docs/dna-center/#!get-device-count -- name: Cisco DNA Center documentation for Devices GetDeviceInterfaceCount2 - description: Complete reference of the GetDeviceInterfaceCount2 API. - link: https://developer.cisco.com/docs/dna-center/#!get-device-interface-count-2 +- name: Cisco DNA Center documentation for Devices GetDeviceInterfaceCount + description: Complete reference of the GetDeviceInterfaceCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-device-interface-count notes: - SDK Method used are devices.Devices.get_device_count, @@ -59,6 +79,10 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" + hostname: [] + managementIpAddress: [] + macAddress: [] + locationName: [] register: result - name: Get Network Device Count by id @@ -75,7 +99,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_custom_prompt.py b/plugins/modules/network_device_custom_prompt.py index 38fbc4eaa5..5a69ba5b07 100644 --- a/plugins/modules/network_device_custom_prompt.py +++ b/plugins/modules/network_device_custom_prompt.py @@ -11,7 +11,7 @@ description: - Manage operation create of the resource Network Device Custom Prompt. - > - Save custom prompt added by user in Cisco DNA Center. API will always override the existing prompts. User should + Save custom prompt added by user in Catalyst Center. API will always override the existing prompts. User should provide all the custom prompt in case of any update. version_added: '6.0.0' extends_documentation_fragment: @@ -19,21 +19,21 @@ author: Rafael Campos (@racampos) options: passwordPrompt: - description: Password Prompt. + description: Password for Custom Prompt. type: str usernamePrompt: - description: Username Prompt. + description: Username for Custom Prompt. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for System Settings CustomPromptPOSTAPI description: Complete reference of the CustomPromptPOSTAPI API. link: https://developer.cisco.com/docs/dna-center/#!custom-prompt-postapi notes: - SDK Method used are - system_settings.SystemSettings.custom_prompt_post_api, + system_settings.SystemSettings.custom_prompt_p_o_s_t_api, - Paths used are post /dna/intent/api/v1/network-device/custom-prompt, @@ -54,7 +54,6 @@ usernamePrompt: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_custom_prompt_info.py b/plugins/modules/network_device_custom_prompt_info.py index cd3d02bdd0..5228a1f00f 100644 --- a/plugins/modules/network_device_custom_prompt_info.py +++ b/plugins/modules/network_device_custom_prompt_info.py @@ -10,7 +10,7 @@ short_description: Information module for Network Device Custom Prompt Info description: - Get all Network Device Custom Prompt Info. -- Returns supported custom prompts by Cisco DNA Center. +- Returns supported custom prompts by Catalyst Center. version_added: '6.0.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -20,15 +20,15 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for System Settings CustomPromptSupportGETAPI description: Complete reference of the CustomPromptSupportGETAPI API. link: https://developer.cisco.com/docs/dna-center/#!custom-prompt-support-getapi notes: - SDK Method used are - system_settings.SystemSettings.custom_prompt_support_get_api, + system_settings.SystemSettings.custom_prompt_support_g_e_t_api, - Paths used are get /dna/intent/api/v1/network-device/custom-prompt, @@ -37,7 +37,7 @@ EXAMPLES = r""" - name: Get all Network Device Custom Prompt Info - cisco.dnac.network_device_custom_prompt_info_info: + cisco.dnac.network_device_custom_prompt_info: dnac_host: "{{dnac_host}}" dnac_username: "{{dnac_username}}" dnac_password: "{{dnac_password}}" @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_equipment_info.py b/plugins/modules/network_device_equipment_info.py index 7bc3a67334..86e5c4f89c 100644 --- a/plugins/modules/network_device_equipment_info.py +++ b/plugins/modules/network_device_equipment_info.py @@ -10,7 +10,9 @@ short_description: Information module for Network Device Equipment description: - Get all Network Device Equipment. -- Return PowerSupply/ Fan details for the Given device. +- > + Return all types of equipment details like PowerSupply, Fan, Chassis, Backplane, Module, PROCESSOR, Other and SFP + for the Given device. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -30,15 +32,15 @@ If no type is mentioned, All equipments are fetched for the device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Devices ReturnPowerSupplyFanDetailsForTheGivenDevice - description: Complete reference of the ReturnPowerSupplyFanDetailsForTheGivenDevice API. - link: https://developer.cisco.com/docs/dna-center/#!return-power-supply-fan-details-for-the-given-device +- name: Cisco DNA Center documentation for Devices GetTheDetailsOfPhysicalComponentsOfTheGivenDevice + description: Complete reference of the GetTheDetailsOfPhysicalComponentsOfTheGivenDevice API. + link: https://developer.cisco.com/docs/dna-center/#!get-the-details-of-physical-components-of-the-given-device notes: - SDK Method used are - devices.Devices.return_power_supply_fan_details_for_the_given_device, + devices.Devices.get_the_details_of_physical_components_of_the_given_device, - Paths used are get /dna/intent/api/v1/network-device/{deviceUuid}/equipment, @@ -61,7 +63,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -77,7 +78,8 @@ "vendorEquipmentType": "string", "description": "string", "instanceUuid": "string", - "name": "string" + "name": "string", + "manufacturer": "string" } ], "version": "string" diff --git a/plugins/modules/network_device_export.py b/plugins/modules/network_device_export.py index c1bf8d245d..15d9a981c6 100644 --- a/plugins/modules/network_device_export.py +++ b/plugins/modules/network_device_export.py @@ -17,25 +17,22 @@ author: Rafael Campos (@racampos) options: deviceUuids: - description: Network Device Export's deviceUuids. + description: List of device uuids. elements: str type: list - id: - description: Network Device Export's id. - type: str operationEnum: - description: Network Device Export's operationEnum. + description: 0 to export Device Credential Details Or 1 to export Device Details. type: str parameters: - description: Network Device Export's parameters. + description: List of device parameters that needs to be exported to file. elements: str type: list password: - description: Network Device Export's password. + description: Password is required when the operationEnum value is 0. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices ExportDeviceList description: Complete reference of the ExportDeviceList API. @@ -61,14 +58,12 @@ dnac_debug: "{{dnac_debug}}" deviceUuids: - string - id: string operationEnum: string parameters: - string password: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_functional_capability_info.py b/plugins/modules/network_device_functional_capability_info.py index 1d88047ab9..f8b1cb7323 100644 --- a/plugins/modules/network_device_functional_capability_info.py +++ b/plugins/modules/network_device_functional_capability_info.py @@ -37,8 +37,8 @@ - Id path parameter. Functional Capability UUID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetFunctionalCapabilityById description: Complete reference of the GetFunctionalCapabilityById API. @@ -86,7 +86,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_global_polling_interval_info.py b/plugins/modules/network_device_global_polling_interval_info.py index 41bced4d18..8754fa5573 100644 --- a/plugins/modules/network_device_global_polling_interval_info.py +++ b/plugins/modules/network_device_global_polling_interval_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetPollingIntervalForAllDevices description: Complete reference of the GetPollingIntervalForAllDevices API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_info.py b/plugins/modules/network_device_info.py index 7dae65a3f0..ec67bf1676 100644 --- a/plugins/modules/network_device_info.py +++ b/plugins/modules/network_device_info.py @@ -190,8 +190,8 @@ - Limit query parameter. 1 <= limit <= 500 max. No. Of devices to be returned in the result. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceByID description: Complete reference of the GetDeviceByID API. @@ -271,7 +271,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -318,7 +317,19 @@ "tunnelUdpPort": "string", "type": "string", "upTime": "string", - "waasDeviceMode": "string" + "waasDeviceMode": "string", + "dnsResolvedManagementAddress": "string", + "apEthernetMacAddress": "string", + "vendor": "string", + "reasonsForPendingSyncRequests": "string", + "pendingSyncRequestsCount": "string", + "reasonsForDeviceResync": "string", + "lastDeviceResyncStartTime": "string", + "uptimeSeconds": 0, + "managedAtleastOnce": true, + "deviceSupportLevel": "string", + "managementState": "string", + "description": "string" }, "version": "string" } diff --git a/plugins/modules/network_device_insight_device_link_info.py b/plugins/modules/network_device_insight_device_link_info.py new file mode 100644 index 0000000000..967b6ef472 --- /dev/null +++ b/plugins/modules/network_device_insight_device_link_info.py @@ -0,0 +1,126 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_insight_device_link_info +short_description: Information module for Network Device Insight Device Link +description: +- Get all Network Device Insight Device Link. +- Find all devices with link mismatch speed / vlan . +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + siteId: + description: + - SiteId path parameter. + type: str + offset: + description: + - Offset query parameter. Row Number. Default value is 1. + type: int + limit: + description: + - Limit query parameter. Default value is 500. + type: int + category: + description: + - Category query parameter. Links mismatch category. Value can be speed-duplex or vlan. + type: str + sortBy: + description: + - SortBy query parameter. Sort By. + type: str + order: + description: + - Order query parameter. Order. Value can be asc or desc. Default value is asc. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Devices InventoryInsightDeviceLinkMismatch + description: Complete reference of the InventoryInsightDeviceLinkMismatch API. + link: https://developer.cisco.com/docs/dna-center/#!inventory-insight-device-link-mismatch +notes: + - SDK Method used are + devices.Devices.inventory_insight_device_link_mismatch, + + - Paths used are + get /dna/intent/api/v1/network-device/insight/{siteId}/device-link, + +""" + +EXAMPLES = r""" +- name: Get all Network Device Insight Device Link + cisco.dnac.network_device_insight_device_link_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + offset: 0 + limit: 0 + category: string + sortBy: string + order: string + siteId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "endPortAllowedVlanIds": "string", + "endPortNativeVlanId": "string", + "startPortAllowedVlanIds": "string", + "startPortNativeVlanId": "string", + "linkStatus": "string", + "endDeviceHostName": "string", + "endDeviceId": "string", + "endDeviceIpAddress": "string", + "endPortAddress": "string", + "endPortDuplex": "string", + "endPortId": "string", + "endPortMask": "string", + "endPortName": "string", + "endPortPepId": "string", + "endPortSpeed": "string", + "startDeviceHostName": "string", + "startDeviceId": "string", + "startDeviceIpAddress": "string", + "startPortAddress": "string", + "startPortDuplex": "string", + "startPortId": "string", + "startPortMask": "string", + "startPortName": "string", + "startPortPepId": "string", + "startPortSpeed": "string", + "lastUpdated": "string", + "numUpdates": 0, + "avgUpdateFrequency": 0, + "type": "string", + "instanceUuid": "string", + "instanceTenantId": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/network_device_interface_neighbor_info.py b/plugins/modules/network_device_interface_neighbor_info.py index da4550a9e2..dd0103517a 100644 --- a/plugins/modules/network_device_interface_neighbor_info.py +++ b/plugins/modules/network_device_interface_neighbor_info.py @@ -28,8 +28,8 @@ - InterfaceUuid path parameter. Instanceuuid of interface. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetConnectedDeviceDetail description: Complete reference of the GetConnectedDeviceDetail API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_interface_poe_info.py b/plugins/modules/network_device_interface_poe_info.py index 2c525456f6..4035da3a8f 100644 --- a/plugins/modules/network_device_interface_poe_info.py +++ b/plugins/modules/network_device_interface_poe_info.py @@ -31,8 +31,8 @@ - InterfaceNameList query parameter. Comma seperated interface names. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices ReturnsPOEInterfaceDetailsForTheDevice description: Complete reference of the ReturnsPOEInterfaceDetailsForTheDevice API. @@ -62,7 +62,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_inventory_insight_link_mismatch_info.py b/plugins/modules/network_device_inventory_insight_link_mismatch_info.py index ee282e771a..82b97fc2d0 100644 --- a/plugins/modules/network_device_inventory_insight_link_mismatch_info.py +++ b/plugins/modules/network_device_inventory_insight_link_mismatch_info.py @@ -44,8 +44,8 @@ - Order query parameter. Order. Value can be asc or desc. Default value is asc. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices InventoryInsightDeviceLinkMismatchAPI description: Complete reference of the InventoryInsightDeviceLinkMismatchAPI API. @@ -79,7 +79,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_ip_address_info.py b/plugins/modules/network_device_ip_address_info.py new file mode 100644 index 0000000000..be09615276 --- /dev/null +++ b/plugins/modules/network_device_ip_address_info.py @@ -0,0 +1,119 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_ip_address_info +short_description: Information module for Network Device Ip Address +description: +- Get Network Device Ip Address by id. +- Returns the network device by specified IP address. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + ipAddress: + description: + - IpAddress path parameter. Device IP address. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Devices GetNetworkDeviceByIP + description: Complete reference of the GetNetworkDeviceByIP API. + link: https://developer.cisco.com/docs/dna-center/#!get-network-device-by-ip +notes: + - SDK Method used are + devices.Devices.get_network_device_by_ip, + + - Paths used are + get /dna/intent/api/v1/network-device/ip-address/{ipAddress}, + +""" + +EXAMPLES = r""" +- name: Get Network Device Ip Address by id + cisco.dnac.network_device_ip_address_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + ipAddress: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "apManagerInterfaceIp": "string", + "associatedWlcIp": "string", + "bootDateTime": "string", + "collectionInterval": "string", + "collectionStatus": "string", + "errorCode": "string", + "errorDescription": "string", + "family": "string", + "hostname": "string", + "id": "string", + "instanceTenantId": "string", + "instanceUuid": "string", + "interfaceCount": "string", + "inventoryStatusDetail": "string", + "lastUpdateTime": 0, + "lastUpdated": "string", + "lineCardCount": "string", + "lineCardId": "string", + "location": "string", + "locationName": "string", + "macAddress": "string", + "managementIpAddress": "string", + "memorySize": "string", + "platformId": "string", + "reachabilityFailureReason": "string", + "reachabilityStatus": "string", + "role": "string", + "roleSource": "string", + "serialNumber": "string", + "series": "string", + "snmpContact": "string", + "snmpLocation": "string", + "softwareType": "string", + "softwareVersion": "string", + "tagCount": "string", + "tunnelUdpPort": "string", + "type": "string", + "upTime": "string", + "waasDeviceMode": "string", + "dnsResolvedManagementAddress": "string", + "apEthernetMacAddress": "string", + "vendor": "string", + "reasonsForPendingSyncRequests": "string", + "pendingSyncRequestsCount": "string", + "reasonsForDeviceResync": "string", + "lastDeviceResyncStartTime": "string", + "uptimeSeconds": 0, + "managedAtleastOnce": true, + "deviceSupportLevel": "string", + "managementState": "string", + "description": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/network_device_lexicographically_sorted_info.py b/plugins/modules/network_device_lexicographically_sorted_info.py index cd7473692b..0eb0ccd4bd 100644 --- a/plugins/modules/network_device_lexicographically_sorted_info.py +++ b/plugins/modules/network_device_lexicographically_sorted_info.py @@ -108,8 +108,8 @@ - Limit query parameter. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceValuesThatMatchFullyOrPartiallyAnAttribute description: Complete reference of the GetDeviceValuesThatMatchFullyOrPartiallyAnAttribute API. @@ -159,17 +159,11 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: dict + type: str sample: > - { - "response": [ - "string" - ], - "version": "string" - } + "string" """ diff --git a/plugins/modules/network_device_linecard_details_info.py b/plugins/modules/network_device_linecard_details_info.py index 6ec120deda..b4b9682c2c 100644 --- a/plugins/modules/network_device_linecard_details_info.py +++ b/plugins/modules/network_device_linecard_details_info.py @@ -24,8 +24,8 @@ - DeviceUuid path parameter. Instanceuuid of device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetLinecardDetails description: Complete reference of the GetLinecardDetails API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_management_address_update.py b/plugins/modules/network_device_management_address_update.py new file mode 100644 index 0000000000..328e4e457a --- /dev/null +++ b/plugins/modules/network_device_management_address_update.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_management_address_update +short_description: Resource module for Network Device Management Address Update +description: +- Manage operation update of the resource Network Device Management Address Update. +- This is a simple PUT API to edit the management IP Address of the device. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + deviceid: + description: Deviceid path parameter. The UUID of the device whose management IP + address is to be updated. + type: str + newIP: + description: New IP Address of the device to be Updated. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Devices UpdateDeviceManagementAddress + description: Complete reference of the UpdateDeviceManagementAddress API. + link: https://developer.cisco.com/docs/dna-center/#!update-device-management-address +notes: + - SDK Method used are + devices.Devices.update_device_management_address, + + - Paths used are + put /dna/intent/api/v1/network-device/{deviceid}/management-address, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.network_device_management_address_update: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + deviceid: string + newIP: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/network_device_meraki_organization_info.py b/plugins/modules/network_device_meraki_organization_info.py index a8bc1ddeb6..0315c080f1 100644 --- a/plugins/modules/network_device_meraki_organization_info.py +++ b/plugins/modules/network_device_meraki_organization_info.py @@ -21,11 +21,11 @@ type: dict id: description: - - Id path parameter. + - Id path parameter. Device Id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetOrganizationListForMeraki description: Complete reference of the GetOrganizationListForMeraki API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_module_count_info.py b/plugins/modules/network_device_module_count_info.py index 5969b346ee..8a7400622d 100644 --- a/plugins/modules/network_device_module_count_info.py +++ b/plugins/modules/network_device_module_count_info.py @@ -44,8 +44,8 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetModuleCount description: Complete reference of the GetModuleCount API. @@ -78,7 +78,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_module_info.py b/plugins/modules/network_device_module_info.py index be3bd1a556..05ae77d724 100644 --- a/plugins/modules/network_device_module_info.py +++ b/plugins/modules/network_device_module_info.py @@ -58,8 +58,8 @@ - Id path parameter. Module id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetModuleInfoById description: Complete reference of the GetModuleInfoById API. @@ -112,7 +112,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_poe_info.py b/plugins/modules/network_device_poe_info.py index 4f78d1e703..7323d9d1ad 100644 --- a/plugins/modules/network_device_poe_info.py +++ b/plugins/modules/network_device_poe_info.py @@ -21,11 +21,11 @@ type: dict deviceUuid: description: - - DeviceUuid path parameter. Uuid of the device. + - DeviceUuid path parameter. UUID of the device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices POEDetails description: Complete reference of the POEDetails API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_polling_interval_info.py b/plugins/modules/network_device_polling_interval_info.py index fc4707d26e..5a890d5474 100644 --- a/plugins/modules/network_device_polling_interval_info.py +++ b/plugins/modules/network_device_polling_interval_info.py @@ -24,8 +24,8 @@ - Id path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetPollingIntervalById description: Complete reference of the GetPollingIntervalById API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_range_info.py b/plugins/modules/network_device_range_info.py index 5ea4572f49..01825cdf61 100644 --- a/plugins/modules/network_device_range_info.py +++ b/plugins/modules/network_device_range_info.py @@ -30,8 +30,8 @@ - RecordsToReturn path parameter. Number of records to return 1<= recordsToReturn <= 500. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetNetworkDeviceByPaginationRange description: Complete reference of the GetNetworkDeviceByPaginationRange API. @@ -61,7 +61,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -109,7 +108,19 @@ "tunnelUdpPort": "string", "type": "string", "upTime": "string", - "waasDeviceMode": "string" + "waasDeviceMode": "string", + "dnsResolvedManagementAddress": "string", + "apEthernetMacAddress": "string", + "vendor": "string", + "reasonsForPendingSyncRequests": "string", + "pendingSyncRequestsCount": "string", + "reasonsForDeviceResync": "string", + "lastDeviceResyncStartTime": "string", + "uptimeSeconds": 0, + "managedAtleastOnce": true, + "deviceSupportLevel": "string", + "managementState": "string", + "description": "string" } ], "version": "string" diff --git a/plugins/modules/network_device_register_for_wsa_info.py b/plugins/modules/network_device_register_for_wsa_info.py index 29c483aa29..7785cd9360 100644 --- a/plugins/modules/network_device_register_for_wsa_info.py +++ b/plugins/modules/network_device_register_for_wsa_info.py @@ -30,8 +30,8 @@ - Macaddress query parameter. Mac addres of the device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDevicesRegisteredForWSANotification description: Complete reference of the GetDevicesRegisteredForWSANotification API. @@ -61,7 +61,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_stack_details_info.py b/plugins/modules/network_device_stack_details_info.py index 5cdaf55ad6..ebf1a6c1e9 100644 --- a/plugins/modules/network_device_stack_details_info.py +++ b/plugins/modules/network_device_stack_details_info.py @@ -24,8 +24,8 @@ - DeviceId path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetStackDetailsForDevice description: Complete reference of the GetStackDetailsForDevice API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_summary_info.py b/plugins/modules/network_device_summary_info.py index 3096ba1cf2..9ef9c5dec9 100644 --- a/plugins/modules/network_device_summary_info.py +++ b/plugins/modules/network_device_summary_info.py @@ -24,8 +24,8 @@ - Id path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceSummary description: Complete reference of the GetDeviceSummary API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_supervisor_card_details_info.py b/plugins/modules/network_device_supervisor_card_details_info.py index f9db5bdd7a..f4bf0fc546 100644 --- a/plugins/modules/network_device_supervisor_card_details_info.py +++ b/plugins/modules/network_device_supervisor_card_details_info.py @@ -24,8 +24,8 @@ - DeviceUuid path parameter. Instanceuuid of device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetSupervisorCardDetail description: Complete reference of the GetSupervisorCardDetail API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_sync.py b/plugins/modules/network_device_sync.py index 526b8d239b..049800bc3b 100644 --- a/plugins/modules/network_device_sync.py +++ b/plugins/modules/network_device_sync.py @@ -24,11 +24,11 @@ type: bool payload: description: Network Device Sync's payload. - elements: dict + elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices SyncDevices description: Complete reference of the SyncDevices API. @@ -54,10 +54,9 @@ dnac_debug: "{{dnac_debug}}" forceSync: true payload: - - {} + - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_update_role.py b/plugins/modules/network_device_update_role.py index 14ded7ec10..319ef58e1c 100644 --- a/plugins/modules/network_device_update_role.py +++ b/plugins/modules/network_device_update_role.py @@ -17,17 +17,17 @@ author: Rafael Campos (@racampos) options: id: - description: Network Device Update Role's id. + description: DeviceId of the Device. type: str role: - description: Network Device Update Role's role. + description: Role of device as ACCESS, CORE, DISTRIBUTION, BORDER ROUTER. type: str roleSource: - description: Network Device Update Role's roleSource. + description: Role source as MANUAL / AUTO. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices UpdateDeviceRole description: Complete reference of the UpdateDeviceRole API. @@ -56,7 +56,6 @@ roleSource: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_user_defined_field.py b/plugins/modules/network_device_user_defined_field.py index 8d0ddc17ef..cb25f8eef3 100644 --- a/plugins/modules/network_device_user_defined_field.py +++ b/plugins/modules/network_device_user_defined_field.py @@ -13,7 +13,7 @@ - Creates a new global User Defined Field, which can be assigned to devices. - Deletes an existing Global User-Defined-Field using it's id. - Updates an existing global User Defined Field, using it's id. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -28,8 +28,8 @@ description: Name of UDF. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices CreateUserDefinedField description: Complete reference of the CreateUserDefinedField API. @@ -94,7 +94,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_user_defined_field_delete.py b/plugins/modules/network_device_user_defined_field_delete.py new file mode 100644 index 0000000000..ccc04acbcc --- /dev/null +++ b/plugins/modules/network_device_user_defined_field_delete.py @@ -0,0 +1,70 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_user_defined_field_delete +short_description: Resource module for Network Device User Defined Field Delete +description: +- Manage operation delete of the resource Network Device User Defined Field Delete. +- > + Remove a User-Defined-Field from device. Name of UDF has to be passed as the query parameter. Please note that + Global UDF will not be deleted by this operation. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + deviceId: + description: DeviceId path parameter. UUID of device from which UDF has to be removed. + type: str + name: + description: Name query parameter. Name of UDF to be removed. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Devices RemoveUserDefinedFieldFromDevice + description: Complete reference of the RemoveUserDefinedFieldFromDevice API. + link: https://developer.cisco.com/docs/dna-center/#!remove-user-defined-field-from-device +notes: + - SDK Method used are + devices.Devices.remove_user_defined_field_from_device, + + - Paths used are + delete /dna/intent/api/v1/network-device/{deviceId}/user-defined-field, + +""" + +EXAMPLES = r""" +- name: Delete all + cisco.dnac.network_device_user_defined_field_delete: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + deviceId: string + name: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/network_device_user_defined_field_info.py b/plugins/modules/network_device_user_defined_field_info.py index 9671142727..fb3a1b7f44 100644 --- a/plugins/modules/network_device_user_defined_field_info.py +++ b/plugins/modules/network_device_user_defined_field_info.py @@ -12,8 +12,8 @@ - Get all Network Device User Defined Field. - > Gets existing global User Defined Fields. If no input is given, it fetches ALL the Global UDFs. Filter/search is - supported either by UDF Ids or by UDF names, but not both. -version_added: '6.7.0' + supported by UDF Ids or UDF names or both. +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -30,8 +30,8 @@ - Name query parameter. Comma-seperated name(s) used for search/filtering. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetAllUserDefinedFields description: Complete reference of the GetAllUserDefinedFields API. @@ -61,7 +61,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_user_defined_field_update.py b/plugins/modules/network_device_user_defined_field_update.py new file mode 100644 index 0000000000..f0a9c4face --- /dev/null +++ b/plugins/modules/network_device_user_defined_field_update.py @@ -0,0 +1,81 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: network_device_user_defined_field_update +short_description: Resource module for Network Device User Defined Field Update +description: +- Manage operation update of the resource Network Device User Defined Field Update. +- > + Assigns an existing Global User-Defined-Field to a device. If the UDF is already assigned to the specific device, + then it updates the device UDF value accordingly. Please note that the assigning UDF 'name' must be an existing + global UDF. Otherwise error shall be shown. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + deviceId: + description: DeviceId path parameter. UUID of device to which UDF has to be added. + type: str + payload: + description: Network Device User Defined Field Update's payload. + elements: dict + suboptions: + name: + description: Name of the User Defined Field. + type: str + value: + description: Value of the User Defined Field that will be assigned to the device. + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Devices AddUserDefinedFieldToDevice + description: Complete reference of the AddUserDefinedFieldToDevice API. + link: https://developer.cisco.com/docs/dna-center/#!add-user-defined-field-to-device +notes: + - SDK Method used are + devices.Devices.add_user_defined_field_to_device, + + - Paths used are + put /dna/intent/api/v1/network-device/{deviceId}/user-defined-field, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.network_device_user_defined_field_update: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + deviceId: string + payload: + - name: string + value: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/network_device_vlan_info.py b/plugins/modules/network_device_vlan_info.py index 132c102c7e..76ad0369ef 100644 --- a/plugins/modules/network_device_vlan_info.py +++ b/plugins/modules/network_device_vlan_info.py @@ -10,7 +10,7 @@ short_description: Information module for Network Device Vlan description: - Get all Network Device Vlan. -- Returns Device Interface VLANs. +- Returns Device Interface VLANs. If parameter value is null or empty, it won't return any value in response. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -25,11 +25,14 @@ type: str interfaceType: description: - - InterfaceType query parameter. Vlan assocaited with sub-interface. + - > + InterfaceType query parameter. Vlan associated with sub-interface. If no interfaceType mentioned it will + return all types of Vlan interfaces. If interfaceType is selected but not specified then it will take + default value. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetDeviceInterfaceVLANs description: Complete reference of the GetDeviceInterfaceVLANs API. @@ -59,7 +62,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_device_wireless_lan_info.py b/plugins/modules/network_device_wireless_lan_info.py index f08b1bcca0..f89bbead3d 100644 --- a/plugins/modules/network_device_wireless_lan_info.py +++ b/plugins/modules/network_device_wireless_lan_info.py @@ -24,8 +24,8 @@ - Id path parameter. Device ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetWirelessLanControllerDetailsById description: Complete reference of the GetWirelessLanControllerDetailsById API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -62,22 +61,19 @@ type: dict sample: > { - "response": { - "adminEnabledPorts": [ - 0 - ], - "apGroupName": "string", - "deviceId": "string", - "ethMacAddress": "string", - "flexGroupName": "string", - "id": "string", - "instanceTenantId": "string", - "instanceUuid": "string", - "lagModeEnabled": true, - "netconfEnabled": true, - "wirelessLicenseInfo": "string", - "wirelessPackageInstalled": true - }, - "version": "string" + "adminEnabledPorts": [ + 0 + ], + "apGroupName": "string", + "deviceId": "string", + "ethMacAddress": "string", + "flexGroupName": "string", + "id": "string", + "instanceTenantId": "string", + "instanceUuid": "string", + "lagModeEnabled": true, + "netconfEnabled": true, + "wirelessLicenseInfo": "string", + "wirelessPackageInstalled": true } """ diff --git a/plugins/modules/network_device_with_snmp_v3_des_info.py b/plugins/modules/network_device_with_snmp_v3_des_info.py index b3b6a55d68..81abfc8127 100644 --- a/plugins/modules/network_device_with_snmp_v3_des_info.py +++ b/plugins/modules/network_device_with_snmp_v3_des_info.py @@ -42,7 +42,7 @@ - Order query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Devices ReturnsDevicesAddedToCiscoDNACenterWithSnmpV3DES diff --git a/plugins/modules/network_info.py b/plugins/modules/network_info.py index 0aa99bde53..36a7a62868 100644 --- a/plugins/modules/network_info.py +++ b/plugins/modules/network_info.py @@ -24,8 +24,8 @@ - SiteId query parameter. Site id to get the network settings associated with the site. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings GetNetwork description: Complete reference of the GetNetwork API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/network_settings_workflow_manager.py b/plugins/modules/network_settings_workflow_manager.py index cdf7b06344..7580660247 100644 --- a/plugins/modules/network_settings_workflow_manager.py +++ b/plugins/modules/network_settings_workflow_manager.py @@ -54,18 +54,19 @@ elements: dict type: list suboptions: - dhcp_server_ips: + name: + description: Specifies the name assigned to the Global IP Pool. + type: str + pool_type: description: > - The DHCP server IPs responsible for automatically assigning IP addresses - and network configuration parameters to devices on a local network. - elements: str - type: list - dns_server_ips: - description: Responsible for translating domain names into corresponding IP addresses. - elements: str - type: list - gateway: - description: Serves as an entry or exit point for data traffic between networks. + Includes both the Generic Ip Pool and Tunnel Ip Pool. + Generic - Used for general purpose within the network such as device + management or communication between the network devices. + Tunnel - Designated for the tunnel interfaces to encapsulate packets + within the network protocol. It is used in VPN connections, + GRE tunnels, or other types of overlay networks. + default: Generic + choices: [Generic, Tunnel] type: str ip_address_space: description: IP address space either IPv4 or IPv6. @@ -75,44 +76,71 @@ Defines the IP pool's Classless Inter-Domain Routing block, enabling systematic IP address distribution within a network. type: str + gateway: + description: Serves as an entry or exit point for data traffic between networks. + type: str + dhcp_server_ips: + description: > + The DHCP server IPs responsible for automatically assigning IP addresses + and network configuration parameters to devices on a local network. + elements: str + type: list + dns_server_ips: + description: Responsible for translating domain names into corresponding IP addresses. + elements: str + type: list prev_name: description: > The former identifier for the global pool. It should be used exclusively when you need to update the global pool's name. type: str - name: - description: Specifies the name assigned to the Global IP Pool. - type: str - pool_type: - description: > - Includes both the Generic Ip Pool and Tunnel Ip Pool. - Generic - Used for general purpose within the network such as device - management or communication between the network devices. - Tunnel - Designated for the tunnel interfaces to encapsulate packets - within the network protocol. It is used in VPN connections, - GRE tunnels, or other types of overlay networks. - default: Generic - choices: [Generic, Tunnel] - type: str reserve_pool_details: description: Reserved IP subpool details from the global pool. type: dict suboptions: - ipv4_dhcp_servers: - description: Specifies the IPv4 addresses for DHCP servers, for example, "1.1.1.1". - elements: str - type: list - ipv4_dns_servers: - description: Specifies the IPv4 addresses for DNS servers, for example, "4.4.4.4". - elements: str - type: list - ipv4_gateway: - description: Provides the gateway's IPv4 address, for example, "175.175.0.1". + site_name: + description: > + The name of the site provided as a path parameter, used + to specify where the IP sub-pool will be reserved. type: str - version_added: 4.0.0 + name: + description: Name of the reserve IP subpool. + type: str + pool_type: + description: Type of the reserve ip sub pool. + Generic - Used for general purpose within the network such as device + management or communication between the network devices. + LAN - Used for the devices and the resources within the Local Area Network + such as device connectivity, internal communication, or services. + Management - Used for the management purposes such as device management interfaces, + management access, or other administrative functions. + Service - Used for the network services and application such as DNS (Domain Name System), + DHCP (Dynamic Host Configuration Protocol), NTP (Network Time Protocol). + WAN - Used for the devices and resources with the Wide Area Network such as remote + sites interconnection with other network or services hosted within WAN. + default: Generic + choices: [Generic, LAN, Management, Service, WAN] + type: str + ipv6_address_space: + description: > + Determines whether both IPv6 and IPv4 inputs are required. + If set to false, only IPv4 inputs are required. + If set to true, both IPv6 and IPv4 inputs are required. + type: bool ipv4_global_pool: - description: IP v4 Global pool address with cidr, example 175.175.0.0/16. + description: + - IP v4 Global pool address with cidr, example 175.175.0.0/16. + - If both 'ipv6_global_pool' and 'ipv4_global_pool_name' are provided, the 'ipv4_global_pool' will be given priority. + type: str + ipv4_global_pool_name: + description: + - Specifies the name to be associated with the IPv4 Global IP Pool. + - If both 'ipv4_global_pool' and 'ipv4_global_pool_name' are provided, the 'ipv4_global_pool' will be given priority. + type: str + version_added: 6.14.0 + ipv4_subnet: + description: Indicates the IPv4 subnet address, for example, "175.175.0.0". type: str ipv4_prefix: description: ip4 prefix length is enabled or ipv4 total Host input is enabled @@ -120,18 +148,21 @@ ipv4_prefix_length: description: The ipv4 prefix length is required when ipv4_prefix value is true. type: int - ipv4_subnet: - description: Indicates the IPv4 subnet address, for example, "175.175.0.0". - type: str ipv4_total_host: description: The total number of hosts for IPv4, required when the 'ipv4_prefix' is set to false. type: int - ipv6_address_space: - description: > - Determines whether both IPv6 and IPv4 inputs are required. - If set to false, only IPv4 inputs are required. - If set to true, both IPv6 and IPv4 inputs are required. - type: bool + ipv4_gateway: + description: Provides the gateway's IPv4 address, for example, "175.175.0.1". + type: str + version_added: 4.0.0 + ipv4_dhcp_servers: + description: Specifies the IPv4 addresses for DHCP servers, for example, "1.1.1.1". + elements: str + type: list + ipv4_dns_servers: + description: Specifies the IPv4 addresses for DNS servers, for example, "4.4.4.4". + elements: str + type: list ipv6_dhcp_servers: description: > Specifies the IPv6 addresses for DHCP servers in the format. @@ -150,9 +181,19 @@ For example, "2001:0db8:0123:4567:89ab:cdef:0003:0003". type: str ipv6_global_pool: - description: > - IPv6 Global pool address with cidr this is required when ipv6_address_space - value is true, example 2001 db8 85a3 /64. + description: + - The ipv6_global_pool is a mandatory when the ipv6_address_space is set to true. + - It specifies the global IPv6 address pool using CIDR notation, such as "2001:db8:85a3::/64". + - In cases where both ipv6_global_pool and ipv6_global_pool_name are specified, ipv6_global_pool will take precedence. + type: str + ipv6_global_pool_name: + description: + - Specifies the name assigned to the Ip v6 Global IP Pool. + - If both 'ipv6_global_pool' and 'ipv6_global_pool_name' are provided, the 'ipv6_global_pool' will be given priority. + type: str + version_added: 6.14.0 + ipv6_subnet: + description: IPv6 Subnet address, example 2001:db8:85a3:0:100. type: str ipv6_prefix: description: > @@ -162,51 +203,49 @@ ipv6_prefix_length: description: IPv6 prefix length is required when the ipv6_prefix value is true. type: int - ipv6_subnet: - description: IPv6 Subnet address, example 2001 db8 85a3 0 100. - type: str ipv6_total_host: description: The total number of hosts for IPv6 is required if the 'ipv6_prefix' is set to false. type: int - name: - description: Name of the reserve IP subpool. - type: str prev_name: description: The former name associated with the reserved IP sub-pool. type: str - site_name: - description: > - The name of the site provided as a path parameter, used - to specify where the IP sub-pool will be reserved. - type: str slaac_support: description: > Allows devices on IPv6 networks to self-configure their IP addresses autonomously, eliminating the need for manual setup. type: bool - pool_type: - description: Type of the reserve ip sub pool. - Generic - Used for general purpose within the network such as device - management or communication between the network devices. - LAN - Used for the devices and the resources within the Local Area Network - such as device connectivity, internal communication, or services. - Management - Used for the management purposes such as device management interfaces, - management access, or other administrative functions. - Service - Used for the network services and application such as DNS (Domain Name System), - DHCP (Dynamic Host Configuration Protocol), NTP (Network Time Protocol). - WAN - Used for the devices and resources with the Wide Area Network such as remote - sites interconnection with other network or services hosted within WAN. - default: Generic - choices: [Generic, LAN, Management, Service, WAN] - type: str network_management_details: description: Set default network settings for the site type: dict suboptions: + site_name: + description: > + The name of the site provided as a path parameter, used + to specify where the IP sub-pool will be reserved. + type: str settings: description: Network management details settings. type: dict suboptions: + network_aaa: + description: Network V2's network_aaa. + suboptions: + ip_address: + description: IP address for AAA and ISE server (eg 1.1.1.1). + type: str + network: + description: IP Address for AAA or ISE server (eg 2.2.2.2). + type: str + protocol: + description: Protocol for AAA or ISE serve (eg RADIUS). + type: str + servers: + description: Server type for AAA Network (eg AAA). + type: str + shared_secret: + description: Shared secret for ISE Server. + type: str + type: dict client_and_endpoint_aaa: description: Network V2's clientAndEndpoint_aaa. suboptions: @@ -243,6 +282,13 @@ description: Secondary IP Address for DHCP (eg 3.3.3.3). type: str type: dict + ntp_server: + description: IP address for NTP server (eg 1.1.1.2). + elements: str + type: list + timezone: + description: Input for time zone (eg Africa/Abidjan). + type: str message_of_the_day: description: Network V2's messageOfTheday. suboptions: @@ -263,29 +309,6 @@ description: Port for NetFlow Collector (eg; 443). type: int type: dict - network_aaa: - description: Network V2's network_aaa. - suboptions: - ip_address: - description: IP address for AAA and ISE server (eg 1.1.1.1). - type: str - network: - description: IP Address for AAA or ISE server (eg 2.2.2.2). - type: str - protocol: - description: Protocol for AAA or ISE serve (eg RADIUS). - type: str - servers: - description: Server type for AAA Network (eg AAA). - type: str - shared_secret: - description: Shared secret for ISE Server. - type: str - type: dict - ntp_server: - description: IP address for NTP server (eg 1.1.1.2). - elements: str - type: list snmp_server: description: Network V2's snmpServer. suboptions: @@ -308,16 +331,8 @@ elements: str type: list type: dict - timezone: - description: Input for time zone (eg Africa/Abidjan). - type: str - site_name: - description: > - The name of the site provided as a path parameter, used - to specify where the IP sub-pool will be reserved. - type: str requirements: -- dnacentersdk == 2.4.5 +- dnacentersdk >= 2.4.5 - python >= 3.9 notes: - SDK Method used are @@ -341,7 +356,7 @@ """ EXAMPLES = r""" -- name: Create global pool, reserve an ip pool and network +- name: Create global pool cisco.dnac.network_settings_workflow_manager: dnac_host: "{{dnac_host}}" dnac_username: "{{dnac_username}}" @@ -359,55 +374,133 @@ settings: ip_pool: - name: string - gateway: string + pool_type: Generic ip_address_space: string cidr: string - pool_type: Generic + gateway: string dhcp_server_ips: list dns_server_ips: list - reserve_pool_details: + +- name: Create reserve an ip pool + cisco.dnac.network_settings_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - reserve_pool_details: + - site_name: string + name: string + pool_type: LAN ipv6_address_space: True ipv4_global_pool: string ipv4_prefix: True ipv4_prefix_length: 9 ipv4_subnet: string - name: string ipv6_prefix: True ipv6_prefix_length: 64 ipv6_global_pool: string ipv6_subnet: string - site_name: string slaac_support: True + +- name: Create reserve an ip pool using global pool name + cisco.dnac.network_settings_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - reserve_pool_details: + - name: string + site_name: string pool_type: LAN - network_management_details: + ipv6_address_space: True + ipv4_global_pool_name: string + ipv4_prefix: True + ipv4_prefix_length: 9 + ipv4_subnet: string + ipv6_prefix: True + ipv6_prefix_length: 64 + ipv6_global_pool_name: string + ipv6_subnet: string + slaac_support: True + +- name: Delete reserved pool + cisco.dnac.network_settings_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: deleted + config_verify: True + config: + - reserve_pool_details: + - site_name: string + name: string + +- name: Manage the network functions + cisco.dnac.network_settings_workflow_manager: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + dnac_log: True + dnac_log_level: "{{ dnac_log_level }}" + state: merged + config_verify: True + config: + - network_management_details: + site_name: string settings: + network_aaa: + network: string + protocol: string + servers: string + client_and_endpoint_aaa: + network: string + protocol: string + servers: string dhcp_server: list dns_server: domain_name: string primary_ip_address: string secondary_ip_address: string - client_and_endpoint_aaa: - network: string - protocol: string - servers: string + ntp_server: list + timezone: string message_of_the_day: banner_message: string retain_existing_banner: string netflow_collector: ip_address: string port: 443 - network_aaa: - network: string - protocol: string - servers: string - ntp_server: list snmp_server: configure_dnac_ip: True ip_addresses: list syslog_server: configure_dnac_ip: True ip_addresses: list - site_name: string """ RETURN = r""" @@ -499,6 +592,7 @@ def validate_input(self): "type": 'dict', "ip_pool": { "type": 'list', + "elements": 'dict', "ip_address_space": {"type": 'string'}, "dhcp_server_ips": {"type": 'list'}, "dns_server_ips": {"type": 'list'}, @@ -511,7 +605,8 @@ def validate_input(self): } }, "reserve_pool_details": { - "type": 'dict', + "type": 'list', + "elements": 'dict', "name": {"type": 'string'}, "prev_name": {"type": 'string'}, "ipv6_address_space": {"type": 'bool'}, @@ -653,7 +748,10 @@ def get_obj_params(self, get_object): try: if get_object == "GlobalPool": obj_params = [ - ("settings", "settings"), + ("IpAddressSpace", "IpAddressSpace"), + ("dhcpServerIps", "dhcpServerIps"), + ("dnsServerIps", "dnsServerIps"), + ("gateway", "gateway"), ] elif get_object == "ReservePool": obj_params = [ @@ -737,28 +835,24 @@ def get_global_pool_params(self, pool_info): self.log("Global Pool Details: {0}".format(pool_info), "DEBUG") global_pool = { - "settings": { - "ippool": [{ - "dhcpServerIps": pool_info.get("dhcpServerIps"), - "dnsServerIps": pool_info.get("dnsServerIps"), - "ipPoolCidr": pool_info.get("ipPoolCidr"), - "ipPoolName": pool_info.get("ipPoolName"), - "type": pool_info.get("ipPoolType").capitalize() - }] - } + "dhcpServerIps": pool_info.get("dhcpServerIps"), + "dnsServerIps": pool_info.get("dnsServerIps"), + "ipPoolCidr": pool_info.get("ipPoolCidr"), + "ipPoolName": pool_info.get("ipPoolName"), + "type": pool_info.get("ipPoolType").capitalize() } self.log("Formated global pool details: {0}".format(global_pool), "DEBUG") - global_ippool = global_pool.get("settings").get("ippool")[0] + # global_ippool = global_pool.get("settings").get("ippool")[0] if pool_info.get("ipv6") is False: - global_ippool.update({"IpAddressSpace": "IPv4"}) + global_pool.update({"IpAddressSpace": "IPv4"}) else: - global_ippool.update({"IpAddressSpace": "IPv6"}) + global_pool.update({"IpAddressSpace": "IPv6"}) - self.log("ip_address_space: {0}".format(global_ippool.get("IpAddressSpace")), "DEBUG") + self.log("ip_address_space: {0}".format(global_pool.get("IpAddressSpace")), "DEBUG") if not pool_info["gateways"]: - global_ippool.update({"gateway": ""}) + global_pool.update({"gateway": ""}) else: - global_ippool.update({"gateway": pool_info.get("gateways")[0]}) + global_pool.update({"gateway": pool_info.get("gateways")[0]}) return global_pool @@ -981,6 +1075,14 @@ def get_network_params(self, site_id): } }) + network_settings_snmp = network_settings.get("snmpServer") + if not network_settings_snmp.get("ipAddresses"): + network_settings_snmp.update({"ipAddresses": []}) + + network_settings_syslog = network_settings.get("syslogServer") + if not network_settings_syslog.get("ipAddresses"): + network_settings_syslog.update({"ipAddresses": []}) + self.log("Formatted playbook network details: {0}".format(network_details), "DEBUG") return network_details @@ -1003,25 +1105,32 @@ def global_pool_exists(self, name): "details": None, "id": None } - response = self.dnac._exec( - family="network_settings", - function="get_global_pool", - ) - if not isinstance(response, dict): - self.log("Failed to retrieve the global pool details - " - "Response is not a dictionary", "CRITICAL") - return global_pool - - all_global_pool_details = response.get("response") - global_pool_details = get_dict_result(all_global_pool_details, "ipPoolName", name) - self.log("Global ip pool name: {0}".format(name), "DEBUG") - self.log("Global pool details: {0}".format(global_pool_details), "DEBUG") - if not global_pool_details: - self.log("Global pool {0} does not exist".format(name), "INFO") - return global_pool - global_pool.update({"exists": True}) - global_pool.update({"id": global_pool_details.get("id")}) - global_pool["details"] = self.get_global_pool_params(global_pool_details) + value = 1 + while True: + response = self.dnac._exec( + family="network_settings", + function="get_global_pool", + params={"offset": value} + ) + value += 25 + if not isinstance(response, dict): + self.msg = "Failed to retrieve the global pool details - Response is not a dictionary" + self.log(self.msg, "CRITICAL") + self.status = "failed" + return self.check_return_status() + + all_global_pool_details = response.get("response") + if not all_global_pool_details: + self.log("Global pool '{0}' does not exist".format(name), "INFO") + return global_pool + + global_pool_details = get_dict_result(all_global_pool_details, "ipPoolName", name) + if global_pool_details: + self.log("Global pool found with name '{0}': {1}".format(name, global_pool_details), "INFO") + global_pool.update({"exists": True}) + global_pool.update({"id": global_pool_details.get("id")}) + global_pool["details"] = self.get_global_pool_params(global_pool_details) + break self.log("Formatted global pool details: {0}".format(global_pool), "DEBUG") return global_pool @@ -1060,7 +1169,7 @@ def reserve_pool_exists(self, name, site_name): family="network_settings", function="get_reserve_ip_subpool", op_modifies=True, - params={"siteId": site_id} + params={"site_id": site_id} ) if not isinstance(response, dict): reserve_pool.update({"success": False}) @@ -1083,25 +1192,20 @@ def reserve_pool_exists(self, name, site_name): self.log("Reserved pool id: {0}".format(reserve_pool.get("id")), "DEBUG") return reserve_pool - def get_have_global_pool(self, config): + def get_have_global_pool(self, global_pool_details): """ Get the current Global Pool information from Cisco Catalyst Center based on the provided playbook details. check this API using check_return_status. Parameters: - config (dict) - Playbook details containing Global Pool configuration. + global_pool_details (dict) - Playbook details containing Global Pool configuration. Returns: self - The current object with updated information. """ - global_pool = { - "exists": False, - "details": None, - "id": None - } - global_pool_settings = config.get("global_pool_details").get("settings") + global_pool_settings = global_pool_details.get("settings") if global_pool_settings is None: self.msg = "settings in global_pool_details is missing in the playbook" self.status = "failed" @@ -1113,120 +1217,120 @@ def get_have_global_pool(self, config): self.status = "failed" return self - name = global_pool_ippool[0].get("name") - if name is None: - self.msg = "Mandatory Parameter name required" - self.status = "failed" - return self - - # If the Global Pool doesn't exist and a previous name is provided - # Else try using the previous name - global_pool = self.global_pool_exists(name) - self.log("Global pool details: {0}".format(global_pool), "DEBUG") - prev_name = global_pool_ippool[0].get("prev_name") - if global_pool.get("exists") is False and \ - prev_name is not None: - global_pool = self.global_pool_exists(prev_name) - if global_pool.get("exists") is False: - self.msg = "Prev name {0} doesn't exist in global_pool_details".format(prev_name) + global_pool = [] + global_pool_index = 0 + for pool_details in global_pool_ippool: + name = pool_details.get("name") + if name is None: + self.msg = "Mandatory Parameter name '{0}' required for global pool".format(name) self.status = "failed" return self - self.log("Global pool exists: {0}".format(global_pool.get("exists")), "DEBUG") - self.log("Current Site: {0}".format(global_pool.get("details")), "DEBUG") + # If the Global Pool doesn't exist and a previous name is provided + # Else try using the previous name + global_pool.append(self.global_pool_exists(name)) + self.log("Global pool details of '{0}': {1}".format(name, global_pool[global_pool_index]), "DEBUG") + prev_name = pool_details.get("prev_name") + if global_pool[global_pool_index].get("exists") is False and \ + prev_name is not None: + global_pool.append(self.global_pool_exists(prev_name)) + if global_pool.get("exists") is False: + self.msg = "Prev name {0} doesn't exist in global_pool_details".format(prev_name) + self.status = "failed" + return self + global_pool_index += 1 + + self.log("Global pool details: {0}".format(global_pool), "DEBUG") self.have.update({"globalPool": global_pool}) self.msg = "Collecting the global pool details from the Cisco Catalyst Center" self.status = "success" return self - def get_have_reserve_pool(self, config): + def get_have_reserve_pool(self, reserve_pool_details): """ Get the current Reserved Pool information from Cisco Catalyst Center based on the provided playbook details. Check this API using check_return_status Parameters: - config (list of dict) - Playbook details containing Reserved Pool configuration. + reserve_pool_details (list of dict) - Playbook details containing Reserved Pool configuration. Returns: self - The current object with updated information. """ - reserve_pool = { - "exists": False, - "details": None, - "id": None - } - reserve_pool_details = config.get("reserve_pool_details") - name = reserve_pool_details.get("name") - if name is None: - self.msg = "Mandatory Parameter name required in reserve_pool_details\n" - self.status = "failed" - return self - - site_name = reserve_pool_details.get("site_name") - self.log("Site Name: {0}".format(site_name), "DEBUG") - if site_name is None: - self.msg = "Missing parameter 'site_name' in reserve_pool_details" - self.status = "failed" - return self - - # Check if the Reserved Pool exists in Cisco Catalyst Center - # based on the provided name and site name - reserve_pool = self.reserve_pool_exists(name, site_name) - if not reserve_pool.get("success"): - return self.check_return_status() - self.log("Reserved pool details: {0}".format(reserve_pool), "DEBUG") + reserve_pool = [] + reserve_pool_index = 0 + for item in reserve_pool_details: + name = item.get("name") + if name is None: + self.msg = "Mandatory Parameter name required in reserve_pool_details." + self.status = "failed" + return self + site_name = item.get("site_name") + self.log("Site Name: {0}".format(site_name), "DEBUG") + if site_name is None: + self.msg = "Missing parameter 'site_name' in reserve_pool_details" + self.status = "failed" + return self - # If the Reserved Pool doesn't exist and a previous name is provided - # Else try using the previous name - prev_name = reserve_pool_details.get("prev_name") - if reserve_pool.get("exists") is False and \ - prev_name is not None: - reserve_pool = self.reserve_pool_exists(prev_name, site_name) - if not reserve_pool.get("success"): + # Check if the Reserved Pool exists in Cisco Catalyst Center + # based on the provided name and site name + reserve_pool.append(self.reserve_pool_exists(name, site_name)) + if not reserve_pool[reserve_pool_index].get("success"): return self.check_return_status() + self.log("Reserved pool details for '{0}': {1}".format(name, reserve_pool[reserve_pool_index]), "DEBUG") + + # If the Reserved Pool doesn't exist and a previous name is provided + # Else try using the previous name + prev_name = item.get("prev_name") + if reserve_pool[reserve_pool_index].get("exists") is False and \ + prev_name is not None: + reserve_pool.append(self.reserve_pool_exists(prev_name, site_name)) + if not reserve_pool[reserve_pool_index].get("success"): + return self.check_return_status() + + # If the previous name doesn't exist in Cisco Catalyst Center, return with error + if reserve_pool[reserve_pool_index].get("exists") is False: + self.msg = "Prev name {0} doesn't exist in reserve_pool_details".format(prev_name) + self.status = "failed" + return self - # If the previous name doesn't exist in Cisco Catalyst Center, return with error - if reserve_pool.get("exists") is False: - self.msg = "Prev name {0} doesn't exist in reserve_pool_details".format(prev_name) - self.status = "failed" - return self + self.log("Reserved pool exists: {0}".format(reserve_pool[reserve_pool_index].get("exists")), "DEBUG") + self.log("Reserved pool: {0}".format(reserve_pool[reserve_pool_index].get("details")), "DEBUG") - self.log("Reserved pool exists: {0}".format(reserve_pool.get("exists")), "DEBUG") - self.log("Reserved pool: {0}".format(reserve_pool.get("details")), "DEBUG") + # If reserve pool exist, convert ipv6AddressSpace to the required format (boolean) + if reserve_pool[reserve_pool_index].get("exists"): + reserve_pool_info = reserve_pool[reserve_pool_index].get("details") + if reserve_pool_info.get("ipv6AddressSpace") == "False": + reserve_pool_info.update({"ipv6AddressSpace": False}) + else: + reserve_pool_info.update({"ipv6AddressSpace": True}) - # If reserve pool exist, convert ipv6AddressSpace to the required format (boolean) - if reserve_pool.get("exists"): - reserve_pool_details = reserve_pool.get("details") - if reserve_pool_details.get("ipv6AddressSpace") == "False": - reserve_pool_details.update({"ipv6AddressSpace": False}) - else: - reserve_pool_details.update({"ipv6AddressSpace": True}) + reserve_pool_index += 1 self.log("Reserved pool details: {0}".format(reserve_pool), "DEBUG") self.have.update({"reservePool": reserve_pool}) - self.msg = "Collecting the reserve pool details from the Cisco Catalyst Center" + self.msg = "Collected the reserve pool details from the Cisco Catalyst Center" self.status = "success" return self - def get_have_network(self, config): + def get_have_network(self, network_details): """ Get the current Network details from Cisco Catalyst Center based on the provided playbook details. Parameters: - config (dict) - Playbook details containing Network Management configuration. + network_details (dict) - Playbook details containing Network Management configuration. Returns: self - The current object with updated Network information. """ network = {} - site_name = config.get("network_management_details").get("site_name") + site_name = network_details.get("site_name") if site_name is None: - self.msg = "Mandatory Parameter 'site_name' missing" - self.status = "failed" - return self + site_name = "Global" + network_details.update({"site_name": site_name}) site_id = self.get_site_id(site_name) if site_id is None: @@ -1255,20 +1359,73 @@ def get_have(self, config): Reserved Pool, and Network information. """ - if config.get("global_pool_details") is not None: - self.get_have_global_pool(config).check_return_status() + global_pool_details = config.get("global_pool_details") + if global_pool_details is not None: + self.get_have_global_pool(global_pool_details).check_return_status() - if config.get("reserve_pool_details") is not None: - self.get_have_reserve_pool(config).check_return_status() + reserve_pool_details = config.get("reserve_pool_details") + if reserve_pool_details is not None: + self.get_have_reserve_pool(reserve_pool_details).check_return_status() - if config.get("network_management_details") is not None: - self.get_have_network(config).check_return_status() + network_details = config.get("network_management_details") + if network_details is not None: + self.get_have_network(network_details).check_return_status() self.log("Current State (have): {0}".format(self.have), "INFO") self.msg = "Successfully retrieved the details from the Cisco Catalyst Center" self.status = "success" return self + def get_global_pool_cidr(self, global_pool_cidr, global_pool_name): + """ + Get the Ipv4 or Ipv6 global pool cidr from the global pool name. + + Parameters: + global_pool_cidr (dict) - Global pool cidr value of the current item. + global_pool_name (dict) - Global pool name of the current item. + + Returns: + global_pool_cidr (str) - Global pool cidr value of the current item. + """ + + if global_pool_cidr: + return global_pool_cidr + + if not global_pool_name: + self.msg = "Missing parameter 'Global Pool CIDR' or 'Global Pool name' is mandatory under reserve_pool_details." + self.status = "failed" + return self.check_return_status() + + value = 1 + while True: + response = self.dnac._exec( + family="network_settings", + function="get_global_pool", + params={"offset": value} + ) + value += 25 + if not isinstance(response, dict): + self.msg = "Failed to retrieve the global pool details - Response is not a dictionary" + self.log(self.msg, "CRITICAL") + self.status = "failed" + return self.check_return_status() + + all_global_pool_details = response.get("response") + if not all_global_pool_details: + self.log("Invalid global_pool_name '{0}' under reserve_pool_details".format(global_pool_name), "ERROR") + self.msg = "No information found for the global pool named '{0}'".format(global_pool_name) + self.status = "failed" + return self.check_return_status() + + global_pool_details = get_dict_result(all_global_pool_details, "ipPoolName", global_pool_name) + if global_pool_details: + global_pool_cidr = global_pool_details.get("ipPoolCidr") + self.log("Global pool found with name '{0}': {1}".format(global_pool_name, global_pool_details), "INFO") + break + + self.log("Global Pool '{0}' cidr: {1}".format(global_pool_name, global_pool_cidr), "INFO") + return global_pool_cidr + def get_want_global_pool(self, global_ippool): """ Get all the Global Pool information from playbook @@ -1286,47 +1443,48 @@ def get_want_global_pool(self, global_ippool): # Initialize the desired Global Pool configuration want_global = { "settings": { - "ippool": [{ - "IpAddressSpace": global_ippool.get("ip_address_space"), - "dhcpServerIps": global_ippool.get("dhcp_server_ips"), - "dnsServerIps": global_ippool.get("dns_server_ips"), - "ipPoolName": global_ippool.get("name"), - "ipPoolCidr": global_ippool.get("cidr"), - "gateway": global_ippool.get("gateway"), - "type": global_ippool.get("pool_type"), - }] + "ippool": [] } } - want_ippool = want_global.get("settings").get("ippool")[0] - - # Converting to the required format based on the existing Global Pool - if not self.have.get("globalPool").get("exists"): - if want_ippool.get("dhcpServerIps") is None: - want_ippool.update({"dhcpServerIps": []}) - if want_ippool.get("dnsServerIps") is None: - want_ippool.update({"dnsServerIps": []}) - if want_ippool.get("IpAddressSpace") is None: - want_ippool.update({"IpAddressSpace": ""}) - if want_ippool.get("gateway") is None: - want_ippool.update({"gateway": ""}) - if want_ippool.get("type") is None: - want_ippool.update({"type": "Generic"}) - else: - have_ippool = self.have.get("globalPool").get("details") \ - .get("settings").get("ippool")[0] - - # Copy existing Global Pool information if the desired configuration is not provided - want_ippool.update({ - "IpAddressSpace": have_ippool.get("IpAddressSpace"), - "type": have_ippool.get("type"), - "ipPoolCidr": have_ippool.get("ipPoolCidr") - }) - want_ippool.update({}) - want_ippool.update({}) - - for key in ["dhcpServerIps", "dnsServerIps", "gateway"]: - if want_ippool.get(key) is None and have_ippool.get(key) is not None: - want_ippool[key] = have_ippool[key] + want_ippool = want_global.get("settings").get("ippool") + global_pool_index = 0 + for pool_details in global_ippool: + pool_values = { + "IpAddressSpace": pool_details.get("ip_address_space"), + "dhcpServerIps": pool_details.get("dhcp_server_ips"), + "dnsServerIps": pool_details.get("dns_server_ips"), + "ipPoolName": pool_details.get("name"), + "ipPoolCidr": pool_details.get("cidr"), + "gateway": pool_details.get("gateway"), + "type": pool_details.get("pool_type"), + } + # Converting to the required format based on the existing Global Pool + if not self.have.get("globalPool")[global_pool_index].get("exists"): + if pool_values.get("dhcpServerIps") is None: + pool_values.update({"dhcpServerIps": []}) + if pool_values.get("dnsServerIps") is None: + pool_values.update({"dnsServerIps": []}) + if pool_values.get("IpAddressSpace") is None: + pool_values.update({"IpAddressSpace": ""}) + if pool_values.get("gateway") is None: + pool_values.update({"gateway": ""}) + if pool_values.get("type") is None: + pool_values.update({"type": "Generic"}) + else: + have_ippool = self.have.get("globalPool")[global_pool_index].get("details") + + # Copy existing Global Pool information if the desired configuration is not provided + pool_values.update({ + "IpAddressSpace": have_ippool.get("IpAddressSpace"), + "type": have_ippool.get("type"), + "ipPoolCidr": have_ippool.get("ipPoolCidr"), + "id": self.have.get("globalPool")[global_pool_index].get("id") + }) + for key in ["dhcpServerIps", "dnsServerIps", "gateway"]: + if pool_values.get(key) is None and have_ippool.get(key) is not None: + pool_values[key] = have_ippool[key] + want_ippool.append(pool_values) + global_pool_index += 1 self.log("Global pool playbook details: {0}".format(want_global), "DEBUG") self.want.update({"wantGlobal": want_global}) @@ -1348,101 +1506,113 @@ def get_want_reserve_pool(self, reserve_pool): self - The current object with updated desired Reserved Pool information. """ - want_reserve = { - "name": reserve_pool.get("name"), - "type": reserve_pool.get("pool_type"), - "ipv6AddressSpace": reserve_pool.get("ipv6_address_space"), - "ipv4GlobalPool": reserve_pool.get("ipv4_global_pool"), - "ipv4Prefix": reserve_pool.get("ipv4_prefix"), - "ipv4PrefixLength": reserve_pool.get("ipv4_prefix_length"), - "ipv4GateWay": reserve_pool.get("ipv4_gateway"), - "ipv4DhcpServers": reserve_pool.get("ipv4_dhcp_servers"), - "ipv4DnsServers": reserve_pool.get("ipv4_dns_servers"), - "ipv4Subnet": reserve_pool.get("ipv4_subnet"), - "ipv6GlobalPool": reserve_pool.get("ipv6_global_pool"), - "ipv6Prefix": reserve_pool.get("ipv6_prefix"), - "ipv6PrefixLength": reserve_pool.get("ipv6_prefix_length"), - "ipv6GateWay": reserve_pool.get("ipv6_gateway"), - "ipv6DhcpServers": reserve_pool.get("ipv6_dhcp_servers"), - "ipv6Subnet": reserve_pool.get("ipv6_subnet"), - "ipv6DnsServers": reserve_pool.get("ipv6_dns_servers"), - "ipv4TotalHost": reserve_pool.get("ipv4_total_host"), - "ipv6TotalHost": reserve_pool.get("ipv6_total_host") - } - - # Check for missing mandatory parameters in the playbook - if not want_reserve.get("name"): - self.msg = "Missing mandatory parameter 'name' in reserve_pool_details" - self.status = "failed" - return self - - if want_reserve.get("ipv4Prefix") is True: - if want_reserve.get("ipv4Subnet") is None and \ - want_reserve.get("ipv4TotalHost") is None: - self.msg = "missing parameter 'ipv4_subnet' or 'ipv4TotalHost' \ - while adding the ipv4 in reserve_pool_details" + want_reserve = [] + reserve_pool_index = 0 + for item in reserve_pool: + pool_values = { + "name": item.get("name"), + "type": item.get("pool_type"), + "ipv6AddressSpace": item.get("ipv6_address_space"), + "ipv4GlobalPool": self.get_global_pool_cidr(item.get("ipv4_global_pool"), + item.get("ipv4_global_pool_name")), + "ipv4Prefix": item.get("ipv4_prefix"), + "ipv4PrefixLength": item.get("ipv4_prefix_length"), + "ipv4GateWay": item.get("ipv4_gateway"), + "ipv4DhcpServers": item.get("ipv4_dhcp_servers"), + "ipv4DnsServers": item.get("ipv4_dns_servers"), + "ipv4Subnet": item.get("ipv4_subnet"), + "ipv6Prefix": item.get("ipv6_prefix"), + "ipv6PrefixLength": item.get("ipv6_prefix_length"), + "ipv6GateWay": item.get("ipv6_gateway"), + "ipv6DhcpServers": item.get("ipv6_dhcp_servers"), + "ipv6Subnet": item.get("ipv6_subnet"), + "ipv6DnsServers": item.get("ipv6_dns_servers"), + "ipv4TotalHost": item.get("ipv4_total_host"), + "ipv6TotalHost": item.get("ipv6_total_host") + } + # Check for missing mandatory parameters in the playbook + if pool_values.get("ipv6AddressSpace") is True: + pool_values.update({ + "ipv6GlobalPool": self.get_global_pool_cidr(item.get("ipv6_global_pool"), + item.get("ipv6_global_pool_name"))}) + + if not pool_values.get("name"): + self.msg = "Missing mandatory parameter 'name' in reserve_pool_details '{0}' element" \ + .format(reserve_pool_index + 1) self.status = "failed" return self - if want_reserve.get("ipv6Prefix") is True: - if want_reserve.get("ipv6Subnet") is None and \ - want_reserve.get("ipv6TotalHost") is None: - self.msg = "missing parameter 'ipv6_subnet' or 'ipv6TotalHost' \ - while adding the ipv6 in reserve_pool_details" - self.status = "failed" - return self + if pool_values.get("ipv4Prefix") is True: + if pool_values.get("ipv4Subnet") is None and \ + pool_values.get("ipv4TotalHost") is None: + self.msg = "Failed to add IPv4 in reserve_pool_details '{0}'. ".format(reserve_pool_index + 1) + \ + "Required parameters 'ipv4_subnet' or 'ipv4_total_host' are missing." + self.status = "failed" + return self - self.log("Reserved IP pool playbook details: {0}".format(want_reserve), "DEBUG") + if pool_values.get("ipv6Prefix") is True: + if pool_values.get("ipv6Subnet") is None and \ + pool_values.get("ipv6TotalHost") is None: + self.msg = "Failed to add IPv6 in reserve_pool_details '{0}'. ".format(reserve_pool_index + 1) + \ + "Required parameters 'ipv6_subnet' or 'ipv6_total_host' are missing." + self.status = "failed" + return self - # If there are no existing Reserved Pool details, validate and set defaults - if not self.have.get("reservePool").get("details"): - if not want_reserve.get("ipv4GlobalPool"): - self.msg = "missing parameter 'ipv4GlobalPool' in reserve_pool_details" - self.status = "failed" - return self + self.log("Reserved IP pool playbook details: {0}".format(pool_values), "DEBUG") - if not want_reserve.get("ipv4PrefixLength"): - self.msg = "missing parameter 'ipv4_prefix_length' in reserve_pool_details" - self.status = "failed" - return self + # If there are no existing Reserved Pool details, validate and set defaults + if not self.have.get("reservePool")[reserve_pool_index].get("details"): + if not pool_values.get("ipv4GlobalPool"): + self.msg = "missing parameter 'ipv4GlobalPool' in reserve_pool_details '{0}' element" \ + .format(reserve_pool_index + 1) + self.status = "failed" + return self + + if not pool_values.get("ipv4PrefixLength"): + self.msg = "missing parameter 'ipv4_prefix_length' in reserve_pool_details '{0}' element" \ + .format(reserve_pool_index + 1) + self.status = "failed" + return self - if want_reserve.get("type") is None: - want_reserve.update({"type": "Generic"}) - if want_reserve.get("ipv4GateWay") is None: - want_reserve.update({"ipv4GateWay": ""}) - if want_reserve.get("ipv4DhcpServers") is None: - want_reserve.update({"ipv4DhcpServers": []}) - if want_reserve.get("ipv4DnsServers") is None: - want_reserve.update({"ipv4DnsServers": []}) - if want_reserve.get("ipv6AddressSpace") is None: - want_reserve.update({"ipv6AddressSpace": False}) - if want_reserve.get("slaacSupport") is None: - want_reserve.update({"slaacSupport": True}) - if want_reserve.get("ipv4TotalHost") is None: - del want_reserve['ipv4TotalHost'] - if want_reserve.get("ipv6AddressSpace") is True: - want_reserve.update({"ipv6Prefix": True}) + if pool_values.get("type") is None: + pool_values.update({"type": "Generic"}) + if pool_values.get("ipv4GateWay") is None: + pool_values.update({"ipv4GateWay": ""}) + if pool_values.get("ipv4DhcpServers") is None: + pool_values.update({"ipv4DhcpServers": []}) + if pool_values.get("ipv4DnsServers") is None: + pool_values.update({"ipv4DnsServers": []}) + if pool_values.get("ipv6AddressSpace") is None: + pool_values.update({"ipv6AddressSpace": False}) + if pool_values.get("slaacSupport") is None: + pool_values.update({"slaacSupport": True}) + if pool_values.get("ipv4TotalHost") is None: + del pool_values['ipv4TotalHost'] + if pool_values.get("ipv6AddressSpace") is True: + pool_values.update({"ipv6Prefix": True}) + else: + del pool_values['ipv6Prefix'] + + if not pool_values.get("ipv6AddressSpace"): + keys_to_check = ['ipv6PrefixLength', 'ipv6GateWay', 'ipv6DhcpServers', + 'ipv6DnsServers', 'ipv6TotalHost'] + for key in keys_to_check: + if pool_values.get(key) is None: + del pool_values[key] else: - del want_reserve['ipv6Prefix'] - - if not want_reserve.get("ipv6AddressSpace"): - keys_to_check = ['ipv6GlobalPool', 'ipv6PrefixLength', - 'ipv6GateWay', 'ipv6DhcpServers', - 'ipv6DnsServers', 'ipv6TotalHost'] - for key in keys_to_check: - if want_reserve.get(key) is None: - del want_reserve[key] - else: - keys_to_delete = ['type', 'ipv4GlobalPool', - 'ipv4Prefix', 'ipv4PrefixLength', - 'ipv4TotalHost', 'ipv4Subnet'] - for key in keys_to_delete: - if key in want_reserve: - del want_reserve[key] + keys_to_delete = ['type', 'ipv4GlobalPool', + 'ipv4Prefix', 'ipv4PrefixLength', + 'ipv4TotalHost', 'ipv4Subnet'] + for key in keys_to_delete: + if key in pool_values: + del pool_values[key] + + want_reserve.append(pool_values) + reserve_pool_index += 1 self.want.update({"wantReserve": want_reserve}) - self.log("Desired State (want): {0}".format(self.want), "INFO") - self.msg = "Collecting the reserve pool details from the playbook" + self.log("Reserved Pool details: {0}".format(want_reserve), "INFO") + self.msg = "Collected the reserved pool details from the playbook" self.status = "success" return self @@ -1635,8 +1805,7 @@ def get_want_network(self, network_management_details): }) else: if clientAndEndpoint_aaa.get("servers") == "ISE": - self.msg = "missing parameter ip_address in clientAndEndpoint_aaa, \ - server ISE is set" + self.msg = "Failed to process client_and_endpoint_aaa due to missing 'ip_address' parameter. ISE server is configured." self.status = "failed" return self @@ -1646,7 +1815,7 @@ def get_want_network(self, network_management_details): clientAndEndpoint_aaa.get("network") }) else: - self.msg = "missing parameter network in clientAndEndpoint_aaa" + self.msg = "Failed to process client_and_endpoint_aaa due to missing parameter 'network' in the playbook." self.status = "failed" return self @@ -1656,7 +1825,7 @@ def get_want_network(self, network_management_details): clientAndEndpoint_aaa.get("protocol") }) else: - self.msg = "missing parameter protocol in clientAndEndpoint_aaa" + self.msg = "Failed to process client_and_endpoint_aaa due to missing parameter 'protocol' in the playbook." self.status = "failed" return self @@ -1666,7 +1835,7 @@ def get_want_network(self, network_management_details): clientAndEndpoint_aaa.get("servers") }) else: - self.msg = "missing parameter servers in clientAndEndpoint_aaa" + self.msg = "Failed to process client_and_endpoint_aaa due to missing parameter 'servers' in the playbook." self.status = "failed" return self @@ -1680,7 +1849,7 @@ def get_want_network(self, network_management_details): self.log("Network playbook details: {0}".format(want_network), "DEBUG") self.want.update({"wantNetwork": want_network}) - self.msg = "Collecting the network details from the playbook" + self.msg = "Collected the network details from the playbook" self.status = "success" return self @@ -1696,7 +1865,7 @@ def get_want(self, config): """ if config.get("global_pool_details"): - global_ippool = config.get("global_pool_details").get("settings").get("ip_pool")[0] + global_ippool = config.get("global_pool_details").get("settings").get("ip_pool") self.get_want_global_pool(global_ippool).check_return_status() if config.get("reserve_pool_details"): @@ -1713,26 +1882,41 @@ def get_want(self, config): self.status = "success" return self - def update_global_pool(self, config): + def update_global_pool(self, global_pool): """ Update/Create Global Pool in Cisco Catalyst Center with fields provided in playbook Parameters: - config (list of dict) - Playbook details + global_pool (list of dict) - Global Pool playbook details Returns: None """ - name = config.get("global_pool_details") \ - .get("settings").get("ip_pool")[0].get("name") + create_global_pool = [] + update_global_pool = [] + global_pool_index = 0 result_global_pool = self.result.get("response")[0].get("globalPool") - result_global_pool.get("response").update({name: {}}) + want_global_pool = self.want.get("wantGlobal").get("settings").get("ippool") + self.log("Global pool playbook details: {0}".format(global_pool), "DEBUG") + for item in self.have.get("globalPool"): + result_global_pool.get("msg") \ + .update({want_global_pool[global_pool_index].get("ipPoolName"): {}}) + if item.get("exists") is True: + update_global_pool.append(want_global_pool[global_pool_index]) + else: + create_global_pool.append(want_global_pool[global_pool_index]) - # Check pool exist, if not create and return - if not self.have.get("globalPool").get("exists"): - pool_params = self.want.get("wantGlobal") - self.log("Desired State for global pool (want): {0}".format(pool_params), "DEBUG") + global_pool_index += 1 + + # Check create_global_pool; if yes, create the global pool + if create_global_pool: + self.log("Global pool(s) details to be created: {0}".format(create_global_pool), "INFO") + pool_params = { + "settings": { + "ippool": copy.deepcopy(create_global_pool) + } + } response = self.dnac._exec( family="network_settings", function="create_global_pool", @@ -1740,133 +1924,139 @@ def update_global_pool(self, config): params=pool_params, ) self.check_execution_response_status(response).check_return_status() - self.log("Successfully created global pool '{0}'.".format(name), "INFO") - result_global_pool.get("response").get(name) \ - .update({"globalPool Details": self.want.get("wantGlobal")}) - result_global_pool.get("msg").update({name: "Global Pool Created Successfully"}) - return - - # Pool exists, check update is required - if not self.requires_update(self.have.get("globalPool").get("details"), - self.want.get("wantGlobal"), self.global_pool_obj_params): - self.log("Global pool '{0}' doesn't require an update".format(name), "INFO") - result_global_pool.get("response").get(name).update({ - "Cisco Catalyst Center params": - self.have.get("globalPool").get("details").get("settings").get("ippool")[0] - }) - result_global_pool.get("response").get(name).update({ - "Id": self.have.get("globalPool").get("id") - }) - result_global_pool.get("msg").update({ - name: "Global pool doesn't require an update" - }) - return - - self.log("Global pool requires update", "DEBUG") - # Pool Exists - pool_params = copy.deepcopy(self.want.get("wantGlobal")) - pool_params_ippool = pool_params.get("settings").get("ippool")[0] - pool_params_ippool.update({"id": self.have.get("globalPool").get("id")}) - self.log("Desired State for global pool (want): {0}".format(pool_params), "DEBUG") - keys_to_remove = ["IpAddressSpace", "ipPoolCidr", "type"] - for key in keys_to_remove: - del pool_params["settings"]["ippool"][0][key] - - have_ippool = self.have.get("globalPool").get("details").get("settings").get("ippool")[0] - keys_to_update = ["dhcpServerIps", "dnsServerIps", "gateway"] - for key in keys_to_update: - if pool_params_ippool.get(key) is None: - pool_params_ippool[key] = have_ippool.get(key) - - self.log("Desired global pool details (want): {0}".format(pool_params), "DEBUG") - response = self.dnac._exec( - family="network_settings", - function="update_global_pool", - op_modifies=True, - params=pool_params, - ) - - self.check_execution_response_status(response).check_return_status() - self.log("Global pool '{0}' updated successfully".format(name), "INFO") - result_global_pool.get("response").get(name) \ - .update({"Id": self.have.get("globalPool").get("details").get("id")}) - result_global_pool.get("msg").update({name: "Global Pool Updated Successfully"}) + self.log("Successfully created global pool successfully.", "INFO") + for item in pool_params.get("settings").get("ippool"): + name = item.get("ipPoolName") + self.log("Global pool '{0}' created successfully.".format(name), "INFO") + result_global_pool.get("response").update({"created": pool_params}) + result_global_pool.get("msg").update({name: "Global Pool Created Successfully"}) + + if update_global_pool: + final_update_global_pool = [] + # Pool exists, check update is required + for item in update_global_pool: + name = item.get("ipPoolName") + for pool_value in self.have.get("globalPool"): + if pool_value.get("exists") and pool_value.get("details").get("ipPoolName") == name: + if not self.requires_update(pool_value.get("details"), item, self.global_pool_obj_params): + self.log("Global pool '{0}' doesn't require an update".format(name), "INFO") + result_global_pool.get("msg").update({name: "Global pool doesn't require an update"}) + elif item not in final_update_global_pool: + final_update_global_pool.append(item) + + if final_update_global_pool: + self.log("Global pool requires update", "INFO") + + # Pool(s) needs update + pool_params = { + "settings": { + "ippool": copy.deepcopy(final_update_global_pool) + } + } + self.log("Desired State for global pool (want): {0}".format(pool_params), "DEBUG") + keys_to_remove = ["IpAddressSpace", "ipPoolCidr", "type"] + for item in pool_params["settings"]["ippool"]: + for key in keys_to_remove: + del item[key] + + self.log("Desired global pool details (want): {0}".format(pool_params), "DEBUG") + response = self.dnac._exec( + family="network_settings", + function="update_global_pool", + op_modifies=True, + params=pool_params, + ) + + self.check_execution_response_status(response).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") + result_global_pool.get("response").update({"globalPool Details": pool_params}) + result_global_pool.get("msg").update({name: "Global Pool Updated Successfully"}) + + self.log("Global pool configuration operations completed successfully.", "INFO") return - def update_reserve_pool(self, config): + def update_reserve_pool(self, reserve_pool): """ Update or Create a Reserve Pool in Cisco Catalyst Center based on the provided configuration. This method checks if a reserve pool with the specified name exists in Cisco Catalyst Center. If it exists and requires an update, it updates the pool. If not, it creates a new pool. Parameters: - config (list of dict) - Playbook details containing Reserve Pool information. + reserve_pool (list of dict) - Playbook details containing Reserve Pool information. Returns: None """ - name = config.get("reserve_pool_details").get("name") - result_reserve_pool = self.result.get("response")[1].get("reservePool") - result_reserve_pool.get("response").update({name: {}}) - self.log("Current reserved pool details in Catalyst Center: {0}" - .format(self.have.get("reservePool").get("details")), "DEBUG") - self.log("Desired reserved pool details in Catalyst Center: {0}" - .format(self.want.get("wantReserve")), "DEBUG") - - # Check pool exist, if not create and return - self.log("IPv4 global pool: {0}" - .format(self.want.get("wantReserve").get("ipv4GlobalPool")), "DEBUG") - site_name = config.get("reserve_pool_details").get("site_name") - reserve_params = self.want.get("wantReserve") - site_id = self.get_site_id(site_name) - reserve_params.update({"site_id": site_id}) - if not self.have.get("reservePool").get("exists"): - self.log("Desired reserved pool details (want): {0}".format(reserve_params), "DEBUG") + reserve_pool_index = -1 + for item in reserve_pool: + reserve_pool_index += 1 + name = item.get("name") + result_reserve_pool = self.result.get("response")[1].get("reservePool") + self.log("Current reserved pool '{0}' details in Catalyst Center: {1}" + .format(name, self.have.get("reservePool")[reserve_pool_index].get("details")), "DEBUG") + self.log("Desired reserved pool '{0}' details in Catalyst Center: {1}" + .format(name, self.want.get("wantReserve")[reserve_pool_index]), "DEBUG") + + # Check pool exist, if not create and return + self.log("IPv4 reserved pool '{0}': {1}" + .format(name, self.want.get("wantReserve")[reserve_pool_index].get("ipv4GlobalPool")), "DEBUG") + site_name = item.get("site_name") + reserve_params = self.want.get("wantReserve")[reserve_pool_index] + site_id = self.get_site_id(site_name) + reserve_params.update({"site_id": site_id}) + if not self.have.get("reservePool")[reserve_pool_index].get("exists"): + self.log("Desired reserved pool '{0}' details (want): {1}" + .format(name, reserve_params), "DEBUG") + response = self.dnac._exec( + family="network_settings", + function="reserve_ip_subpool", + op_modifies=True, + params=reserve_params, + ) + self.check_execution_response_status(response).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]}) + result_reserve_pool.get("msg") \ + .update({name: "Ip Subpool Reservation Created Successfully"}) + continue + + # Check update is required + if not self.requires_update(self.have.get("reservePool")[reserve_pool_index].get("details"), + self.want.get("wantReserve")[reserve_pool_index], + self.reserve_pool_obj_params): + self.log("Reserved ip subpool '{0}' doesn't require an update".format(name), "INFO") + result_reserve_pool.get("msg") \ + .update({name: "Reserved ip subpool doesn't require an update"}) + continue + + self.log("Reserved ip pool '{0}' requires an update".format(name), "DEBUG") + + # Pool Exists + self.log("Current reserved ip pool '{0}' details in Catalyst Center: {1}" + .format(name, self.have.get("reservePool")), "DEBUG") + self.log("Desired reserved ip pool '{0}' details: {1}" + .format(name, self.want.get("wantReserve")), "DEBUG") + reserve_params.update({"id": self.have.get("reservePool")[reserve_pool_index].get("id")}) response = self.dnac._exec( family="network_settings", - function="reserve_ip_subpool", + function="update_reserve_ip_subpool", op_modifies=True, params=reserve_params, ) self.check_execution_response_status(response).check_return_status() - self.log("Successfully created IP subpool reservation '{0}'.".format(name), "INFO") - result_reserve_pool.get("response").get(name) \ - .update({"reservePool Details": self.want.get("wantReserve")}) - result_reserve_pool.get("msg") \ - .update({name: "Ip Subpool Reservation Created Successfully"}) - return - - # Check update is required - if not self.requires_update(self.have.get("reservePool").get("details"), - self.want.get("wantReserve"), self.reserve_pool_obj_params): - self.log("Reserved ip subpool '{0}' doesn't require an update".format(name), "INFO") + self.log("Reserved ip subpool '{0}' updated successfully.".format(name), "INFO") + result_reserve_pool.get("response") \ + .update({name: self.have.get("reservePool")[reserve_pool_index].get("details")}) result_reserve_pool.get("response").get(name) \ - .update({"Cisco Catalyst Center params": self.have.get("reservePool").get("details")}) - result_reserve_pool.get("response").get(name) \ - .update({"Id": self.have.get("reservePool").get("id")}) + .update({"Id": self.have.get("reservePool")[reserve_pool_index].get("id")}) result_reserve_pool.get("msg") \ - .update({name: "Reserve ip subpool doesn't require an update"}) - return + .update({name: "Reserved Ip Subpool updated successfully."}) - self.log("Reserved ip pool '{0}' requires an update".format(name), "DEBUG") - # Pool Exists - self.log("Current reserved ip pool '{0}' details in Catalyst Center: {1}" - .format(name, self.have.get("reservePool")), "DEBUG") - self.log("Desired reserved ip pool '{0}' details: {1}" - .format(name, self.want.get("wantReserve")), "DEBUG") - reserve_params.update({"id": self.have.get("reservePool").get("id")}) - response = self.dnac._exec( - family="network_settings", - function="update_reserve_ip_subpool", - op_modifies=True, - params=reserve_params, - ) - self.check_execution_response_status(response).check_return_status() - self.log("Reserved ip subpool '{0}' updated successfully.".format(name), "INFO") - result_reserve_pool['msg'] = "Reserved Ip Subpool Updated Successfully" - result_reserve_pool.get("response").get(name) \ - .update({"Reservation details": self.have.get("reservePool").get("details")}) + self.log("Updated reserved IP subpool successfully", "INFO") return def update_network(self, config): @@ -1933,95 +2123,106 @@ def get_diff_merged(self, config): self """ - if config.get("global_pool_details") is not None: - self.update_global_pool(config) + global_pool = config.get("global_pool_details") + if global_pool is not None: + self.update_global_pool(global_pool) - if config.get("reserve_pool_details") is not None: - self.update_reserve_pool(config) + reserve_pool = config.get("reserve_pool_details") + if reserve_pool is not None: + self.update_reserve_pool(reserve_pool) if config.get("network_management_details") is not None: self.update_network(config) return self - def delete_reserve_pool(self, name): + def delete_reserve_pool(self, reserve_pool_details): """ Delete a Reserve Pool by name in Cisco Catalyst Center Parameters: - name (str) - The name of the Reserve Pool to be deleted. + reserve_pool_details (list of dict) - Reserverd pool playbook details. Returns: self """ - reserve_pool_exists = self.have.get("reservePool").get("exists") - result_reserve_pool = self.result.get("response")[1].get("reservePool") - - if not reserve_pool_exists: - result_reserve_pool.get("response").update({name: "Reserve Pool not found"}) - self.msg = "Reserved Ip Subpool Not Found" - self.status = "success" - return self + reserve_pool_index = -1 + for item in reserve_pool_details: + reserve_pool_index += 1 + name = item.get("name") + reserve_pool_exists = self.have.get("reservePool")[reserve_pool_index].get("exists") + result_reserve_pool = self.result.get("response")[1].get("reservePool") + + if not reserve_pool_exists: + result_reserve_pool.get("msg").update({name: "Reserve Pool not found"}) + self.log("Reserved Ip Subpool '{0}' not found".format(name), "INFO") + continue + + self.log("Reserved IP pool scheduled for deletion: {0}" + .format(self.have.get("reservePool")[reserve_pool_index].get("name")), "INFO") + _id = self.have.get("reservePool")[reserve_pool_index].get("id") + self.log("Reserved pool '{0}' id: {1}".format(name, _id), "DEBUG") + response = self.dnac._exec( + family="network_settings", + function="release_reserve_ip_subpool", + op_modifies=True, + params={"id": _id}, + ) + self.check_execution_response_status(response).check_return_status() + executionid = response.get("executionId") + result_reserve_pool = self.result.get("response")[1].get("reservePool") + result_reserve_pool.get("response").update({name: {}}) + result_reserve_pool.get("response").get(name) \ + .update({"Execution Id": executionid}) + result_reserve_pool.get("msg") \ + .update({name: "Ip subpool reservation released successfully"}) - self.log("Reserved IP pool scheduled for deletion: {0}" - .format(self.have.get("reservePool").get("name")), "INFO") - _id = self.have.get("reservePool").get("id") - self.log("Reserved pool {0} id: {1}".format(name, _id), "DEBUG") - response = self.dnac._exec( - family="network_settings", - function="release_reserve_ip_subpool", - op_modifies=True, - params={"id": _id}, - ) - self.check_execution_response_status(response).check_return_status() - executionid = response.get("executionId") - result_reserve_pool = self.result.get("response")[1].get("reservePool") - result_reserve_pool.get("response").update({name: {}}) - result_reserve_pool.get("response").get(name) \ - .update({"Execution Id": executionid}) - result_reserve_pool.get("msg") \ - .update({name: "Ip subpool reservation released successfully"}) - self.msg = "Reserved pool - {0} released successfully".format(name) + self.msg = "Reserved pool(s) released successfully" self.status = "success" return self - def delete_global_pool(self, name): + def delete_global_pool(self, global_pool_details): """ Delete a Global Pool by name in Cisco Catalyst Center Parameters: - name (str) - The name of the Global Pool to be deleted. + global_pool_details (dict) - Global pool details of the playbook Returns: self """ - global_pool_exists = self.have.get("globalPool").get("exists") result_global_pool = self.result.get("response")[0].get("globalPool") - if not global_pool_exists: - result_global_pool.get("response").update({name: "Global Pool not found"}) - self.msg = "Global pool Not Found" - self.status = "success" - return self + global_pool_index = 0 + for item in self.have.get("globalPool"): + global_pool_exists = item.get("exists") + name = global_pool_details.get("settings").get("ip_pool")[global_pool_index].get("name") + global_pool_index += 1 + if not global_pool_exists: + result_global_pool.get("msg").update({name: "Global Pool not found"}) + self.log("Global pool '{0}' not found".format(name), "INFO") + continue + + id = item.get("id") + response = self.dnac._exec( + family="network_settings", + function="delete_global_ip_pool", + op_modifies=True, + params={"id": id}, + ) - response = self.dnac._exec( - family="network_settings", - function="delete_global_ip_pool", - op_modifies=True, - params={"id": self.have.get("globalPool").get("id")}, - ) + # Check the execution status + self.check_execution_response_status(response).check_return_status() + executionid = response.get("executionId") - # Check the execution status - self.check_execution_response_status(response).check_return_status() - executionid = response.get("executionId") + # Update result information + result_global_pool = self.result.get("response")[0].get("globalPool") + result_global_pool.get("response").update({name: {}}) + result_global_pool.get("response").get(name).update({"Execution Id": executionid}) + result_global_pool.get("msg").update({name: "Global pool deleted successfully"}) - # Update result information - result_global_pool = self.result.get("response")[0].get("globalPool") - result_global_pool.get("response").update({name: {}}) - result_global_pool.get("response").get(name).update({"Execution Id": executionid}) - result_global_pool.get("msg").update({name: "Pool deleted successfully"}) - self.msg = "Global pool - {0} deleted successfully".format(name) + self.msg = "Global pools deleted successfully" self.status = "success" return self @@ -2036,14 +2237,13 @@ def get_diff_deleted(self, config): self """ - if config.get("reserve_pool_details") is not None: - name = config.get("reserve_pool_details").get("name") - self.delete_reserve_pool(name).check_return_status() + reserve_pool_details = config.get("reserve_pool_details") + if reserve_pool_details is not None: + self.delete_reserve_pool(reserve_pool_details).check_return_status() - if config.get("global_pool_details") is not None: - name = config.get("global_pool_details") \ - .get("settings").get("ip_pool")[0].get("name") - self.delete_global_pool(name).check_return_status() + global_pool_details = config.get("global_pool_details") + if global_pool_details is not None: + self.delete_global_pool(global_pool_details).check_return_status() return self @@ -2064,33 +2264,39 @@ def verify_diff_merged(self, config): self.log("Current State (have): {0}".format(self.have), "INFO") self.log("Requested State (want): {0}".format(self.want), "INFO") if config.get("global_pool_details") is not None: + global_pool_index = 0 self.log("Desired State of global pool (want): {0}" .format(self.want.get("wantGlobal")), "DEBUG") self.log("Current State of global pool (have): {0}" - .format(self.have.get("globalPool").get("details")), "DEBUG") - if self.requires_update(self.have.get("globalPool").get("details"), - self.want.get("wantGlobal"), self.global_pool_obj_params): - self.msg = "Global Pool Config is not applied to the Cisco Catalyst Center" - self.status = "failed" - return self + .format(self.have.get("globalPool")), "DEBUG") + for item in self.want.get("wantGlobal").get("settings").get("ippool"): + if self.requires_update(self.have.get("globalPool")[global_pool_index].get("details"), + item, self.global_pool_obj_params): + self.msg = "Global Pool Config is not applied to the Cisco Catalyst Center" + self.status = "failed" + return self - self.log("Successfully validated global pool '{0}'.".format(self.want - .get("wantGlobal").get("settings").get("ippool")[0].get("ipPoolName")), "INFO") + global_pool_index += 1 + + self.log("Successfully validated global pool(s).", "INFO") self.result.get("response")[0].get("globalPool").update({"Validation": "Success"}) if config.get("reserve_pool_details") is not None: - if self.requires_update(self.have.get("reservePool").get("details"), - self.want.get("wantReserve"), self.reserve_pool_obj_params): - self.log("Desired State for reserve pool (want): {0}" - .format(self.want.get("wantReserve")), "DEBUG") - self.log("Current State for reserve pool (have): {0}" - .format(self.have.get("reservePool").get("details")), "DEBUG") - self.msg = "Reserved Pool Config is not applied to the Cisco Catalyst Center" - self.status = "failed" - return self + reserve_pool_index = 0 + self.log("Desired State for reserve pool (want): {0}" + .format(self.want.get("wantReserve")), "DEBUG") + self.log("Current State for reserve pool (have): {0}" + .format(self.have.get("reservePool")), "DEBUG") + for item in self.want.get("wantReserve"): + if self.requires_update(self.have.get("reservePool")[reserve_pool_index].get("details"), + item, self.reserve_pool_obj_params): + self.msg = "Reserved Pool Config is not applied to the Cisco Catalyst Center" + self.status = "failed" + return self + + reserve_pool_index += 1 - self.log("Successfully validated the reserved pool '{0}'." - .format(self.want.get("wantReserve").get("name")), "INFO") + self.log("Successfully validated the reserved pool(s)", "INFO") self.result.get("response")[1].get("reservePool").update({"Validation": "Success"}) if config.get("network_management_details") is not None: @@ -2104,8 +2310,7 @@ def verify_diff_merged(self, config): .format(config.get("network_management_details").get("site_name")), "INFO") self.result.get("response")[2].get("network").update({"Validation": "Success"}) - self.msg = "Successfully validated the Global Pool, Reserve Pool \ - and the Network Functions." + self.msg = "Successfully validated the Global Pool, Reserve Pool and the Network Functions." self.status = "success" return self @@ -2126,27 +2331,36 @@ def verify_diff_deleted(self, config): self.log("Current State (have): {0}".format(self.have), "INFO") self.log("Desired State (want): {0}".format(self.want), "INFO") if config.get("global_pool_details") is not None: - global_pool_exists = self.have.get("globalPool").get("exists") - if global_pool_exists: - self.msg = "Global Pool Config is not applied to the Cisco Catalyst Center" - self.status = "failed" - return self + global_pool_index = 0 + global_pool_details = self.have.get("globalPool") + for item in global_pool_details: + global_pool_exists = item.get("exists") + name = config.get("global_pool_details").get("settings") \ + .get("ip_pool")[global_pool_index].get("name") + if global_pool_exists: + self.msg = "Global Pool Config '{0}' is not applied to the Cisco Catalyst Center" \ + .format(name) + self.status = "failed" + return self - self.log("Successfully validated absence of Global Pool '{0}'." - .format(config.get("global_pool_details") - .get("settings").get("ip_pool")[0].get("name")), "INFO") + self.log("Successfully validated absence of Global Pool '{0}'.".format(name), "INFO") + global_pool_index += 1 self.result.get("response")[0].get("globalPool").update({"Validation": "Success"}) if config.get("reserve_pool_details") is not None: - reserve_pool_exists = self.have.get("reservePool").get("exists") - if reserve_pool_exists: - self.msg = "Reserved Pool Config is not applied to the Catalyst Center" - self.status = "failed" - return self + reserve_pool_index = 0 + reserve_pool_details = self.have.get("reservePool") + for item in reserve_pool_details: + reserve_pool_exists = item.get("exists") + name = config.get("reserve_pool_details")[reserve_pool_index].get("name") + if reserve_pool_exists: + self.msg = "Reserved Pool Config '{0}' is not applied to the Catalyst Center" \ + .format(name) + self.status = "failed" + return self - self.log("Successfully validated the absence of Reserve Pool '{0}'." - .format(config.get("reserve_pool_details").get("name")), "INFO") - self.result.get("response")[1].get("reservePool").update({"Validation": "Success"}) + self.log("Successfully validated the absence of Reserve Pool '{0}'.".format(name), "INFO") + self.result.get("response")[1].get("reservePool").update({"Validation": "Success"}) self.msg = "Successfully validated the absence of Global Pool/Reserve Pool" self.status = "success" diff --git a/plugins/modules/network_update.py b/plugins/modules/network_update.py index 42b2eec0fd..65e6265006 100644 --- a/plugins/modules/network_update.py +++ b/plugins/modules/network_update.py @@ -131,7 +131,7 @@ is associated with the site. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateNetwork diff --git a/plugins/modules/network_v2.py b/plugins/modules/network_v2.py index faa1b85c9b..0bbe2869a1 100644 --- a/plugins/modules/network_v2.py +++ b/plugins/modules/network_v2.py @@ -134,7 +134,7 @@ the network settings. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings CreateNetworkV2 diff --git a/plugins/modules/network_v2_info.py b/plugins/modules/network_v2_info.py index 096b27bbda..715d1f6de1 100644 --- a/plugins/modules/network_v2_info.py +++ b/plugins/modules/network_v2_info.py @@ -24,7 +24,7 @@ - SiteId query parameter. Site Id to get the network settings associated with the site. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Network Settings GetNetworkV2 diff --git a/plugins/modules/nfv_profile.py b/plugins/modules/nfv_profile.py index 37ce591019..42809830ca 100644 --- a/plugins/modules/nfv_profile.py +++ b/plugins/modules/nfv_profile.py @@ -147,7 +147,7 @@ description: Name of the profile to create NFV profile. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design CreateNFVProfile diff --git a/plugins/modules/nfv_profile_info.py b/plugins/modules/nfv_profile_info.py index 7deb4f7bea..2a48807428 100644 --- a/plugins/modules/nfv_profile_info.py +++ b/plugins/modules/nfv_profile_info.py @@ -36,7 +36,7 @@ - Name query parameter. Name of network profile to be retrieved. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design GetNFVProfile diff --git a/plugins/modules/nfv_provision.py b/plugins/modules/nfv_provision.py index e242de7f57..7c913e63b0 100644 --- a/plugins/modules/nfv_provision.py +++ b/plugins/modules/nfv_provision.py @@ -375,7 +375,7 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design ProvisionNFV diff --git a/plugins/modules/nfv_provision_detail_info.py b/plugins/modules/nfv_provision_detail_info.py index 2a0f85a5a5..65b9281db4 100644 --- a/plugins/modules/nfv_provision_detail_info.py +++ b/plugins/modules/nfv_provision_detail_info.py @@ -24,7 +24,7 @@ - DeviceIp query parameter. Device to which the provisioning detail has to be retrieved. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design GetDeviceDetailsByIP diff --git a/plugins/modules/nfv_provision_details.py b/plugins/modules/nfv_provision_details.py index af9792e72d..552fa12b34 100644 --- a/plugins/modules/nfv_provision_details.py +++ b/plugins/modules/nfv_provision_details.py @@ -23,7 +23,7 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Site Design NFVProvisioningDetail diff --git a/plugins/modules/path_trace.py b/plugins/modules/path_trace.py index 055db2d564..34c0d135fb 100644 --- a/plugins/modules/path_trace.py +++ b/plugins/modules/path_trace.py @@ -26,7 +26,7 @@ description: Destination IP address. type: str destPort: - description: Destination Port. + description: Destination Port, range 1-65535. type: str flowAnalysisId: description: FlowAnalysisId path parameter. Flow analysis request id. @@ -40,17 +40,17 @@ description: Periodic refresh of path for every 30 sec. type: bool protocol: - description: Protocol. + description: Protocol - one of TCP, UDP - checks both when left blank. type: str sourceIP: description: Source IP address. type: str sourcePort: - description: Source Port. + description: Source Port, range 1-65535. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Path Trace InitiateANewPathtrace description: Complete reference of the InitiateANewPathtrace API. @@ -103,7 +103,6 @@ flowAnalysisId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/path_trace_info.py b/plugins/modules/path_trace_info.py index d305183c19..03c9e6a04a 100644 --- a/plugins/modules/path_trace_info.py +++ b/plugins/modules/path_trace_info.py @@ -31,24 +31,24 @@ type: str destIP: description: - - DestIP query parameter. Destination IP adress. + - DestIP query parameter. Destination IP address. type: str sourcePort: description: - SourcePort query parameter. Source port. - type: str + type: float destPort: description: - DestPort query parameter. Destination port. - type: str + type: float gtCreateTime: description: - GtCreateTime query parameter. Analyses requested after this time. - type: str + type: float ltCreateTime: description: - LtCreateTime query parameter. Analyses requested before this time. - type: str + type: float protocol: description: - Protocol query parameter. @@ -64,15 +64,15 @@ lastUpdateTime: description: - LastUpdateTime query parameter. Last update time. - type: str + type: float limit: description: - Limit query parameter. Number of resources returned. - type: int + type: float offset: description: - Offset query parameter. Start index of resources returned (1-based). - type: int + type: float order: description: - Order query parameter. Order by this field. @@ -86,19 +86,19 @@ - FlowAnalysisId path parameter. Flow analysis request id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: +- name: Cisco DNA Center documentation for Path Trace RetrievesAllPreviousPathtracesSummary + description: Complete reference of the RetrievesAllPreviousPathtracesSummary API. + link: https://developer.cisco.com/docs/dna-center/#!retrieves-all-previous-pathtraces-summary - name: Cisco DNA Center documentation for Path Trace RetrievesPreviousPathtrace description: Complete reference of the RetrievesPreviousPathtrace API. link: https://developer.cisco.com/docs/dna-center/#!retrieves-previous-pathtrace -- name: Cisco DNA Center documentation for Path Trace RetrivesAllPreviousPathtracesSummary - description: Complete reference of the RetrivesAllPreviousPathtracesSummary API. - link: https://developer.cisco.com/docs/dna-center/#!retrives-all-previous-pathtraces-summary notes: - SDK Method used are + path_trace.PathTrace.retrieves_all_previous_pathtraces_summary, path_trace.PathTrace.retrieves_previous_pathtrace, - path_trace.PathTrace.retrives_all_previous_pathtraces_summary, - Paths used are get /dna/intent/api/v1/flow-analysis, @@ -120,14 +120,14 @@ periodicRefresh: True sourceIP: string destIP: string - sourcePort: string - destPort: string - gtCreateTime: string - ltCreateTime: string + sourcePort: 0 + destPort: 0 + gtCreateTime: 0 + ltCreateTime: 0 protocol: string status: string taskId: string - lastUpdateTime: string + lastUpdateTime: 0 limit: 0 offset: 0 order: string @@ -148,7 +148,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -1068,7 +1067,8 @@ "protocol": "string", "sourceIP": "string", "sourcePort": "string", - "status": "string" + "status": "string", + "previousFlowAnalysisId": "string" } }, "version": "string" diff --git a/plugins/modules/planned_access_points.py b/plugins/modules/planned_access_points.py new file mode 100644 index 0000000000..b6c99f519f --- /dev/null +++ b/plugins/modules/planned_access_points.py @@ -0,0 +1,313 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: planned_access_points +short_description: Resource module for Planned Access Points +description: +- Manage operations create, update and delete of the resource Planned Access Points. +- > + Allows creation of a new planned access point on an existing floor map including its planned radio and antenna + details. Use the Get variant of this API to fetch any existing planned access points for the floor. The payload to + create a planned access point is in the same format, albeit a single object instead of a list, of that API. +- > + Allow to delete a planned access point from an existing floor map including its planned radio and antenna details. + Use the Get variant of this API to fetch the existing planned access points for the floor. The instanceUUID listed + in each of the planned access point attributes acts as the path param input to this API to delete that specific + instance. +- > + Allows updating a planned access point on an existing floor map including its planned radio and antenna details. + Use the Get variant of this API to fetch the existing planned access points for the floor. The payload to update a + planned access point is in the same format, albeit a single object instead of a list, of that API. +version_added: '6.0.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + attributes: + description: Planned Access Points's attributes. + suboptions: + createDate: + description: Planned Access Points's createDate. + type: int + domain: + description: Planned Access Points's domain. + type: str + heirarchyName: + description: Planned Access Points's heirarchyName. + type: str + id: + description: Planned Access Points's id. + type: float + instanceUuid: + description: Planned Access Points's instanceUuid. + type: str + macaddress: + description: Planned Access Points's macaddress. + type: str + name: + description: Planned Access Points's name. + type: str + source: + description: Planned Access Points's source. + type: str + typeString: + description: Planned Access Points's typeString. + type: str + type: dict + floorId: + description: FloorId path parameter. The instance UUID of the floor hierarchy element. + type: str + isSensor: + description: IsSensor flag. + type: bool + location: + description: Planned Access Points's location. + suboptions: + altitude: + description: Planned Access Points's altitude. + type: float + lattitude: + description: Planned Access Points's lattitude. + type: float + longtitude: + description: Planned Access Points's longtitude. + type: float + type: dict + plannedAccessPointUuid: + description: PlannedAccessPointUuid path parameter. The instance UUID of the planned + access point to delete. + type: str + position: + description: Planned Access Points's position. + suboptions: + x: + description: Planned Access Points's x. + type: float + y: + description: Planned Access Points's y. + type: float + z: + description: Planned Access Points's z. + type: float + type: dict + radioCount: + description: Planned Access Points's radioCount. + type: int + radios: + description: Planned Access Points's radios. + elements: dict + suboptions: + antenna: + description: Planned Access Points's antenna. + suboptions: + azimuthAngle: + description: Planned Access Points's azimuthAngle. + type: float + elevationAngle: + description: Planned Access Points's elevationAngle. + type: float + gain: + description: Planned Access Points's gain. + type: float + mode: + description: Planned Access Points's mode. + type: str + name: + description: Planned Access Points's name. + type: str + type: + description: Planned Access Points's type. + type: str + type: dict + attributes: + description: Planned Access Points's attributes. + suboptions: + channel: + description: Planned Access Points's channel. + type: float + channelString: + description: Planned Access Points's channelString. + type: str + id: + description: Planned Access Points's id. + type: float + ifMode: + description: Planned Access Points's ifMode. + type: str + ifTypeString: + description: Planned Access Points's ifTypeString. + type: str + ifTypeSubband: + description: Planned Access Points's ifTypeSubband. + type: str + instanceUuid: + description: Planned Access Points's instanceUuid. + type: str + slotId: + description: Planned Access Points's slotId. + type: float + type: dict + isSensor: + description: IsSensor flag. + type: bool + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Devices CreatePlannedAccessPointForFloor + description: Complete reference of the CreatePlannedAccessPointForFloor API. + link: https://developer.cisco.com/docs/dna-center/#!create-planned-access-point-for-floor +- name: Cisco DNA Center documentation for Devices DeletePlannedAccessPointForFloor + description: Complete reference of the DeletePlannedAccessPointForFloor API. + link: https://developer.cisco.com/docs/dna-center/#!delete-planned-access-point-for-floor +- name: Cisco DNA Center documentation for Devices UpdatePlannedAccessPointForFloor + description: Complete reference of the UpdatePlannedAccessPointForFloor API. + link: https://developer.cisco.com/docs/dna-center/#!update-planned-access-point-for-floor +notes: + - SDK Method used are + devices.Devices.create_planned_access_point_for_floor, + devices.Devices.delete_planned_access_point_for_floor, + devices.Devices.update_planned_access_point_for_floor, + + - Paths used are + post /dna/intent/api/v1/floors/{floorId}/planned-access-points, + delete /dna/intent/api/v1/floors/{floorId}/planned-access-points/{plannedAccessPointUuid}, + put /dna/intent/api/v1/floors/{floorId}/planned-access-points, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.planned_access_points: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + attributes: + createDate: 0 + domain: string + heirarchyName: string + id: 0 + instanceUuid: string + macaddress: string + name: string + source: string + typeString: string + floorId: string + isSensor: true + location: + altitude: 0 + lattitude: 0 + longtitude: 0 + position: + x: 0 + y: 0 + z: 0 + radioCount: 0 + radios: + - antenna: + azimuthAngle: 0 + elevationAngle: 0 + gain: 0 + mode: string + name: string + type: string + attributes: + channel: 0 + channelString: string + id: 0 + ifMode: string + ifTypeString: string + ifTypeSubband: string + instanceUuid: string + slotId: 0 + isSensor: true + +- name: Create + cisco.dnac.planned_access_points: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + attributes: + createDate: 0 + domain: string + heirarchyName: string + id: 0 + instanceUuid: string + macaddress: string + name: string + source: string + typeString: string + floorId: string + isSensor: true + location: + altitude: 0 + lattitude: 0 + longtitude: 0 + position: + x: 0 + y: 0 + z: 0 + radioCount: 0 + radios: + - antenna: + azimuthAngle: 0 + elevationAngle: 0 + gain: 0 + mode: string + name: string + type: string + attributes: + channel: 0 + channelString: string + id: 0 + ifMode: string + ifTypeString: string + ifTypeSubband: string + instanceUuid: string + slotId: 0 + isSensor: true + +- name: Delete by id + cisco.dnac.planned_access_points: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + floorId: string + plannedAccessPointUuid: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/planned_access_points_info.py b/plugins/modules/planned_access_points_info.py index bed5d8656f..24203b1a3e 100644 --- a/plugins/modules/planned_access_points_info.py +++ b/plugins/modules/planned_access_points_info.py @@ -26,18 +26,18 @@ limit: description: - Limit query parameter. - type: int + type: float offset: description: - Offset query parameter. - type: int + type: float radios: description: - Radios query parameter. Inlcude planned radio details. type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Devices GetPlannedAccessPointsForFloor description: Complete reference of the GetPlannedAccessPointsForFloor API. @@ -69,7 +69,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/platform_nodes_configuration_summary_info.py b/plugins/modules/platform_nodes_configuration_summary_info.py index d06ecb029a..88e1b57499 100644 --- a/plugins/modules/platform_nodes_configuration_summary_info.py +++ b/plugins/modules/platform_nodes_configuration_summary_info.py @@ -23,8 +23,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Platform Configuration CiscoDNACenterNodesConfigurationSummary description: Complete reference of the CiscoDNACenterNodesConfigurationSummary API. @@ -52,7 +52,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/platform_release_summary_info.py b/plugins/modules/platform_release_summary_info.py index b37caefc01..bf8a458503 100644 --- a/plugins/modules/platform_release_summary_info.py +++ b/plugins/modules/platform_release_summary_info.py @@ -22,8 +22,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Platform Configuration CiscoDNACenterReleaseSummary description: Complete reference of the CiscoDNACenterReleaseSummary API. @@ -51,7 +51,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device.py b/plugins/modules/pnp_device.py index a3451edeb4..60ab34e1f3 100644 --- a/plugins/modules/pnp_device.py +++ b/plugins/modules/pnp_device.py @@ -18,813 +18,119 @@ - cisco.dnac.module author: Rafael Campos (@racampos) options: - _id: - description: Pnp Device's _id. - type: str deviceInfo: description: Pnp Device's deviceInfo. suboptions: - aaaCredentials: - description: Pnp Device's aaaCredentials. - suboptions: - password: - description: Pnp Device's password. - type: str - username: - description: Pnp Device's username. - type: str - type: dict - addedOn: - description: Pnp Device's addedOn. - type: int - addnMacAddrs: - description: Pnp Device's addnMacAddrs. - elements: str - type: list - agentType: - description: Pnp Device's agentType. - type: str - authStatus: - description: Pnp Device's authStatus. - type: str - authenticatedSudiSerialNo: - description: Pnp Device's authenticatedSudiSerialNo. - type: str - capabilitiesSupported: - description: Pnp Device's capabilitiesSupported. - elements: str - type: list - cmState: - description: Pnp Device's cmState. - type: str description: - description: Pnp Device's description. + description: Description. type: str deviceSudiSerialNos: - description: Pnp Device's deviceSudiSerialNos. - elements: str - type: list - deviceType: - description: Pnp Device's deviceType. - type: str - featuresSupported: - description: Pnp Device's featuresSupported. + description: Device Sudi Serial Nos. elements: str type: list - fileSystemList: - description: Pnp Device's fileSystemList. - elements: dict - suboptions: - freespace: - description: Pnp Device's freespace. - type: int - name: - description: Pnp Device's name. - type: str - readable: - description: Readable flag. - type: bool - size: - description: Pnp Device's size. - type: int - type: - description: Pnp Device's type. - type: str - writeable: - description: Writeable flag. - type: bool - type: list - firstContact: - description: Pnp Device's firstContact. - type: int hostname: - description: Pnp Device's hostname. + description: Hostname. type: str - httpHeaders: - description: Pnp Device's httpHeaders. - elements: dict - suboptions: - key: - description: Pnp Device's key. - type: str - value: - description: Pnp Device's value. - type: str - type: list - imageFile: - description: Pnp Device's imageFile. - type: str - imageVersion: - description: Pnp Device's imageVersion. - type: str - ipInterfaces: - description: Pnp Device's ipInterfaces. - elements: dict - suboptions: - ipv4Address: - description: Pnp Device's ipv4Address. - type: dict - ipv6AddressList: - description: Pnp Device's ipv6AddressList. - elements: dict - type: list - macAddress: - description: Pnp Device's macAddress. - type: str - name: - description: Pnp Device's name. - type: str - status: - description: Pnp Device's status. - type: str - type: list - lastContact: - description: Pnp Device's lastContact. - type: int - lastSyncTime: - description: Pnp Device's lastSyncTime. - type: int - lastUpdateOn: - description: Pnp Device's lastUpdateOn. - type: int - location: - description: Pnp Device's location. - suboptions: - address: - description: Pnp Device's address. - type: str - altitude: - description: Pnp Device's altitude. - type: str - latitude: - description: Pnp Device's latitude. - type: str - longitude: - description: Pnp Device's longitude. - type: str - siteId: - description: Pnp Device's siteId. - type: str - type: dict + isSudiRequired: + description: Is Sudi Required. + type: bool macAddress: - description: Pnp Device's macAddress. - type: str - mode: - description: Pnp Device's mode. - type: str - name: - description: Pnp Device's name. - type: str - neighborLinks: - description: Pnp Device's neighborLinks. - elements: dict - suboptions: - localInterfaceName: - description: Pnp Device's localInterfaceName. - type: str - localMacAddress: - description: Pnp Device's localMacAddress. - type: str - localShortInterfaceName: - description: Pnp Device's localShortInterfaceName. - type: str - remoteDeviceName: - description: Pnp Device's remoteDeviceName. - type: str - remoteInterfaceName: - description: Pnp Device's remoteInterfaceName. - type: str - remoteMacAddress: - description: Pnp Device's remoteMacAddress. - type: str - remotePlatform: - description: Pnp Device's remotePlatform. - type: str - remoteShortInterfaceName: - description: Pnp Device's remoteShortInterfaceName. - type: str - remoteVersion: - description: Pnp Device's remoteVersion. - type: str - type: list - onbState: - description: Pnp Device's onbState. + description: Mac Address. type: str pid: - description: Pnp Device's pid. - type: str - pnpProfileList: - description: Pnp Device's pnpProfileList. - elements: dict - suboptions: - createdBy: - description: Pnp Device's createdBy. - type: str - discoveryCreated: - description: DiscoveryCreated flag. - type: bool - primaryEndpoint: - description: Pnp Device's primaryEndpoint. - suboptions: - certificate: - description: Pnp Device's certificate. - type: str - fqdn: - description: Pnp Device's fqdn. - type: str - ipv4Address: - description: Pnp Device's ipv4Address. - type: dict - ipv6Address: - description: Pnp Device's ipv6Address. - type: dict - port: - description: Pnp Device's port. - type: int - protocol: - description: Pnp Device's protocol. - type: str - type: dict - profileName: - description: Pnp Device's profileName. - type: str - secondaryEndpoint: - description: Pnp Device's secondaryEndpoint. - suboptions: - certificate: - description: Pnp Device's certificate. - type: str - fqdn: - description: Pnp Device's fqdn. - type: str - ipv4Address: - description: Pnp Device's ipv4Address. - type: dict - ipv6Address: - description: Pnp Device's ipv6Address. - type: dict - port: - description: Pnp Device's port. - type: int - protocol: - description: Pnp Device's protocol. - type: str - type: dict - type: list - populateInventory: - description: PopulateInventory flag. - type: bool - preWorkflowCliOuputs: - description: Pnp Device's preWorkflowCliOuputs. - elements: dict - suboptions: - cli: - description: Pnp Device's cli. - type: str - cliOutput: - description: Pnp Device's cliOutput. - type: str - type: list - projectId: - description: Pnp Device's projectId. + description: Pid. type: str - projectName: - description: Pnp Device's projectName. - type: str - reloadRequested: - description: ReloadRequested flag. - type: bool serialNumber: - description: Pnp Device's serialNumber. + description: Serial Number. type: str - smartAccountId: - description: Pnp Device's smartAccountId. - type: str - source: - description: Pnp Device's source. + siteId: + description: Site Id. type: str stack: - description: Stack flag. + description: Stack. type: bool stackInfo: description: Pnp Device's stackInfo. suboptions: isFullRing: - description: IsFullRing flag. + description: Is Full Ring. type: bool stackMemberList: description: Pnp Device's stackMemberList. elements: dict suboptions: hardwareVersion: - description: Pnp Device's hardwareVersion. + description: Hardware Version. type: str licenseLevel: - description: Pnp Device's licenseLevel. + description: License Level. type: str licenseType: - description: Pnp Device's licenseType. + description: License Type. type: str macAddress: - description: Pnp Device's macAddress. + description: Mac Address. type: str pid: - description: Pnp Device's pid. + description: Pid. type: str priority: - description: Pnp Device's priority. - type: int + description: Priority. + type: float role: - description: Pnp Device's role. + description: Role. type: str serialNumber: - description: Pnp Device's serialNumber. + description: Serial Number. type: str softwareVersion: - description: Pnp Device's softwareVersion. + description: Software Version. type: str stackNumber: - description: Pnp Device's stackNumber. - type: int + description: Stack Number. + type: float state: - description: Pnp Device's state. + description: State. type: str sudiSerialNumber: - description: Pnp Device's sudiSerialNumber. + description: Sudi Serial Number. type: str type: list stackRingProtocol: - description: Pnp Device's stackRingProtocol. + description: Stack Ring Protocol. type: str supportsStackWorkflows: - description: SupportsStackWorkflows flag. + description: Supports Stack Workflows. type: bool totalMemberCount: - description: Pnp Device's totalMemberCount. - type: int + description: Total Member Count. + type: float validLicenseLevels: - description: Pnp Device's validLicenseLevels. + description: Valid License Levels. elements: str type: list type: dict - state: - description: Pnp Device's state. - type: str - sudiRequired: - description: SudiRequired flag. - type: bool - tags: - description: Pnp Device's tags. - type: dict + userMicNumbers: + description: User Mic Numbers. + elements: str + type: list userSudiSerialNos: - description: Pnp Device's userSudiSerialNos. + description: User Sudi Serial Nos. elements: str type: list - virtualAccountId: - description: Pnp Device's virtualAccountId. - type: str workflowId: - description: Pnp Device's workflowId. + description: Workflow Id. type: str workflowName: - description: Pnp Device's workflowName. + description: Workflow Name. type: str type: dict id: - description: Id path parameter. + description: Id. type: str - runSummaryList: - description: Pnp Device's runSummaryList. - elements: dict - suboptions: - details: - description: Pnp Device's details. - type: str - errorFlag: - description: ErrorFlag flag. - type: bool - historyTaskInfo: - description: Pnp Device's historyTaskInfo. - suboptions: - addnDetails: - description: Pnp Device's addnDetails. - elements: dict - suboptions: - key: - description: Pnp Device's key. - type: str - value: - description: Pnp Device's value. - type: str - type: list - name: - description: Pnp Device's name. - type: str - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: - description: Pnp Device's type. - type: str - workItemList: - description: Pnp Device's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device's command. - type: str - endTime: - description: Pnp Device's endTime. - type: int - outputStr: - description: Pnp Device's outputStr. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: list - type: dict - timestamp: - description: Pnp Device's timestamp. - type: int - type: list - systemResetWorkflow: - description: Pnp Device's systemResetWorkflow. - suboptions: - _id: - description: Pnp Device's _id. - type: str - addToInventory: - description: AddToInventory flag. - type: bool - addedOn: - description: Pnp Device's addedOn. - type: int - configId: - description: Pnp Device's configId. - type: str - currTaskIdx: - description: Pnp Device's currTaskIdx. - type: int - description: - description: Pnp Device's description. - type: str - endTime: - description: Pnp Device's endTime. - type: int - execTime: - description: Pnp Device's execTime. - type: int - imageId: - description: Pnp Device's imageId. - type: str - instanceType: - description: Pnp Device's instanceType. - type: str - lastupdateOn: - description: Pnp Device's lastupdateOn. - type: int - name: - description: Pnp Device's name. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - tasks: - description: Pnp Device's tasks. - elements: dict - suboptions: - currWorkItemIdx: - description: Pnp Device's currWorkItemIdx. - type: int - endTime: - description: Pnp Device's endTime. - type: int - name: - description: Pnp Device's name. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - taskSeqNo: - description: Pnp Device's taskSeqNo. - type: int - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: - description: Pnp Device's type. - type: str - workItemList: - description: Pnp Device's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device's command. - type: str - endTime: - description: Pnp Device's endTime. - type: int - outputStr: - description: Pnp Device's outputStr. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: list - type: list - tenantId: - description: Pnp Device's tenantId. - type: str - type: - description: Pnp Device's type. - type: str - useState: - description: Pnp Device's useState. - type: str - version: - description: Pnp Device's version. - type: int - type: dict - systemWorkflow: - description: Pnp Device's systemWorkflow. - suboptions: - _id: - description: Pnp Device's _id. - type: str - addToInventory: - description: AddToInventory flag. - type: bool - addedOn: - description: Pnp Device's addedOn. - type: int - configId: - description: Pnp Device's configId. - type: str - currTaskIdx: - description: Pnp Device's currTaskIdx. - type: int - description: - description: Pnp Device's description. - type: str - endTime: - description: Pnp Device's endTime. - type: int - execTime: - description: Pnp Device's execTime. - type: int - imageId: - description: Pnp Device's imageId. - type: str - instanceType: - description: Pnp Device's instanceType. - type: str - lastupdateOn: - description: Pnp Device's lastupdateOn. - type: int - name: - description: Pnp Device's name. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - tasks: - description: Pnp Device's tasks. - elements: dict - suboptions: - currWorkItemIdx: - description: Pnp Device's currWorkItemIdx. - type: int - endTime: - description: Pnp Device's endTime. - type: int - name: - description: Pnp Device's name. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - taskSeqNo: - description: Pnp Device's taskSeqNo. - type: int - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: - description: Pnp Device's type. - type: str - workItemList: - description: Pnp Device's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device's command. - type: str - endTime: - description: Pnp Device's endTime. - type: int - outputStr: - description: Pnp Device's outputStr. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: list - type: list - tenantId: - description: Pnp Device's tenantId. - type: str - type: - description: Pnp Device's type. - type: str - useState: - description: Pnp Device's useState. - type: str - version: - description: Pnp Device's version. - type: int - type: dict - tenantId: - description: Pnp Device's tenantId. - type: str - version: - description: Pnp Device's version. - type: int - workflow: - description: Pnp Device's workflow. - suboptions: - _id: - description: Pnp Device's _id. - type: str - addToInventory: - description: AddToInventory flag. - type: bool - addedOn: - description: Pnp Device's addedOn. - type: int - configId: - description: Pnp Device's configId. - type: str - currTaskIdx: - description: Pnp Device's currTaskIdx. - type: int - description: - description: Pnp Device's description. - type: str - endTime: - description: Pnp Device's endTime. - type: int - execTime: - description: Pnp Device's execTime. - type: int - imageId: - description: Pnp Device's imageId. - type: str - instanceType: - description: Pnp Device's instanceType. - type: str - lastupdateOn: - description: Pnp Device's lastupdateOn. - type: int - name: - description: Pnp Device's name. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - tasks: - description: Pnp Device's tasks. - elements: dict - suboptions: - currWorkItemIdx: - description: Pnp Device's currWorkItemIdx. - type: int - endTime: - description: Pnp Device's endTime. - type: int - name: - description: Pnp Device's name. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - taskSeqNo: - description: Pnp Device's taskSeqNo. - type: int - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: - description: Pnp Device's type. - type: str - workItemList: - description: Pnp Device's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device's command. - type: str - endTime: - description: Pnp Device's endTime. - type: int - outputStr: - description: Pnp Device's outputStr. - type: str - startTime: - description: Pnp Device's startTime. - type: int - state: - description: Pnp Device's state. - type: str - timeTaken: - description: Pnp Device's timeTaken. - type: int - type: list - type: list - tenantId: - description: Pnp Device's tenantId. - type: str - type: - description: Pnp Device's type. - type: str - useState: - description: Pnp Device's useState. - type: str - version: - description: Pnp Device's version. - type: int - type: dict - workflowParameters: - description: Pnp Device's workflowParameters. - suboptions: - configList: - description: Pnp Device's configList. - elements: dict - suboptions: - configId: - description: Pnp Device's configId. - type: str - configParameters: - description: Pnp Device's configParameters. - elements: dict - suboptions: - key: - description: Pnp Device's key. - type: str - value: - description: Pnp Device's value. - type: str - type: list - type: list - licenseLevel: - description: Pnp Device's licenseLevel. - type: str - licenseType: - description: Pnp Device's licenseType. - type: str - topOfStackSerialNumber: - description: Pnp Device's topOfStackSerialNumber. - type: str - type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) AddDevice description: Complete reference of the AddDevice API. @@ -859,99 +165,16 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" state: present - _id: string deviceInfo: - aaaCredentials: - password: string - username: string - addedOn: 0 - addnMacAddrs: - - string - agentType: string - authStatus: string - authenticatedSudiSerialNo: string - capabilitiesSupported: - - string - cmState: string description: string deviceSudiSerialNos: - string - deviceType: string - featuresSupported: - - string - fileSystemList: - - freespace: 0 - name: string - readable: true - size: 0 - type: string - writeable: true - firstContact: 0 hostname: string - httpHeaders: - - key: string - value: string - imageFile: string - imageVersion: string - ipInterfaces: - - ipv4Address: {} - ipv6AddressList: - - {} - macAddress: string - name: string - status: string - lastContact: 0 - lastSyncTime: 0 - lastUpdateOn: 0 - location: - address: string - altitude: string - latitude: string - longitude: string - siteId: string + isSudiRequired: true macAddress: string - mode: string - name: string - neighborLinks: - - localInterfaceName: string - localMacAddress: string - localShortInterfaceName: string - remoteDeviceName: string - remoteInterfaceName: string - remoteMacAddress: string - remotePlatform: string - remoteShortInterfaceName: string - remoteVersion: string - onbState: string pid: string - pnpProfileList: - - createdBy: string - discoveryCreated: true - primaryEndpoint: - certificate: string - fqdn: string - ipv4Address: {} - ipv6Address: {} - port: 0 - protocol: string - profileName: string - secondaryEndpoint: - certificate: string - fqdn: string - ipv4Address: {} - ipv6Address: {} - port: 0 - protocol: string - populateInventory: true - preWorkflowCliOuputs: - - cli: string - cliOutput: string - projectId: string - projectName: string - reloadRequested: true serialNumber: string - smartAccountId: string - source: string + siteId: string stack: true stackInfo: isFullRing: true @@ -973,148 +196,12 @@ totalMemberCount: 0 validLicenseLevels: - string - state: string - sudiRequired: true - tags: {} + userMicNumbers: + - string userSudiSerialNos: - string - virtualAccountId: string workflowId: string workflowName: string - runSummaryList: - - details: string - errorFlag: true - historyTaskInfo: - addnDetails: - - key: string - value: string - name: string - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - timestamp: 0 - systemResetWorkflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - systemWorkflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - tenantId: string - version: 0 - workflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - workflowParameters: - configList: - - configId: string - configParameters: - - key: string - value: string - licenseLevel: string - licenseType: string - topOfStackSerialNumber: string - name: Update by id cisco.dnac.pnp_device: @@ -1126,263 +213,15 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" state: present - _id: string deviceInfo: - aaaCredentials: - password: string - username: string - addedOn: 0 - addnMacAddrs: - - string - agentType: string - authStatus: string - authenticatedSudiSerialNo: string - capabilitiesSupported: - - string - cmState: string - description: string - deviceSudiSerialNos: - - string - deviceType: string - featuresSupported: - - string - fileSystemList: - - freespace: 0 - name: string - readable: true - size: 0 - type: string - writeable: true - firstContact: 0 hostname: string - httpHeaders: - - key: string - value: string - imageFile: string - imageVersion: string - ipInterfaces: - - ipv4Address: {} - ipv6AddressList: - - {} - macAddress: string - name: string - status: string - lastContact: 0 - lastSyncTime: 0 - lastUpdateOn: 0 - location: - address: string - altitude: string - latitude: string - longitude: string - siteId: string - macAddress: string - mode: string - name: string - neighborLinks: - - localInterfaceName: string - localMacAddress: string - localShortInterfaceName: string - remoteDeviceName: string - remoteInterfaceName: string - remoteMacAddress: string - remotePlatform: string - remoteShortInterfaceName: string - remoteVersion: string - onbState: string pid: string - pnpProfileList: - - createdBy: string - discoveryCreated: true - primaryEndpoint: - certificate: string - fqdn: string - ipv4Address: {} - ipv6Address: {} - port: 0 - protocol: string - profileName: string - secondaryEndpoint: - certificate: string - fqdn: string - ipv4Address: {} - ipv6Address: {} - port: 0 - protocol: string - populateInventory: true - preWorkflowCliOuputs: - - cli: string - cliOutput: string - projectId: string - projectName: string - reloadRequested: true serialNumber: string - smartAccountId: string - source: string stack: true - stackInfo: - isFullRing: true - stackMemberList: - - hardwareVersion: string - licenseLevel: string - licenseType: string - macAddress: string - pid: string - priority: 0 - role: string - serialNumber: string - softwareVersion: string - stackNumber: 0 - state: string - sudiSerialNumber: string - stackRingProtocol: string - supportsStackWorkflows: true - totalMemberCount: 0 - validLicenseLevels: - - string - state: string sudiRequired: true - tags: {} - userSudiSerialNos: - - string - virtualAccountId: string - workflowId: string - workflowName: string + sudiSerialNos: + - {} id: string - runSummaryList: - - details: string - errorFlag: true - historyTaskInfo: - addnDetails: - - key: string - value: string - name: string - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - timestamp: 0 - systemResetWorkflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - systemWorkflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - tenantId: string - version: 0 - workflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - workflowParameters: - configList: - - configId: string - configParameters: - - key: string - value: string - licenseLevel: string - licenseType: string - topOfStackSerialNumber: string - name: Delete by id cisco.dnac.pnp_device: @@ -1397,7 +236,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_authorize.py b/plugins/modules/pnp_device_authorize.py index 2a033f504b..da2ad652b4 100644 --- a/plugins/modules/pnp_device_authorize.py +++ b/plugins/modules/pnp_device_authorize.py @@ -11,7 +11,7 @@ description: - Manage operation create of the resource Pnp Device Authorize. - Authorizes one of more devices. A device can only be authorized if Authorization is set in Device Settings. -version_added: '6.5.0' +version_added: '6.0.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -21,15 +21,15 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for AuthorizeDevice +- name: Cisco DNA Center documentation for Device Onboarding (PnP) AuthorizeDevice description: Complete reference of the AuthorizeDevice API. link: https://developer.cisco.com/docs/dna-center/#!authorize-device notes: - SDK Method used are - ..authorize_device, + device_onboarding_pnp.DeviceOnboardingPnp.authorize_device, - Paths used are post /api/v1/onboarding/pnp-device/authorize, @@ -50,7 +50,6 @@ - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_claim.py b/plugins/modules/pnp_device_claim.py index 4ce1b33892..81a7f42c85 100644 --- a/plugins/modules/pnp_device_claim.py +++ b/plugins/modules/pnp_device_claim.py @@ -77,8 +77,8 @@ description: Pnp Device Claim's workflowId. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ClaimDevice description: Complete reference of the ClaimDevice API. @@ -122,7 +122,6 @@ workflowId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_claim_to_site.py b/plugins/modules/pnp_device_claim_to_site.py index 2e3bdd0a5b..1baeaa2f75 100644 --- a/plugins/modules/pnp_device_claim_to_site.py +++ b/plugins/modules/pnp_device_claim_to_site.py @@ -10,7 +10,9 @@ short_description: Resource module for Pnp Device Claim To Site description: - Manage operation create of the resource Pnp Device Claim To Site. -- Claim a device based on DNA-C Site-based design process. Some required parameters differ based on device platform. +- > + Claim a device based on Catalyst Center Site-based design process. Some required parameters differ based on device + platform. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -18,13 +20,13 @@ options: configInfo: description: Pnp Device Claim To Site's configInfo. - elements: dict suboptions: configId: description: Config Id. type: str configParameters: description: Pnp Device Claim To Site's configParameters. + elements: dict suboptions: key: description: Key. @@ -32,8 +34,8 @@ value: description: Value. type: str - type: dict - type: list + type: list + type: dict version_added: 4.2.0 deviceId: description: Device Id. @@ -53,9 +55,10 @@ type: bool type: dict version_added: 4.2.0 - interfaceName: + ipInterfaceName: description: For Catalyst 9800 WLC. type: str + version_added: 6.4.0 rfProfile: description: For Access Points. type: str @@ -76,12 +79,13 @@ type: description: Type. type: str - vlanID: + vlanId: description: For Catalyst 9800 WLC. type: str + version_added: 6.4.0 requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ClaimADeviceToASite description: Complete reference of the ClaimADeviceToASite API. @@ -106,26 +110,25 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" configInfo: - - configId: string + configId: string configParameters: - key: string + - key: string value: string deviceId: string gateway: string imageInfo: imageId: string skip: true - interfaceName: string + ipInterfaceName: string rfProfile: string sensorProfile: string siteId: string staticIP: string subnetMask: string type: string - vlanID: string + vlanId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_config_preview.py b/plugins/modules/pnp_device_config_preview.py index 24d1ae219c..35cce9d30e 100644 --- a/plugins/modules/pnp_device_config_preview.py +++ b/plugins/modules/pnp_device_config_preview.py @@ -26,8 +26,8 @@ description: Pnp Device Config Preview's type. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) PreviewConfig description: Complete reference of the PreviewConfig API. @@ -56,7 +56,6 @@ type: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_count_info.py b/plugins/modules/pnp_device_count_info.py index 94dc35fa23..b670f9e439 100644 --- a/plugins/modules/pnp_device_count_info.py +++ b/plugins/modules/pnp_device_count_info.py @@ -34,11 +34,6 @@ - OnbState query parameter. Device Onboarding State. elements: str type: list - cmState: - description: - - CmState query parameter. Device Connection Manager State. - elements: str - type: list name: description: - Name query parameter. Device Name. @@ -54,21 +49,11 @@ - Source query parameter. Device Source. elements: str type: list - projectId: - description: - - ProjectId query parameter. Device Project Id. - elements: str - type: list workflowId: description: - WorkflowId query parameter. Device Workflow Id. elements: str type: list - projectName: - description: - - ProjectName query parameter. Device Project Name. - elements: str - type: list workflowName: description: - WorkflowName query parameter. Device Workflow Name. @@ -89,8 +74,8 @@ - LastContact query parameter. Device Has Contacted lastContact > 0. type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetDeviceCount description: Complete reference of the GetDeviceCount API. @@ -118,13 +103,10 @@ serialNumber: [] state_: [] onbState: [] - cmState: [] name: [] pid: [] source: [] - projectId: [] workflowId: [] - projectName: [] workflowName: [] smartAccountId: [] virtualAccountId: [] @@ -132,7 +114,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_history_info.py b/plugins/modules/pnp_device_history_info.py index 781a2f035c..0b7c697d10 100644 --- a/plugins/modules/pnp_device_history_info.py +++ b/plugins/modules/pnp_device_history_info.py @@ -33,8 +33,8 @@ - SortOrder query parameter. Sort Order Ascending (asc) or Descending (des). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetDeviceHistory description: Complete reference of the GetDeviceHistory API. @@ -65,7 +65,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_import.py b/plugins/modules/pnp_device_import.py index ed0802a80b..a99660f570 100644 --- a/plugins/modules/pnp_device_import.py +++ b/plugins/modules/pnp_device_import.py @@ -21,810 +21,119 @@ elements: dict suboptions: _id: - description: Pnp Device Import's _id. + description: Id. type: str deviceInfo: description: Pnp Device Import's deviceInfo. suboptions: - aaaCredentials: - description: Pnp Device Import's aaaCredentials. - suboptions: - password: - description: Pnp Device Import's password. - type: str - username: - description: Pnp Device Import's username. - type: str - type: dict - addedOn: - description: Pnp Device Import's addedOn. - type: int - addnMacAddrs: - description: Pnp Device Import's addnMacAddrs. - elements: str - type: list - agentType: - description: Pnp Device Import's agentType. - type: str - authStatus: - description: Pnp Device Import's authStatus. - type: str - authenticatedSudiSerialNo: - description: Pnp Device Import's authenticatedSudiSerialNo. - type: str - capabilitiesSupported: - description: Pnp Device Import's capabilitiesSupported. - elements: str - type: list - cmState: - description: Pnp Device Import's cmState. - type: str description: - description: Pnp Device Import's description. + description: Description. type: str deviceSudiSerialNos: - description: Pnp Device Import's deviceSudiSerialNos. - elements: str - type: list - deviceType: - description: Pnp Device Import's deviceType. - type: str - featuresSupported: - description: Pnp Device Import's featuresSupported. + description: Device Sudi Serial Nos. elements: str type: list - fileSystemList: - description: Pnp Device Import's fileSystemList. - elements: dict - suboptions: - freespace: - description: Pnp Device Import's freespace. - type: int - name: - description: Pnp Device Import's name. - type: str - readable: - description: Readable flag. - type: bool - size: - description: Pnp Device Import's size. - type: int - type: - description: Pnp Device Import's type. - type: str - writeable: - description: Writeable flag. - type: bool - type: list - firstContact: - description: Pnp Device Import's firstContact. - type: int hostname: - description: Pnp Device Import's hostname. - type: str - httpHeaders: - description: Pnp Device Import's httpHeaders. - elements: dict - suboptions: - key: - description: Pnp Device Import's key. - type: str - value: - description: Pnp Device Import's value. - type: str - type: list - imageFile: - description: Pnp Device Import's imageFile. + description: Hostname. type: str - imageVersion: - description: Pnp Device Import's imageVersion. - type: str - ipInterfaces: - description: Pnp Device Import's ipInterfaces. - elements: dict - suboptions: - ipv4Address: - description: Pnp Device Import's ipv4Address. - type: dict - ipv6AddressList: - description: Pnp Device Import's ipv6AddressList. - elements: dict - type: list - macAddress: - description: Pnp Device Import's macAddress. - type: str - name: - description: Pnp Device Import's name. - type: str - status: - description: Pnp Device Import's status. - type: str - type: list - lastContact: - description: Pnp Device Import's lastContact. - type: int - lastSyncTime: - description: Pnp Device Import's lastSyncTime. - type: int - lastUpdateOn: - description: Pnp Device Import's lastUpdateOn. - type: int - location: - description: Pnp Device Import's location. - suboptions: - address: - description: Pnp Device Import's address. - type: str - altitude: - description: Pnp Device Import's altitude. - type: str - latitude: - description: Pnp Device Import's latitude. - type: str - longitude: - description: Pnp Device Import's longitude. - type: str - siteId: - description: Pnp Device Import's siteId. - type: str - type: dict + isSudiRequired: + description: Is Sudi Required. + type: bool macAddress: - description: Pnp Device Import's macAddress. - type: str - mode: - description: Pnp Device Import's mode. - type: str - name: - description: Pnp Device Import's name. - type: str - neighborLinks: - description: Pnp Device Import's neighborLinks. - elements: dict - suboptions: - localInterfaceName: - description: Pnp Device Import's localInterfaceName. - type: str - localMacAddress: - description: Pnp Device Import's localMacAddress. - type: str - localShortInterfaceName: - description: Pnp Device Import's localShortInterfaceName. - type: str - remoteDeviceName: - description: Pnp Device Import's remoteDeviceName. - type: str - remoteInterfaceName: - description: Pnp Device Import's remoteInterfaceName. - type: str - remoteMacAddress: - description: Pnp Device Import's remoteMacAddress. - type: str - remotePlatform: - description: Pnp Device Import's remotePlatform. - type: str - remoteShortInterfaceName: - description: Pnp Device Import's remoteShortInterfaceName. - type: str - remoteVersion: - description: Pnp Device Import's remoteVersion. - type: str - type: list - onbState: - description: Pnp Device Import's onbState. + description: Mac Address. type: str pid: - description: Pnp Device Import's pid. - type: str - pnpProfileList: - description: Pnp Device Import's pnpProfileList. - elements: dict - suboptions: - createdBy: - description: Pnp Device Import's createdBy. - type: str - discoveryCreated: - description: DiscoveryCreated flag. - type: bool - primaryEndpoint: - description: Pnp Device Import's primaryEndpoint. - suboptions: - certificate: - description: Pnp Device Import's certificate. - type: str - fqdn: - description: Pnp Device Import's fqdn. - type: str - ipv4Address: - description: Pnp Device Import's ipv4Address. - type: dict - ipv6Address: - description: Pnp Device Import's ipv6Address. - type: dict - port: - description: Pnp Device Import's port. - type: int - protocol: - description: Pnp Device Import's protocol. - type: str - type: dict - profileName: - description: Pnp Device Import's profileName. - type: str - secondaryEndpoint: - description: Pnp Device Import's secondaryEndpoint. - suboptions: - certificate: - description: Pnp Device Import's certificate. - type: str - fqdn: - description: Pnp Device Import's fqdn. - type: str - ipv4Address: - description: Pnp Device Import's ipv4Address. - type: dict - ipv6Address: - description: Pnp Device Import's ipv6Address. - type: dict - port: - description: Pnp Device Import's port. - type: int - protocol: - description: Pnp Device Import's protocol. - type: str - type: dict - type: list - populateInventory: - description: PopulateInventory flag. - type: bool - preWorkflowCliOuputs: - description: Pnp Device Import's preWorkflowCliOuputs. - elements: dict - suboptions: - cli: - description: Pnp Device Import's cli. - type: str - cliOutput: - description: Pnp Device Import's cliOutput. - type: str - type: list - projectId: - description: Pnp Device Import's projectId. + description: Pid. type: str - projectName: - description: Pnp Device Import's projectName. - type: str - reloadRequested: - description: ReloadRequested flag. - type: bool serialNumber: - description: Pnp Device Import's serialNumber. - type: str - smartAccountId: - description: Pnp Device Import's smartAccountId. + description: Serial Number. type: str - source: - description: Pnp Device Import's source. + siteId: + description: Site Id. type: str stack: - description: Stack flag. + description: Stack. type: bool stackInfo: description: Pnp Device Import's stackInfo. suboptions: isFullRing: - description: IsFullRing flag. + description: Is Full Ring. type: bool stackMemberList: description: Pnp Device Import's stackMemberList. elements: dict suboptions: hardwareVersion: - description: Pnp Device Import's hardwareVersion. + description: Hardware Version. type: str licenseLevel: - description: Pnp Device Import's licenseLevel. + description: License Level. type: str licenseType: - description: Pnp Device Import's licenseType. + description: License Type. type: str macAddress: - description: Pnp Device Import's macAddress. + description: Mac Address. type: str pid: - description: Pnp Device Import's pid. + description: Pid. type: str priority: - description: Pnp Device Import's priority. - type: int + description: Priority. + type: float role: - description: Pnp Device Import's role. + description: Role. type: str serialNumber: - description: Pnp Device Import's serialNumber. + description: Serial Number. type: str softwareVersion: - description: Pnp Device Import's softwareVersion. + description: Software Version. type: str stackNumber: - description: Pnp Device Import's stackNumber. - type: int + description: Stack Number. + type: float state: - description: Pnp Device Import's state. + description: State. type: str sudiSerialNumber: - description: Pnp Device Import's sudiSerialNumber. + description: Sudi Serial Number. type: str type: list stackRingProtocol: - description: Pnp Device Import's stackRingProtocol. + description: Stack Ring Protocol. type: str supportsStackWorkflows: - description: SupportsStackWorkflows flag. + description: Supports Stack Workflows. type: bool totalMemberCount: - description: Pnp Device Import's totalMemberCount. - type: int + description: Total Member Count. + type: float validLicenseLevels: - description: Pnp Device Import's validLicenseLevels. + description: Valid License Levels. elements: str type: list type: dict - state: - description: Pnp Device Import's state. - type: str - sudiRequired: - description: SudiRequired flag. - type: bool - tags: - description: Pnp Device Import's tags. - type: dict + userMicNumbers: + description: User Mic Numbers. + elements: str + type: list userSudiSerialNos: - description: Pnp Device Import's userSudiSerialNos. + description: User Sudi Serial Nos. elements: str type: list - virtualAccountId: - description: Pnp Device Import's virtualAccountId. - type: str workflowId: - description: Pnp Device Import's workflowId. + description: Workflow Id. type: str workflowName: - description: Pnp Device Import's workflowName. - type: str - type: dict - runSummaryList: - description: Pnp Device Import's runSummaryList. - elements: dict - suboptions: - details: - description: Pnp Device Import's details. - type: str - errorFlag: - description: ErrorFlag flag. - type: bool - historyTaskInfo: - description: Pnp Device Import's historyTaskInfo. - suboptions: - addnDetails: - description: Pnp Device Import's addnDetails. - elements: dict - suboptions: - key: - description: Pnp Device Import's key. - type: str - value: - description: Pnp Device Import's value. - type: str - type: list - name: - description: Pnp Device Import's name. - type: str - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: - description: Pnp Device Import's type. - type: str - workItemList: - description: Pnp Device Import's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device Import's command. - type: str - endTime: - description: Pnp Device Import's endTime. - type: int - outputStr: - description: Pnp Device Import's outputStr. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: list - type: dict - timestamp: - description: Pnp Device Import's timestamp. - type: int - type: list - systemResetWorkflow: - description: Pnp Device Import's systemResetWorkflow. - suboptions: - _id: - description: Pnp Device Import's _id. - type: str - addToInventory: - description: AddToInventory flag. - type: bool - addedOn: - description: Pnp Device Import's addedOn. - type: int - configId: - description: Pnp Device Import's configId. - type: str - currTaskIdx: - description: Pnp Device Import's currTaskIdx. - type: int - description: - description: Pnp Device Import's description. - type: str - endTime: - description: Pnp Device Import's endTime. - type: int - execTime: - description: Pnp Device Import's execTime. - type: int - imageId: - description: Pnp Device Import's imageId. - type: str - instanceType: - description: Pnp Device Import's instanceType. - type: str - lastupdateOn: - description: Pnp Device Import's lastupdateOn. - type: int - name: - description: Pnp Device Import's name. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - tasks: - description: Pnp Device Import's tasks. - elements: dict - suboptions: - currWorkItemIdx: - description: Pnp Device Import's currWorkItemIdx. - type: int - endTime: - description: Pnp Device Import's endTime. - type: int - name: - description: Pnp Device Import's name. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - taskSeqNo: - description: Pnp Device Import's taskSeqNo. - type: int - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: - description: Pnp Device Import's type. - type: str - workItemList: - description: Pnp Device Import's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device Import's command. - type: str - endTime: - description: Pnp Device Import's endTime. - type: int - outputStr: - description: Pnp Device Import's outputStr. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: list - type: list - tenantId: - description: Pnp Device Import's tenantId. - type: str - type: - description: Pnp Device Import's type. - type: str - useState: - description: Pnp Device Import's useState. - type: str - version: - description: Pnp Device Import's version. - type: int - type: dict - systemWorkflow: - description: Pnp Device Import's systemWorkflow. - suboptions: - _id: - description: Pnp Device Import's _id. - type: str - addToInventory: - description: AddToInventory flag. - type: bool - addedOn: - description: Pnp Device Import's addedOn. - type: int - configId: - description: Pnp Device Import's configId. - type: str - currTaskIdx: - description: Pnp Device Import's currTaskIdx. - type: int - description: - description: Pnp Device Import's description. - type: str - endTime: - description: Pnp Device Import's endTime. - type: int - execTime: - description: Pnp Device Import's execTime. - type: int - imageId: - description: Pnp Device Import's imageId. - type: str - instanceType: - description: Pnp Device Import's instanceType. - type: str - lastupdateOn: - description: Pnp Device Import's lastupdateOn. - type: int - name: - description: Pnp Device Import's name. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - tasks: - description: Pnp Device Import's tasks. - elements: dict - suboptions: - currWorkItemIdx: - description: Pnp Device Import's currWorkItemIdx. - type: int - endTime: - description: Pnp Device Import's endTime. - type: int - name: - description: Pnp Device Import's name. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - taskSeqNo: - description: Pnp Device Import's taskSeqNo. - type: int - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: - description: Pnp Device Import's type. - type: str - workItemList: - description: Pnp Device Import's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device Import's command. - type: str - endTime: - description: Pnp Device Import's endTime. - type: int - outputStr: - description: Pnp Device Import's outputStr. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: list - type: list - tenantId: - description: Pnp Device Import's tenantId. - type: str - type: - description: Pnp Device Import's type. - type: str - useState: - description: Pnp Device Import's useState. - type: str - version: - description: Pnp Device Import's version. - type: int - type: dict - tenantId: - description: Pnp Device Import's tenantId. - type: str - version: - description: Pnp Device Import's version. - type: int - workflow: - description: Pnp Device Import's workflow. - suboptions: - _id: - description: Pnp Device Import's _id. - type: str - addToInventory: - description: AddToInventory flag. - type: bool - addedOn: - description: Pnp Device Import's addedOn. - type: int - configId: - description: Pnp Device Import's configId. - type: str - currTaskIdx: - description: Pnp Device Import's currTaskIdx. - type: int - description: - description: Pnp Device Import's description. - type: str - endTime: - description: Pnp Device Import's endTime. - type: int - execTime: - description: Pnp Device Import's execTime. - type: int - imageId: - description: Pnp Device Import's imageId. - type: str - instanceType: - description: Pnp Device Import's instanceType. - type: str - lastupdateOn: - description: Pnp Device Import's lastupdateOn. - type: int - name: - description: Pnp Device Import's name. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - tasks: - description: Pnp Device Import's tasks. - elements: dict - suboptions: - currWorkItemIdx: - description: Pnp Device Import's currWorkItemIdx. - type: int - endTime: - description: Pnp Device Import's endTime. - type: int - name: - description: Pnp Device Import's name. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - taskSeqNo: - description: Pnp Device Import's taskSeqNo. - type: int - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: - description: Pnp Device Import's type. - type: str - workItemList: - description: Pnp Device Import's workItemList. - elements: dict - suboptions: - command: - description: Pnp Device Import's command. - type: str - endTime: - description: Pnp Device Import's endTime. - type: int - outputStr: - description: Pnp Device Import's outputStr. - type: str - startTime: - description: Pnp Device Import's startTime. - type: int - state: - description: Pnp Device Import's state. - type: str - timeTaken: - description: Pnp Device Import's timeTaken. - type: int - type: list - type: list - tenantId: - description: Pnp Device Import's tenantId. - type: str - type: - description: Pnp Device Import's type. - type: str - useState: - description: Pnp Device Import's useState. - type: str - version: - description: Pnp Device Import's version. - type: int - type: dict - workflowParameters: - description: Pnp Device Import's workflowParameters. - suboptions: - configList: - description: Pnp Device Import's configList. - elements: dict - suboptions: - configId: - description: Pnp Device Import's configId. - type: str - configParameters: - description: Pnp Device Import's configParameters. - elements: dict - suboptions: - key: - description: Pnp Device Import's key. - type: str - value: - description: Pnp Device Import's value. - type: str - type: list - type: list - licenseLevel: - description: Pnp Device Import's licenseLevel. - type: str - licenseType: - description: Pnp Device Import's licenseType. - type: str - topOfStackSerialNumber: - description: Pnp Device Import's topOfStackSerialNumber. + description: Workflow Name. type: str type: dict type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ImportDevicesInBulk description: Complete reference of the ImportDevicesInBulk API. @@ -851,97 +160,15 @@ payload: - _id: string deviceInfo: - aaaCredentials: - password: string - username: string - addedOn: 0 - addnMacAddrs: - - string - agentType: string - authStatus: string - authenticatedSudiSerialNo: string - capabilitiesSupported: - - string - cmState: string description: string deviceSudiSerialNos: - string - deviceType: string - featuresSupported: - - string - fileSystemList: - - freespace: 0 - name: string - readable: true - size: 0 - type: string - writeable: true - firstContact: 0 hostname: string - httpHeaders: - - key: string - value: string - imageFile: string - imageVersion: string - ipInterfaces: - - ipv4Address: {} - ipv6AddressList: - - {} - macAddress: string - name: string - status: string - lastContact: 0 - lastSyncTime: 0 - lastUpdateOn: 0 - location: - address: string - altitude: string - latitude: string - longitude: string - siteId: string + isSudiRequired: true macAddress: string - mode: string - name: string - neighborLinks: - - localInterfaceName: string - localMacAddress: string - localShortInterfaceName: string - remoteDeviceName: string - remoteInterfaceName: string - remoteMacAddress: string - remotePlatform: string - remoteShortInterfaceName: string - remoteVersion: string - onbState: string pid: string - pnpProfileList: - - createdBy: string - discoveryCreated: true - primaryEndpoint: - certificate: string - fqdn: string - ipv4Address: {} - ipv6Address: {} - port: 0 - protocol: string - profileName: string - secondaryEndpoint: - certificate: string - fqdn: string - ipv4Address: {} - ipv6Address: {} - port: 0 - protocol: string - populateInventory: true - preWorkflowCliOuputs: - - cli: string - cliOutput: string - projectId: string - projectName: string - reloadRequested: true serialNumber: string - smartAccountId: string - source: string + siteId: string stack: true stackInfo: isFullRing: true @@ -963,151 +190,14 @@ totalMemberCount: 0 validLicenseLevels: - string - state: string - sudiRequired: true - tags: {} + userMicNumbers: + - string userSudiSerialNos: - string - virtualAccountId: string workflowId: string workflowName: string - runSummaryList: - - details: string - errorFlag: true - historyTaskInfo: - addnDetails: - - key: string - value: string - name: string - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - timestamp: 0 - systemResetWorkflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - systemWorkflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - tenantId: string - version: 0 - workflow: - _id: string - addToInventory: true - addedOn: 0 - configId: string - currTaskIdx: 0 - description: string - endTime: 0 - execTime: 0 - imageId: string - instanceType: string - lastupdateOn: 0 - name: string - startTime: 0 - state: string - tasks: - - currWorkItemIdx: 0 - endTime: 0 - name: string - startTime: 0 - state: string - taskSeqNo: 0 - timeTaken: 0 - type: string - workItemList: - - command: string - endTime: 0 - outputStr: string - startTime: 0 - state: string - timeTaken: 0 - tenantId: string - type: string - useState: string - version: 0 - workflowParameters: - configList: - - configId: string - configParameters: - - key: string - value: string - licenseLevel: string - licenseType: string - topOfStackSerialNumber: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -1117,7 +207,6 @@ { "successList": [ { - "_id": "string", "id": "string", "deviceInfo": { "source": "string", diff --git a/plugins/modules/pnp_device_info.py b/plugins/modules/pnp_device_info.py index 06500ec52b..2899b2d637 100644 --- a/plugins/modules/pnp_device_info.py +++ b/plugins/modules/pnp_device_info.py @@ -13,8 +13,8 @@ - Get Pnp Device by id. - Returns device details specified by device id. - > - Returns list of devices based on filter crieteria. If a limit is not specified, it will default to return 50 - devices. Pagination and sorting are also supported by this endpoint. + Returns list of devices from Plug & Play based on filter criteria. Returns 50 devices by default. This endpoint + supports Pagination and Sorting. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -55,11 +55,6 @@ - OnbState query parameter. Device Onboarding State. elements: str type: list - cmState: - description: - - CmState query parameter. Device Connection Manager State. - elements: str - type: list name: description: - Name query parameter. Device Name. @@ -75,21 +70,11 @@ - Source query parameter. Device Source. elements: str type: list - projectId: - description: - - ProjectId query parameter. Device Project Id. - elements: str - type: list workflowId: description: - WorkflowId query parameter. Device Workflow Id. elements: str type: list - projectName: - description: - - ProjectName query parameter. Device Project Name. - elements: str - type: list workflowName: description: - WorkflowName query parameter. Device Workflow Name. @@ -126,8 +111,8 @@ - Id path parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetDeviceById description: Complete reference of the GetDeviceById API. @@ -164,13 +149,10 @@ serialNumber: [] state_: [] onbState: [] - cmState: [] name: [] pid: [] source: [] - projectId: [] workflowId: [] - projectName: [] workflowName: [] smartAccountId: [] virtualAccountId: [] @@ -194,7 +176,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_reset.py b/plugins/modules/pnp_device_reset.py index df5a7fe154..3470560f88 100644 --- a/plugins/modules/pnp_device_reset.py +++ b/plugins/modules/pnp_device_reset.py @@ -59,8 +59,8 @@ description: Pnp Device Reset's workflowId. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) ResetDevice description: Complete reference of the ResetDevice API. @@ -98,7 +98,6 @@ workflowId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_device_unclaim.py b/plugins/modules/pnp_device_unclaim.py index 81ac6a27be..47e4c00ef8 100644 --- a/plugins/modules/pnp_device_unclaim.py +++ b/plugins/modules/pnp_device_unclaim.py @@ -10,7 +10,7 @@ short_description: Resource module for Pnp Device Unclaim description: - Manage operation create of the resource Pnp Device Unclaim. -- Un-Claims one of more devices with specified workflow. +- Un-Claims one of more devices with specified workflow Deprecated . version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -21,8 +21,8 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) UnClaimDevice description: Complete reference of the UnClaimDevice API. @@ -50,7 +50,6 @@ - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_global_settings.py b/plugins/modules/pnp_global_settings.py index b7bd4f09ea..5c08d610d4 100644 --- a/plugins/modules/pnp_global_settings.py +++ b/plugins/modules/pnp_global_settings.py @@ -16,150 +16,81 @@ - cisco.dnac.module author: Rafael Campos (@racampos) options: - _id: - description: Pnp Global Settings's _id. - type: str - aaaCredentials: - description: Pnp Global Settings's aaaCredentials. - suboptions: - password: - description: Pnp Global Settings's password. - type: str - username: - description: Pnp Global Settings's username. - type: str - type: dict acceptEula: - description: AcceptEula flag. - type: bool + description: Accept Eula. + type: str defaultProfile: description: Pnp Global Settings's defaultProfile. suboptions: cert: - description: Pnp Global Settings's cert. + description: Cert. type: str fqdnAddresses: - description: Pnp Global Settings's fqdnAddresses. + description: Fqdn Addresses. elements: str type: list ipAddresses: - description: Pnp Global Settings's ipAddresses. + description: Ip Addresses. elements: str type: list port: - description: Pnp Global Settings's port. - type: int + description: Port. + type: str proxy: - description: Proxy flag. - type: bool + description: Proxy. + type: str type: dict + id: + description: Id. + type: str savaMappingList: description: Pnp Global Settings's savaMappingList. elements: dict suboptions: - autoSyncPeriod: - description: Pnp Global Settings's autoSyncPeriod. - type: int ccoUser: - description: Pnp Global Settings's ccoUser. + description: Cco User. type: str expiry: - description: Pnp Global Settings's expiry. - type: int - lastSync: - description: Pnp Global Settings's lastSync. - type: int + description: Expiry. + type: str profile: description: Pnp Global Settings's profile. suboptions: addressFqdn: - description: Pnp Global Settings's addressFqdn. + description: Address Fqdn. type: str addressIpV4: - description: Pnp Global Settings's addressIpV4. + description: Address Ip V4. type: str cert: - description: Pnp Global Settings's cert. + description: Cert. type: str makeDefault: - description: MakeDefault flag. - type: bool + description: Make Default. + type: str name: - description: Pnp Global Settings's name. + description: Name. type: str port: - description: Pnp Global Settings's port. - type: int + description: Port. + type: str profileId: - description: Pnp Global Settings's profileId. + description: Profile Id. type: str proxy: - description: Proxy flag. - type: bool - type: dict - smartAccountId: - description: Pnp Global Settings's smartAccountId. - type: str - syncResult: - description: Pnp Global Settings's syncResult. - suboptions: - syncList: - description: Pnp Global Settings's syncList. - elements: dict - suboptions: - deviceSnList: - description: Pnp Global Settings's deviceSnList. - elements: str - type: list - syncType: - description: Pnp Global Settings's syncType. - type: str - type: list - syncMsg: - description: Pnp Global Settings's syncMsg. + description: Proxy. type: str type: dict - syncResultStr: - description: Pnp Global Settings's syncResultStr. - type: str - syncStartTime: - description: Pnp Global Settings's syncStartTime. - type: int - syncStatus: - description: Pnp Global Settings's syncStatus. - type: str - tenantId: - description: Pnp Global Settings's tenantId. - type: str - token: - description: Pnp Global Settings's token. + smartAccountId: + description: Smart Account Id. type: str virtualAccountId: - description: Pnp Global Settings's virtualAccountId. + description: Virtual Account Id. type: str type: list - taskTimeOuts: - description: Pnp Global Settings's taskTimeOuts. - suboptions: - configTimeOut: - description: Pnp Global Settings's configTimeOut. - type: int - generalTimeOut: - description: Pnp Global Settings's generalTimeOut. - type: int - imageDownloadTimeOut: - description: Pnp Global Settings's imageDownloadTimeOut. - type: int - type: dict - tenantId: - description: Pnp Global Settings's tenantId. - type: str - version: - description: Pnp Global Settings's version. - type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) UpdatePnPGlobalSettings description: Complete reference of the UpdatePnPGlobalSettings API. @@ -184,55 +115,32 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" state: present - _id: string - aaaCredentials: - password: string - username: string - acceptEula: true + acceptEula: string defaultProfile: cert: string fqdnAddresses: - string ipAddresses: - string - port: 0 - proxy: true + port: string + proxy: string + id: string savaMappingList: - - autoSyncPeriod: 0 - ccoUser: string - expiry: 0 - lastSync: 0 + - ccoUser: string + expiry: string profile: addressFqdn: string addressIpV4: string cert: string - makeDefault: true + makeDefault: string name: string - port: 0 + port: string profileId: string - proxy: true + proxy: string smartAccountId: string - syncResult: - syncList: - - deviceSnList: - - string - syncType: string - syncMsg: string - syncResultStr: string - syncStartTime: 0 - syncStatus: string - tenantId: string - token: string virtualAccountId: string - taskTimeOuts: - configTimeOut: 0 - generalTimeOut: 0 - imageDownloadTimeOut: 0 - tenantId: string - version: 0 """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -299,7 +207,6 @@ }, "acceptEula": true, "id": "string", - "_id": "string", "version": 0 } """ diff --git a/plugins/modules/pnp_global_settings_info.py b/plugins/modules/pnp_global_settings_info.py index e9c124ec51..4ced097c3f 100644 --- a/plugins/modules/pnp_global_settings_info.py +++ b/plugins/modules/pnp_global_settings_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetPnPGlobalSettings description: Complete reference of the GetPnPGlobalSettings API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -116,7 +115,6 @@ }, "acceptEula": true, "id": "string", - "_id": "string", "version": 0 } """ diff --git a/plugins/modules/pnp_server_profile_update.py b/plugins/modules/pnp_server_profile_update.py index ee90a6978f..e51c2f5866 100644 --- a/plugins/modules/pnp_server_profile_update.py +++ b/plugins/modules/pnp_server_profile_update.py @@ -18,89 +18,46 @@ - cisco.dnac.module author: Rafael Campos (@racampos) options: - autoSyncPeriod: - description: Pnp Server Profile Update's autoSyncPeriod. - type: int ccoUser: - description: Pnp Server Profile Update's ccoUser. + description: Cco User. type: str - expiry: - description: Pnp Server Profile Update's expiry. - type: int - lastSync: - description: Pnp Server Profile Update's lastSync. - type: int profile: description: Pnp Server Profile Update's profile. suboptions: addressFqdn: - description: Pnp Server Profile Update's addressFqdn. + description: Address Fqdn. type: str addressIpV4: - description: Pnp Server Profile Update's addressIpV4. + description: Address Ip V4. type: str cert: - description: Pnp Server Profile Update's cert. + description: Cert. type: str makeDefault: - description: MakeDefault flag. + description: Make Default. type: bool name: - description: Pnp Server Profile Update's name. + description: Name. type: str port: - description: Pnp Server Profile Update's port. - type: int + description: Port. + type: float profileId: - description: Pnp Server Profile Update's profileId. + description: Profile Id. type: str proxy: - description: Proxy flag. + description: Proxy. type: bool type: dict smartAccountId: - description: Pnp Server Profile Update's smartAccountId. - type: str - syncResult: - description: Pnp Server Profile Update's syncResult. - suboptions: - syncList: - description: Pnp Server Profile Update's syncList. - elements: dict - suboptions: - deviceSnList: - description: Pnp Server Profile Update's deviceSnList. - elements: str - type: list - syncType: - description: Pnp Server Profile Update's syncType. - type: str - type: list - syncMsg: - description: Pnp Server Profile Update's syncMsg. - type: str - type: dict - syncResultStr: - description: Pnp Server Profile Update's syncResultStr. - type: str - syncStartTime: - description: Pnp Server Profile Update's syncStartTime. - type: int - syncStatus: - description: Pnp Server Profile Update's syncStatus. - type: str - tenantId: - description: Pnp Server Profile Update's tenantId. - type: str - token: - description: Pnp Server Profile Update's token. + description: Smart Account Id. type: str virtualAccountId: - description: Pnp Server Profile Update's virtualAccountId. + description: Virtual Account Id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) UpdatePnPServerProfile description: Complete reference of the UpdatePnPServerProfile API. @@ -124,10 +81,7 @@ dnac_port: "{{dnac_port}}" dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" - autoSyncPeriod: 0 ccoUser: string - expiry: 0 - lastSync: 0 profile: addressFqdn: string addressIpV4: string @@ -138,21 +92,9 @@ profileId: string proxy: true smartAccountId: string - syncResult: - syncList: - - deviceSnList: - - string - syncType: string - syncMsg: string - syncResultStr: string - syncStartTime: 0 - syncStatus: string - tenantId: string - token: string virtualAccountId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_smart_account_domains_info.py b/plugins/modules/pnp_smart_account_domains_info.py index bc612723a2..9472829730 100644 --- a/plugins/modules/pnp_smart_account_domains_info.py +++ b/plugins/modules/pnp_smart_account_domains_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetSmartAccountList description: Complete reference of the GetSmartAccountList API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_virtual_account_add.py b/plugins/modules/pnp_virtual_account_add.py index 7a3ceef874..6164411f2c 100644 --- a/plugins/modules/pnp_virtual_account_add.py +++ b/plugins/modules/pnp_virtual_account_add.py @@ -100,8 +100,8 @@ description: Pnp Virtual Account Add's virtualAccountId. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) AddVirtualAccount description: Complete reference of the AddVirtualAccount API. @@ -153,7 +153,6 @@ virtualAccountId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_virtual_account_deregister.py b/plugins/modules/pnp_virtual_account_deregister.py index 06af57d3b9..1aa0a0be84 100644 --- a/plugins/modules/pnp_virtual_account_deregister.py +++ b/plugins/modules/pnp_virtual_account_deregister.py @@ -26,8 +26,8 @@ description: Name query parameter. Virtual Account Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) DeregisterVirtualAccount description: Complete reference of the DeregisterVirtualAccount API. @@ -55,7 +55,6 @@ name: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_virtual_account_devices_sync.py b/plugins/modules/pnp_virtual_account_devices_sync.py index 208bd3352c..b0da9899ab 100644 --- a/plugins/modules/pnp_virtual_account_devices_sync.py +++ b/plugins/modules/pnp_virtual_account_devices_sync.py @@ -12,7 +12,7 @@ - Manage operation create of the resource Pnp Virtual Account Devices Sync. - > Synchronizes the device info from the given smart account & virtual account with the PnP database. The response - payload returns a list of synced devices. + payload returns a list of synced devices Deprecated . version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -99,8 +99,8 @@ description: Pnp Virtual Account Devices Sync's virtualAccountId. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) SyncVirtualAccountDevices description: Complete reference of the SyncVirtualAccountDevices API. @@ -152,7 +152,6 @@ virtualAccountId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_virtual_account_sync_result_info.py b/plugins/modules/pnp_virtual_account_sync_result_info.py index 61a07cb79f..64f16b99fd 100644 --- a/plugins/modules/pnp_virtual_account_sync_result_info.py +++ b/plugins/modules/pnp_virtual_account_sync_result_info.py @@ -10,7 +10,7 @@ short_description: Information module for Pnp Virtual Account Sync Result description: - Get all Pnp Virtual Account Sync Result. -- Returns the summary of devices synced from the given smart account & virtual account with PnP. +- Returns the summary of devices synced from the given smart account & virtual account with PnP Deprecated . version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -28,8 +28,8 @@ - Name path parameter. Virtual Account Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetSyncResultForVirtualAccount description: Complete reference of the GetSyncResultForVirtualAccount API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_virtual_accounts_info.py b/plugins/modules/pnp_virtual_accounts_info.py index 635a189d5d..548d52030d 100644 --- a/plugins/modules/pnp_virtual_accounts_info.py +++ b/plugins/modules/pnp_virtual_accounts_info.py @@ -24,8 +24,8 @@ - Domain path parameter. Smart Account Domain. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetVirtualAccountList description: Complete reference of the GetVirtualAccountList API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_workflow.py b/plugins/modules/pnp_workflow.py index d8658e0ea3..d1a9fa473f 100644 --- a/plugins/modules/pnp_workflow.py +++ b/plugins/modules/pnp_workflow.py @@ -128,8 +128,8 @@ description: Pnp Workflow's version. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) AddAWorkflow description: Complete reference of the AddAWorkflow API. @@ -258,7 +258,6 @@ version: 0 """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_workflow_count_info.py b/plugins/modules/pnp_workflow_count_info.py index 3c835c119b..65a86c79ab 100644 --- a/plugins/modules/pnp_workflow_count_info.py +++ b/plugins/modules/pnp_workflow_count_info.py @@ -25,8 +25,8 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetWorkflowCount description: Complete reference of the GetWorkflowCount API. @@ -55,7 +55,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/pnp_workflow_info.py b/plugins/modules/pnp_workflow_info.py index d91ea342b7..6ad13d548f 100644 --- a/plugins/modules/pnp_workflow_info.py +++ b/plugins/modules/pnp_workflow_info.py @@ -55,8 +55,8 @@ - Id path parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Device Onboarding (PnP) GetWorkflowById description: Complete reference of the GetWorkflowById API. @@ -108,7 +108,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/profiling_rules_count_info.py b/plugins/modules/profiling_rules_count_info.py index 461adba262..a7c9f8dca4 100644 --- a/plugins/modules/profiling_rules_count_info.py +++ b/plugins/modules/profiling_rules_count_info.py @@ -29,7 +29,7 @@ - IncludeDeleted query parameter. Flag to indicate whether deleted rules should be part of the records fetched. type: bool requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/profiling_rules_in_bulk_create.py b/plugins/modules/profiling_rules_in_bulk_create.py index ec2bfc306a..5819da497d 100644 --- a/plugins/modules/profiling_rules_in_bulk_create.py +++ b/plugins/modules/profiling_rules_in_bulk_create.py @@ -121,7 +121,7 @@ type: list type: list requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/projects_details_info.py b/plugins/modules/projects_details_info.py index 2185060fde..4cd5705c00 100644 --- a/plugins/modules/projects_details_info.py +++ b/plugins/modules/projects_details_info.py @@ -40,8 +40,8 @@ - SortOrder query parameter. Sort Order Ascending (asc) or Descending (dsc). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetProjectsDetails description: Complete reference of the GetProjectsDetails API. @@ -74,7 +74,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/provision_workflow_manager.py b/plugins/modules/provision_workflow_manager.py index cd99f3de61..41cf00f6b7 100644 --- a/plugins/modules/provision_workflow_manager.py +++ b/plugins/modules/provision_workflow_manager.py @@ -479,14 +479,17 @@ class instance for further use. device_type = self.want.get("device_type") if device_type == "wired": - status_response = self.dnac_apply['exec']( - family="sda", - function="get_provisioned_wired_device", - op_modifies=True, - params={ - "device_management_ip_address": self.validated_config[0]["management_ip_address"] - }, - ) + try: + status_response = self.dnac_apply['exec']( + family="sda", + function="get_provisioned_wired_device", + op_modifies=True, + params={ + "device_management_ip_address": self.validated_config[0]["management_ip_address"] + }, + ) + except Exception: + status_response = {} self.log("Wired device's status Response collected from 'get_provisioned_wired_device' API is:{0}".format(str(status_response)), "DEBUG") status = status_response.get("status") self.log("The provisioned status of the wired device is {0}".format(status), "INFO") diff --git a/plugins/modules/qos_device_interface.py b/plugins/modules/qos_device_interface.py index e9b67c7601..147e4f2396 100644 --- a/plugins/modules/qos_device_interface.py +++ b/plugins/modules/qos_device_interface.py @@ -70,8 +70,8 @@ type: list type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy CreateQosDeviceInterfaceInfo description: Complete reference of the CreateQosDeviceInterfaceInfo API. @@ -159,7 +159,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/qos_device_interface_info.py b/plugins/modules/qos_device_interface_info.py index ad7bb2bbef..3e68409dc5 100644 --- a/plugins/modules/qos_device_interface_info.py +++ b/plugins/modules/qos_device_interface_info.py @@ -24,8 +24,8 @@ - NetworkDeviceId query parameter. Network device id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetQosDeviceInterfaceInfo description: Complete reference of the GetQosDeviceInterfaceInfo API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/qos_device_interface_info_count_info.py b/plugins/modules/qos_device_interface_info_count_info.py index f77c2ce31f..7060c66699 100644 --- a/plugins/modules/qos_device_interface_info_count_info.py +++ b/plugins/modules/qos_device_interface_info_count_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Application Policy GetQosDeviceInterfaceInfoCount description: Complete reference of the GetQosDeviceInterfaceInfoCount API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reports.py b/plugins/modules/reports.py index 3e7eab25c4..2227dd501e 100644 --- a/plugins/modules/reports.py +++ b/plugins/modules/reports.py @@ -19,6 +19,9 @@ - cisco.dnac.module author: Rafael Campos (@racampos) options: + dataCategory: + description: Category of viewgroup for the report. + type: str deliveries: description: Array of available delivery channels. elements: dict @@ -103,8 +106,8 @@ description: Version of viewgroup for the report. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Reports CreateOrScheduleAReport description: Complete reference of the CreateOrScheduleAReport API. @@ -134,6 +137,7 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" state: present + dataCategory: string deliveries: - {} name: string @@ -173,7 +177,6 @@ reportId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reports_executions_info.py b/plugins/modules/reports_executions_info.py index f12cd7caa1..afb64b7ddc 100644 --- a/plugins/modules/reports_executions_info.py +++ b/plugins/modules/reports_executions_info.py @@ -44,8 +44,8 @@ - The filename used to save the download file. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Reports DownloadReportContent description: Complete reference of the DownloadReportContent API. @@ -93,7 +93,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reports_info.py b/plugins/modules/reports_info.py index aed7e10df6..f0e58b723e 100644 --- a/plugins/modules/reports_info.py +++ b/plugins/modules/reports_info.py @@ -34,8 +34,8 @@ - ReportId path parameter. ReportId of report. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Reports GetAScheduledReport description: Complete reference of the GetAScheduledReport API. @@ -83,7 +83,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reports_view_group_info.py b/plugins/modules/reports_view_group_info.py index 76b1317181..81219c69e4 100644 --- a/plugins/modules/reports_view_group_info.py +++ b/plugins/modules/reports_view_group_info.py @@ -28,8 +28,8 @@ - ViewGroupId path parameter. ViewGroupId of viewgroup. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Reports GetAllViewGroups description: Complete reference of the GetAllViewGroups API. @@ -75,7 +75,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reports_view_group_view_info.py b/plugins/modules/reports_view_group_view_info.py index 11889bac94..2eb44befa3 100644 --- a/plugins/modules/reports_view_group_view_info.py +++ b/plugins/modules/reports_view_group_view_info.py @@ -30,8 +30,8 @@ - ViewId path parameter. View id of view. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Reports GetViewDetailsForAGivenViewGroup_View description: Complete reference of the GetViewDetailsForAGivenViewGroup_View API. @@ -61,7 +61,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reserve_ip_subpool.py b/plugins/modules/reserve_ip_subpool.py index 507b0e0783..779dbc0910 100644 --- a/plugins/modules/reserve_ip_subpool.py +++ b/plugins/modules/reserve_ip_subpool.py @@ -22,11 +22,11 @@ description: Id path parameter. Id of reserve ip subpool to be deleted. type: str ipv4DhcpServers: - description: IPv4 input for dhcp server ip example 1.1.1.1. + description: IPv4 input for dhcp server ip example "1.1.1.1". elements: str type: list ipv4DnsServers: - description: IPv4 input for dns server ip example 4.4.4.4. + description: IPv4 input for dns server ip example "4.4.4.4". elements: str type: list ipv4GateWay: @@ -44,21 +44,22 @@ description: The ipv4 prefix length is required when ipv4prefix value is true. type: int ipv4Subnet: - description: IPv4 Subnet address, example 175.175.0.0. + description: IPv4 Subnet address, example 175.175.0.0. Either ipv4Subnet or ipv4TotalHost + needs to be passed if creating IPv4 subpool. type: str ipv4TotalHost: description: IPv4 total host is required when ipv4prefix value is false. type: int ipv6AddressSpace: - description: If the value is false only ipv4 input are required, otherwise both - ipv6 and ipv4 are required. + description: If the value is omitted or false only ipv4 input are required, otherwise + both ipv6 and ipv4 are required. type: bool ipv6DhcpServers: - description: IPv6 format dhcp server as input example 2001 db8 1234. + description: IPv6 format dhcp server as input example "2001 db8 1234". elements: str type: list ipv6DnsServers: - description: IPv6 format dns server input example 2001 db8 1234. + description: IPv6 format dns server input example "2001 db8 1234". elements: str type: list ipv6GateWay: @@ -76,7 +77,8 @@ description: IPv6 prefix length is required when the ipv6prefix value is true. type: int ipv6Subnet: - description: IPv6 Subnet address, example 2001 db8 85a3 0 100. + description: IPv6 Subnet address, example 2001 db8 85a3 0 100. Either ipv6Subnet + or ipv6TotalHost needs to be passed if creating IPv6 subpool. type: str ipv6TotalHost: description: IPv6 total host is required when ipv6prefix value is false. @@ -94,8 +96,8 @@ description: Type of the reserve ip sub pool. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings ReserveIPSubpool description: Complete reference of the ReserveIPSubpool API. @@ -200,7 +202,6 @@ slaacSupport: true """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reserve_ip_subpool_create.py b/plugins/modules/reserve_ip_subpool_create.py index 699e7c96cb..55f70ba8bd 100644 --- a/plugins/modules/reserve_ip_subpool_create.py +++ b/plugins/modules/reserve_ip_subpool_create.py @@ -17,11 +17,11 @@ author: Rafael Campos (@racampos) options: ipv4DhcpServers: - description: IPv4 input for dhcp server ip example 1.1.1.1. + description: IPv4 input for dhcp server ip example "1.1.1.1". elements: str type: list ipv4DnsServers: - description: IPv4 input for dns server ip example 4.4.4.4. + description: IPv4 input for dns server ip example "4.4.4.4". elements: str type: list ipv4GateWay: @@ -38,21 +38,22 @@ description: The ipv4 prefix length is required when ipv4prefix value is true. type: int ipv4Subnet: - description: IPv4 Subnet address, example 175.175.0.0. + description: IPv4 Subnet address, example 175.175.0.0. Either ipv4Subnet or ipv4TotalHost + needs to be passed if creating IPv4 subpool. type: str ipv4TotalHost: description: IPv4 total host is required when ipv4prefix value is false. type: int ipv6AddressSpace: - description: If the value is false only ipv4 input are required, otherwise both - ipv6 and ipv4 are required. + description: If the value is omitted or false only ipv4 input are required, otherwise + both ipv6 and ipv4 are required. type: bool ipv6DhcpServers: - description: IPv6 format dhcp server as input example 2001 db8 1234. + description: IPv6 format dhcp server as input example "2001 db8 1234". elements: str type: list ipv6DnsServers: - description: IPv6 format dns server input example 2001 db8 1234. + description: IPv6 format dns server input example "2001 db8 1234". elements: str type: list ipv6GateWay: @@ -70,7 +71,8 @@ description: IPv6 prefix length is required when the ipv6prefix value is true. type: int ipv6Subnet: - description: IPv6 Subnet address, example 2001 db8 85a3 0 100. + description: IPv6 Subnet address, example 2001 db8 85a3 0 100. Either ipv6Subnet + or ipv6TotalHost needs to be passed if creating IPv6 subpool. type: str ipv6TotalHost: description: IPv6 total host is required when ipv6prefix value is false. @@ -88,8 +90,8 @@ description: Type of the reserve ip sub pool. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings ReserveIPSubpool description: Complete reference of the ReserveIPSubpool API. @@ -140,7 +142,6 @@ type: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reserve_ip_subpool_delete.py b/plugins/modules/reserve_ip_subpool_delete.py index 65ecd4733c..18bd1decb8 100644 --- a/plugins/modules/reserve_ip_subpool_delete.py +++ b/plugins/modules/reserve_ip_subpool_delete.py @@ -20,8 +20,8 @@ description: Id path parameter. Id of reserve ip subpool to be deleted. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings ReleaseReserveIPSubpool description: Complete reference of the ReleaseReserveIPSubpool API. @@ -48,7 +48,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reserve_ip_subpool_info.py b/plugins/modules/reserve_ip_subpool_info.py index ec3c76d16c..5a787a7d3e 100644 --- a/plugins/modules/reserve_ip_subpool_info.py +++ b/plugins/modules/reserve_ip_subpool_info.py @@ -21,19 +21,37 @@ type: dict siteId: description: - - SiteId query parameter. Site id to get the reserve ip associated with the site. + - > + SiteId query parameter. Site id of site from which to retrieve associated reserve pools. Either siteId (per + site queries) or ignoreInheritedGroups must be used. They can also be used together. type: str offset: description: - - Offset query parameter. Offset/starting row. - type: int + - Offset query parameter. Offset/starting row. Indexed from 1. + type: float limit: description: - - Limit query parameter. No of Global Pools to be retrieved. - type: int + - > + Limit query parameter. Number of reserve pools to be retrieved. Default is 25 if not specified. Maximum + allowed limit is 500. + type: float + ignoreInheritedGroups: + description: + - > + IgnoreInheritedGroups query parameter. Ignores pools inherited from parent site. Either siteId or + ignoreInheritedGroups must be passed. They can also be used together. + type: str + poolUsage: + description: + - PoolUsage query parameter. Can take values empty, partially-full or empty-partially-full. + type: str + groupName: + description: + - GroupName query parameter. Name of the group. + type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings GetReserveIPSubpool description: Complete reference of the GetReserveIPSubpool API. @@ -61,10 +79,12 @@ siteId: string offset: 0 limit: 0 + ignoreInheritedGroups: string + poolUsage: string + groupName: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/reserve_ip_subpool_update.py b/plugins/modules/reserve_ip_subpool_update.py index 4bf71c42ce..93dc11c0c8 100644 --- a/plugins/modules/reserve_ip_subpool_update.py +++ b/plugins/modules/reserve_ip_subpool_update.py @@ -17,50 +17,51 @@ author: Rafael Campos (@racampos) options: id: - description: Id query parameter. Id of subpool to be associated with the site. + description: Id query parameter. Id of subpool group. type: str ipv4DhcpServers: - description: IPv4 input for dhcp server ip example 1.1.1.1. + description: IPv4 input for dhcp server ip example "1.1.1.1". elements: str type: list ipv4DnsServers: - description: IPv4 input for dns server ip example 4.4.4.4. + description: IPv4 input for dns server ip example "4.4.4.4". elements: str type: list ipv4GateWay: - description: Ipv4 Gate Way. + description: Gateway ip address details, example 175.175.0.1. type: str ipv6AddressSpace: - description: If the value is false only ipv4 input are required, otherwise both - ipv6 and ipv4 are required. + description: If the value is false only ipv4 input are required. NOTE if value is + false then any existing ipv6 subpool in the group will be removed. type: bool ipv6DhcpServers: - description: IPv6 format dhcp server as input example 2001 db8 1234. + description: IPv6 format dhcp server as input example "2001 db8 1234". elements: str type: list ipv6DnsServers: - description: IPv6 format dns server input example 2001 db8 1234. + description: IPv6 format dns server input example "2001 db8 1234". elements: str type: list ipv6GateWay: description: Gateway ip address details, example 2001 db8 85a3 0 100 1. type: str ipv6GlobalPool: - description: IP v6 Global pool address with cidr this is required when Ipv6AddressSpace + description: IPv6 Global pool address with cidr this is required when Ipv6AddressSpace value is true, example 2001 db8 85a3 /64. type: str ipv6Prefix: - description: IPv6 prefix value is true, the ip6 prefix length input field is enabled - , if it is false ipv6 total Host input is enable. + description: Ipv6 prefix value is true, the ip6 prefix length input field is enabled, + if it is false ipv6 total Host input is enable. type: bool ipv6PrefixLength: description: IPv6 prefix length is required when the ipv6prefix value is true. type: int ipv6Subnet: - description: IPv6 Subnet address, example 2001 db8 85a3 0 100. + description: IPv6 Subnet address, example 2001 db8 85a3 0 100 . type: str ipv6TotalHost: - description: IPv6 total host is required when ipv6prefix value is false. + description: Size of pool in terms of number of IPs. IPv6 total host is required + when ipv6prefix value is false. type: int name: description: Name of the reserve ip sub pool. @@ -72,8 +73,8 @@ description: Slaac Support. type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateReserveIPSubpool description: Complete reference of the UpdateReserveIPSubpool API. @@ -122,7 +123,6 @@ slaacSupport: true """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/role_permissions_info.py b/plugins/modules/role_permissions_info.py index 51957ed067..6354356651 100644 --- a/plugins/modules/role_permissions_info.py +++ b/plugins/modules/role_permissions_info.py @@ -11,7 +11,7 @@ description: - Get all Role Permissions. - Get permissions for a role from Cisco DNA Center System. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -20,15 +20,15 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for User and Roles GetPermissionsAPI description: Complete reference of the GetPermissionsAPI API. link: https://developer.cisco.com/docs/dna-center/#!get-permissions-api notes: - SDK Method used are - user_and_roles.UserandRoles.get_permissions_ap_i, + userand_roles.UserandRoles.get_permissions_api, - Paths used are get /dna/system/api/v1/role/permissions, @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/roles.py b/plugins/modules/roles.py new file mode 100644 index 0000000000..c5d1aca2dc --- /dev/null +++ b/plugins/modules/roles.py @@ -0,0 +1,127 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: roles +short_description: Resource module for Roles +description: +- Manage operations create, update and delete of the resource Roles. +- Add a new role in Cisco DNA Center System. +- Delete a role in Cisco DNA Center System. +- Update a role in Cisco DNA Center System. +version_added: '3.1.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + description: + description: Description of role. + type: str + resourceTypes: + description: Roles's resourceTypes. + elements: dict + suboptions: + operations: + description: List of operations allowed for the application. Possible values + are "gRead", "gWrite", "gUpdate", "gDelete", or some combination of these. + elements: str + type: list + type: + description: Name of the application in Cisco DNA Center System. + type: str + type: list + role: + description: Name of the role. + type: str + roleId: + description: Id of the role. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for User and Roles AddRoleAPI + description: Complete reference of the AddRoleAPI API. + link: https://developer.cisco.com/docs/dna-center/#!add-role-api +- name: Cisco DNA Center documentation for User and Roles DeleteRoleAPI + description: Complete reference of the DeleteRoleAPI API. + link: https://developer.cisco.com/docs/dna-center/#!delete-role-api +- name: Cisco DNA Center documentation for User and Roles UpdateRoleAPI + description: Complete reference of the UpdateRoleAPI API. + link: https://developer.cisco.com/docs/dna-center/#!update-role-api +notes: + - SDK Method used are + userand_roles.UserandRoles.add_role_api, + userand_roles.UserandRoles.delete_role_api, + userand_roles.UserandRoles.update_role_api, + + - Paths used are + post /dna/system/api/v1/role, + delete /dna/system/api/v1/role/{roleId}, + put /dna/system/api/v1/role, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.roles: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + description: string + resourceTypes: + - operations: + - string + type: string + role: string + +- name: Update all + cisco.dnac.roles: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + description: string + resourceTypes: + - operations: + - string + type: string + roleId: string + +- name: Delete by id + cisco.dnac.roles: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + roleId: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "roleId": "string", + "message": "string" + } +""" diff --git a/plugins/modules/roles_info.py b/plugins/modules/roles_info.py index a8ce30ddfc..deb930512a 100644 --- a/plugins/modules/roles_info.py +++ b/plugins/modules/roles_info.py @@ -10,8 +10,8 @@ short_description: Information module for Roles description: - Get all Roles. -- Get all roles for the Cisco DNA Center system. -version_added: '6.7.0' +- Get all roles for the Cisco DNA Center System. +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -20,15 +20,15 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for User and Roles GetRolesAPI description: Complete reference of the GetRolesAPI API. link: https://developer.cisco.com/docs/dna-center/#!get-roles-api notes: - SDK Method used are - user_and_roles.UserandRoles.get_roles_ap_i, + userand_roles.UserandRoles.get_roles_api, - Paths used are get /dna/system/api/v1/roles, @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_anycast_gateways.py b/plugins/modules/sda_anycast_gateways.py new file mode 100644 index 0000000000..70080060d4 --- /dev/null +++ b/plugins/modules/sda_anycast_gateways.py @@ -0,0 +1,203 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_anycast_gateways +short_description: Resource module for Sda Anycastgateways +description: +- Manage operations create, update and delete of the resource Sda Anycastgateways. +- Adds anycast gateways based on user input. +- Deletes an anycast gateway based on id. +- Updates anycast gateways based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. ID of the anycast gateway to be deleted. + type: str + payload: + description: Sda Anycast Gateways's payload. + elements: dict + suboptions: + fabricId: + description: ID of the fabric containing this anycast gateway. Updating anycast + gateways on fabric zones is not allowed--instead, update the corresponding + anycast gateway on the fabric site and the updates will be applied on all + applicable fabric zones (updating this field is not allowed). + type: str + id: + description: ID of the anycast gateway (updating this field is not allowed). + type: str + ipPoolName: + description: Name of the IP pool associated with the anycast gateway (updating + this field is not allowed). + type: str + isCriticalPool: + description: Enable/disable critical VLAN (not applicable to INFRA_VN; updating + this field is not allowed). + type: bool + isIntraSubnetRoutingEnabled: + description: Enable/disable Intra-Subnet Routing (not applicable to INFRA_VN; + updating this field is not allowed). + type: bool + isIpDirectedBroadcast: + description: Enable/disable IP-directed broadcast (not applicable to INFRA_VN). + type: bool + isLayer2FloodingEnabled: + description: Enable/disable layer 2 flooding (not applicable to INFRA_VN). + type: bool + isMultipleIpToMacAddresses: + description: Enable/disable multiple IP-to-MAC Addresses (Wireless Bridged-Network + Virtual Machine; not applicable to INFRA_VN). + type: bool + isSupplicantBasedExtendedNodeOnboarding: + description: Enable/disable Supplicant-Based Extended Node Onboarding (applicable + only to INFRA_VN; required when poolType is EXTENDED_NODE). + type: bool + isWirelessPool: + description: Enable/disable fabric-enabled wireless (not applicable to INFRA_VN). + type: bool + poolType: + description: The pool type of the anycast gateway (applicable only to INFRA_VN; + updating this field is not allowed). + type: str + securityGroupName: + description: Name of the associated Security Group (not applicable to INFRA_VN). + type: str + tcpMssAdjustment: + description: TCP maximum segment size adjustment. + type: int + trafficType: + description: The type of traffic the anycast gateway serves. + type: str + virtualNetworkName: + description: Name of the layer 3 virtual network associated with the anycast + gateway (updating this field is not allowed). + type: str + vlanId: + description: ID of the VLAN of the anycast gateway (updating this field is not + allowed). + type: int + vlanName: + description: Name of the VLAN of the anycast gateway (updating this field is + not allowed). + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddAnycastGateways + description: Complete reference of the AddAnycastGateways API. + link: https://developer.cisco.com/docs/dna-center/#!add-anycast-gateways +- name: Cisco DNA Center documentation for SDA DeleteAnycastGatewayById + description: Complete reference of the DeleteAnycastGatewayById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-anycast-gateway-by-id +- name: Cisco DNA Center documentation for SDA UpdateAnycastGateways + description: Complete reference of the UpdateAnycastGateways API. + link: https://developer.cisco.com/docs/dna-center/#!update-anycast-gateways +notes: + - SDK Method used are + sda.Sda.add_anycast_gateways, + sda.Sda.delete_anycast_gateway_by_id, + sda.Sda.update_anycast_gateways, + + - Paths used are + post /dna/intent/api/v1/sda/anycastGateways, + delete /dna/intent/api/v1/sda/anycastGateways/{id}, + put /dna/intent/api/v1/sda/anycastGateways, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.sda_anycast_gateways: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - fabricId: string + id: string + ipPoolName: string + isCriticalPool: true + isIntraSubnetRoutingEnabled: true + isIpDirectedBroadcast: true + isLayer2FloodingEnabled: true + isMultipleIpToMacAddresses: true + isSupplicantBasedExtendedNodeOnboarding: true + isWirelessPool: true + poolType: string + securityGroupName: string + tcpMssAdjustment: 0 + trafficType: string + virtualNetworkName: string + vlanId: 0 + vlanName: string + +- name: Create + cisco.dnac.sda_anycastGateways: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - autoGenerateVlanName: true + fabricId: string + ipPoolName: string + isCriticalPool: true + isIntraSubnetRoutingEnabled: true + isIpDirectedBroadcast: true + isLayer2FloodingEnabled: true + isMultipleIpToMacAddresses: true + isSupplicantBasedExtendedNodeOnboarding: true + isWirelessPool: true + poolType: string + securityGroupName: string + tcpMssAdjustment: 0 + trafficType: string + virtualNetworkName: string + vlanId: 0 + vlanName: string + +- name: Delete by id + cisco.dnac.sda_anycastGateways: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_anycast_gateways_count_info.py b/plugins/modules/sda_anycast_gateways_count_info.py new file mode 100644 index 0000000000..e9bf1cf195 --- /dev/null +++ b/plugins/modules/sda_anycast_gateways_count_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_anycast_gateways_count_info +short_description: Information module for Sda Anycastgateways Count +description: +- Get all Sda Anycastgateways Count. +- Returns the count of anycast gateways that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. Only count anycast gateways within this fabric. + type: str + virtualNetworkName: + description: + - VirtualNetworkName query parameter. Only count anycast gateways associated with this virtual network. + type: str + ipPoolName: + description: + - IpPoolName query parameter. Only count anycast gateways associated with this IP pool. + type: str + vlanName: + description: + - VlanName query parameter. Only count anycast gateways associated with this VLAN name. + type: str + vlanId: + description: + - VlanId query parameter. Only count anycast gateways associated with this VLAN ID. + type: int +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetAnycastGatewayCount + description: Complete reference of the GetAnycastGatewayCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-anycast-gateway-count +notes: + - SDK Method used are + sda.Sda.get_anycast_gateway_count, + + - Paths used are + get /dna/intent/api/v1/sda/anycastGateways/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Anycastgateways Count + cisco.dnac.sda_anycast_gateways_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + virtualNetworkName: string + ipPoolName: string + vlanName: string + vlanId: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_anycast_gateways_info.py b/plugins/modules/sda_anycast_gateways_info.py new file mode 100644 index 0000000000..6a81154f59 --- /dev/null +++ b/plugins/modules/sda_anycast_gateways_info.py @@ -0,0 +1,122 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_anycast_gateways_info +short_description: Information module for Sda Anycastgateways +description: +- Get all Sda Anycastgateways. +- Returns a list of anycast gateways that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + id: + description: + - Id query parameter. ID of the anycast gateway to search for in the database. + type: str + fabricId: + description: + - FabricId query parameter. Get anycast gateways within this fabric. + type: str + virtualNetworkName: + description: + - VirtualNetworkName query parameter. Get anycast gateways associated with this virtual network. + type: str + ipPoolName: + description: + - IpPoolName query parameter. Get anycast gateways associated with this IP pool. + type: str + vlanName: + description: + - VlanName query parameter. Get anycast gateways associated with this VLAN name. + type: str + vlanId: + description: + - VlanId query parameter. Get anycast gateways associated with this VLAN ID. + type: int + offset: + description: + - Offset query parameter. Starting record for pagination. + type: int + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: int +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetAnycastGateways + description: Complete reference of the GetAnycastGateways API. + link: https://developer.cisco.com/docs/dna-center/#!get-anycast-gateways +notes: + - SDK Method used are + sda.Sda.get_anycast_gateways, + + - Paths used are + get /dna/intent/api/v1/sda/anycastGateways, + +""" + +EXAMPLES = r""" +- name: Get all Sda Anycastgateways + cisco.dnac.sda_anycast_gateways_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + id: string + fabricId: string + virtualNetworkName: string + ipPoolName: string + vlanName: string + vlanId: 0 + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "fabricId": "string", + "virtualNetworkName": "string", + "ipPoolName": "string", + "tcpMssAdjustment": 0, + "vlanName": "string", + "vlanId": 0, + "trafficType": "string", + "poolType": "string", + "securityGroupName": "string", + "isCriticalPool": true, + "isLayer2FloodingEnabled": true, + "isWirelessPool": true, + "isIpDirectedBroadcast": true, + "isIntraSubnetRoutingEnabled": true, + "isMultipleIpToMacAddresses": true, + "isSupplicantBasedExtendedNodeOnboarding": true + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_authentication_profiles.py b/plugins/modules/sda_authentication_profiles.py new file mode 100644 index 0000000000..ec31b797e5 --- /dev/null +++ b/plugins/modules/sda_authentication_profiles.py @@ -0,0 +1,96 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_authentication_profiles +short_description: Resource module for Sda Authenticationprofiles +description: +- Manage operation update of the resource Sda Authenticationprofiles. +- Updates an authentication profile based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + payload: + description: Sda Authentication Profiles's payload. + elements: dict + suboptions: + authenticationOrder: + description: First authentication method. + type: str + authenticationProfileName: + description: The default host authentication template (updating this field is + not allowed). + type: str + dot1xToMabFallbackTimeout: + description: 802.1x Timeout. + type: int + fabricId: + description: ID of the fabric site/zone (updating this field is not allowed). + type: str + id: + description: ID of the authentication profile (updating this field is not allowed). + type: str + numberOfHosts: + description: Number of Hosts. + type: str + wakeOnLan: + description: Wake on LAN. + type: bool + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA UpdateAuthenticationProfile + description: Complete reference of the UpdateAuthenticationProfile API. + link: https://developer.cisco.com/docs/dna-center/#!update-authentication-profile +notes: + - SDK Method used are + sda.Sda.update_authentication_profile, + + - Paths used are + put /dna/intent/api/v1/sda/authenticationProfiles, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.sda_authentication_profiles: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - authenticationOrder: string + authenticationProfileName: string + dot1xToMabFallbackTimeout: 0 + fabricId: string + id: string + numberOfHosts: string + wakeOnLan: true + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_authentication_profiles_info.py b/plugins/modules/sda_authentication_profiles_info.py new file mode 100644 index 0000000000..27da6f55d8 --- /dev/null +++ b/plugins/modules/sda_authentication_profiles_info.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_authentication_profiles_info +short_description: Information module for Sda Authenticationprofiles +description: +- Get all Sda Authenticationprofiles. +- Returns a list of authentication profiles that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric whose authentication profiles are to be returned. + type: str + authenticationProfileName: + description: + - > + AuthenticationProfileName query parameter. Return only the authentication profiles with this specified name. + Note that 'No Authentication' is not a valid option for this parameter. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetAuthenticationProfiles + description: Complete reference of the GetAuthenticationProfiles API. + link: https://developer.cisco.com/docs/dna-center/#!get-authentication-profiles +notes: + - SDK Method used are + sda.Sda.get_authentication_profiles, + + - Paths used are + get /dna/intent/api/v1/sda/authenticationProfiles, + +""" + +EXAMPLES = r""" +- name: Get all Sda Authenticationprofiles + cisco.dnac.sda_authentication_profiles_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + authenticationProfileName: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "fabricId": "string", + "authenticationProfileName": "string", + "authenticationOrder": "string", + "dot1xToMabFallbackTimeout": 0, + "wakeOnLan": true, + "numberOfHosts": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_count_info.py b/plugins/modules/sda_count_info.py index d942591c12..a8a2ce8afb 100644 --- a/plugins/modules/sda_count_info.py +++ b/plugins/modules/sda_count_info.py @@ -20,7 +20,7 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/sda_device_info.py b/plugins/modules/sda_device_info.py index 22029fe55b..2ccc129f92 100644 --- a/plugins/modules/sda_device_info.py +++ b/plugins/modules/sda_device_info.py @@ -24,8 +24,8 @@ - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetDeviceInfoFromSDAFabric description: Complete reference of the GetDeviceInfoFromSDAFabric API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_device_role_info.py b/plugins/modules/sda_device_role_info.py index b06a698a18..09efaf717d 100644 --- a/plugins/modules/sda_device_role_info.py +++ b/plugins/modules/sda_device_role_info.py @@ -24,8 +24,8 @@ - DeviceManagementIpAddress query parameter. Device Management IP Address. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetDeviceRoleInSDAFabric description: Complete reference of the GetDeviceRoleInSDAFabric API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -62,13 +61,10 @@ type: dict sample: > { - "response": { - "status": "string", - "description": "string", - "roles": [ - "string" - ] - }, - "version": "string" + "roles": [ + "string" + ], + "status": "string", + "description": "string" } """ diff --git a/plugins/modules/sda_extranet_policies.py b/plugins/modules/sda_extranet_policies.py new file mode 100644 index 0000000000..8a4df37a30 --- /dev/null +++ b/plugins/modules/sda_extranet_policies.py @@ -0,0 +1,140 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_extranet_policies +short_description: Resource module for Sda Extranetpolicies +description: +- Manage operations create, update and delete of the resource Sda Extranetpolicies. +- Adds an extranet policy based on user input. +- Deletes an extranet policy based on id. +- Updates an extranet policy based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. ID of the extranet policy. + type: str + payload: + description: Sda Extranet Policies's payload. + elements: dict + suboptions: + extranetPolicyName: + description: Name of the existing extranet policy (updating this field is not + allowed). + type: str + fabricIds: + description: ID of the fabric sites/zones that associated with this extranet + policy. + elements: str + type: list + id: + description: ID of the existing extranet policy (updating this field is not + allowed). + type: str + providerVirtualNetworkName: + description: Name of the existing provider virtual network (updating this field + is not allowed). + type: str + subscriberVirtualNetworkNames: + description: Name of the subscriber virtual networks. + elements: str + type: list + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddExtranetPolicy + description: Complete reference of the AddExtranetPolicy API. + link: https://developer.cisco.com/docs/dna-center/#!add-extranet-policy +- name: Cisco DNA Center documentation for SDA DeleteExtranetPolicyById + description: Complete reference of the DeleteExtranetPolicyById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-extranet-policy-by-id +- name: Cisco DNA Center documentation for SDA UpdateExtranetPolicy + description: Complete reference of the UpdateExtranetPolicy API. + link: https://developer.cisco.com/docs/dna-center/#!update-extranet-policy +notes: + - SDK Method used are + sda.Sda.add_extranet_policy, + sda.Sda.delete_extranet_policy_by_id, + sda.Sda.update_extranet_policy, + + - Paths used are + post /dna/intent/api/v1/sda/extranetPolicies, + delete /dna/intent/api/v1/sda/extranetPolicies/{id}, + put /dna/intent/api/v1/sda/extranetPolicies, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.sda_extranet_policies: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - extranetPolicyName: string + fabricIds: + - string + id: string + providerVirtualNetworkName: string + subscriberVirtualNetworkNames: + - string + +- name: Create + cisco.dnac.sda_extranet_policies: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - extranetPolicyName: string + fabricIds: + - string + providerVirtualNetworkName: string + subscriberVirtualNetworkNames: + - string + +- name: Delete by id + cisco.dnac.sda_extranet_policies: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_extranet_policies_count_info.py b/plugins/modules/sda_extranet_policies_count_info.py new file mode 100644 index 0000000000..37e163f95b --- /dev/null +++ b/plugins/modules/sda_extranet_policies_count_info.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_extranet_policies_count_info +short_description: Information module for Sda Extranetpolicies Count +description: +- Get all Sda Extranetpolicies Count. +- Returns the count of extranet policies that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetExtranetPolicyCount + description: Complete reference of the GetExtranetPolicyCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-extranet-policy-count +notes: + - SDK Method used are + sda.Sda.get_extranet_policy_count, + + - Paths used are + get /dna/intent/api/v1/sda/extranetPolicies/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Extranetpolicies Count + cisco.dnac.sda_extranet_policies_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_extranet_policies_info.py b/plugins/modules/sda_extranet_policies_info.py new file mode 100644 index 0000000000..582ab76c63 --- /dev/null +++ b/plugins/modules/sda_extranet_policies_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_extranet_policies_info +short_description: Information module for Sda Extranetpolicies +description: +- Get all Sda Extranetpolicies. +- Returns a list of extranet policies that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + extranetPolicyName: + description: + - ExtranetPolicyName query parameter. Name of the extranet policy. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: float + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetExtranetPolicies + description: Complete reference of the GetExtranetPolicies API. + link: https://developer.cisco.com/docs/dna-center/#!get-extranet-policies +notes: + - SDK Method used are + sda.Sda.get_extranet_policies, + + - Paths used are + get /dna/intent/api/v1/sda/extranetPolicies, + +""" + +EXAMPLES = r""" +- name: Get all Sda Extranetpolicies + cisco.dnac.sda_extranet_policies_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + extranetPolicyName: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "extranetPolicyName": "string", + "fabricIds": [ + "string" + ], + "providerVirtualNetworkName": "string", + "subscriberVirtualNetworkNames": [ + "string" + ] + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric.py b/plugins/modules/sda_fabric.py index f068b0e1e4..9ab5c6c06d 100644 --- a/plugins/modules/sda_fabric.py +++ b/plugins/modules/sda_fabric.py @@ -21,7 +21,7 @@ description: FabricName query parameter. Fabric Name. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/sda_fabric_authentication_profile.py b/plugins/modules/sda_fabric_authentication_profile.py index 925e28fa1a..924114ff3e 100644 --- a/plugins/modules/sda_fabric_authentication_profile.py +++ b/plugins/modules/sda_fabric_authentication_profile.py @@ -34,8 +34,8 @@ description: SiteNameHierarchy query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddDefaultAuthenticationTemplateInSDAFabric description: Complete reference of the AddDefaultAuthenticationTemplateInSDAFabric API. @@ -105,7 +105,6 @@ siteNameHierarchy: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_authentication_profile_info.py b/plugins/modules/sda_fabric_authentication_profile_info.py index 619af5f016..b5fa4849ac 100644 --- a/plugins/modules/sda_fabric_authentication_profile_info.py +++ b/plugins/modules/sda_fabric_authentication_profile_info.py @@ -29,8 +29,8 @@ - AuthenticateTemplateName query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetDefaultAuthenticationProfileFromSDAFabric description: Complete reference of the GetDefaultAuthenticationProfileFromSDAFabric API. @@ -60,24 +60,21 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: list - elements: dict + type: dict sample: > - [ - { - "siteNameHierarchy": "string", - "authenticateTemplateName": "string", - "authenticationOrder": "string", - "dot1xToMabFallbackTimeout": "string", - "wakeOnLan": true, - "numberOfHosts": "string", - "status": "string", - "description": "string" - } - ] + { + "siteNameHierarchy": "string", + "authenticateTemplateName": "string", + "authenticationOrder": "string", + "dot1xToMabFallbackTimeout": "string", + "wakeOnLan": true, + "numberOfHosts": "string", + "status": "string", + "description": "string", + "executionId": "string" + } """ diff --git a/plugins/modules/sda_fabric_border_device.py b/plugins/modules/sda_fabric_border_device.py index e2441daf86..1b4778f067 100644 --- a/plugins/modules/sda_fabric_border_device.py +++ b/plugins/modules/sda_fabric_border_device.py @@ -110,7 +110,7 @@ description: External Domain Routing Protocol Name. type: str internalAutonomouSystemNumber: - description: Internal Autonomouns System Number (e.g.,1-65535). + description: Internal Autonomous System Number. type: str routeDistributionProtocol: description: Route Distribution Protocol for Control Plane Device. Allowed values @@ -125,8 +125,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddBorderDeviceInSDAFabric description: Complete reference of the AddBorderDeviceInSDAFabric API. @@ -195,7 +195,6 @@ deviceManagementIpAddress: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_border_device_info.py b/plugins/modules/sda_fabric_border_device_info.py index c4318cd732..ee09938074 100644 --- a/plugins/modules/sda_fabric_border_device_info.py +++ b/plugins/modules/sda_fabric_border_device_info.py @@ -25,8 +25,8 @@ - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetBorderDeviceDetailFromSDAFabric description: Complete reference of the GetBorderDeviceDetailFromSDAFabric API. @@ -55,7 +55,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_control_plane_device.py b/plugins/modules/sda_fabric_control_plane_device.py index ff3ecf449d..8e99ed6f0d 100644 --- a/plugins/modules/sda_fabric_control_plane_device.py +++ b/plugins/modules/sda_fabric_control_plane_device.py @@ -31,8 +31,8 @@ type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddControlPlaneDeviceInSDAFabric description: Complete reference of the AddControlPlaneDeviceInSDAFabric API. @@ -79,7 +79,6 @@ siteNameHierarchy: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_control_plane_device_info.py b/plugins/modules/sda_fabric_control_plane_device_info.py index 9267a70140..9250e75818 100644 --- a/plugins/modules/sda_fabric_control_plane_device_info.py +++ b/plugins/modules/sda_fabric_control_plane_device_info.py @@ -25,8 +25,8 @@ - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetControlPlaneDeviceFromSDAFabric description: Complete reference of the GetControlPlaneDeviceFromSDAFabric API. @@ -55,7 +55,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_devices.py b/plugins/modules/sda_fabric_devices.py new file mode 100644 index 0000000000..2a886860d6 --- /dev/null +++ b/plugins/modules/sda_fabric_devices.py @@ -0,0 +1,215 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices +short_description: Resource module for Sda Fabricdevices +description: +- Manage operations create, update and delete of the resource Sda Fabricdevices. +- Adds fabric devices based on user input. +- Deletes a fabric device based on id. +- Deletes fabric devices based on user input. +- Updates fabric devices based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + deviceRoles: + description: DeviceRoles query parameter. Device roles of the fabric device. + type: str + fabricId: + description: FabricId query parameter. ID of the fabric this device belongs to. + type: str + id: + description: Id path parameter. ID of the fabric device. + type: str + networkDeviceId: + description: NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + payload: + description: Sda Fabric Devices's payload. + elements: dict + suboptions: + borderDeviceSettings: + description: Sda Fabric Devices's borderDeviceSettings. + suboptions: + borderTypes: + description: List of the border types of the fabric device. Allowed values + are LAYER_2, LAYER_3. + elements: str + type: list + layer3Settings: + description: Sda Fabric Devices's layer3Settings. + suboptions: + borderPriority: + description: Border priority of the fabric border device. Allowed range + is 1-9. A lower value indicates higher priority. E.g., a priority + of 1 takes precedence over 5. Default priority would be set to 10. + type: int + importExternalRoutes: + description: Set this to import external routes from other routing protocols + (such as BGP) to the fabric control plane. (updating this field is + not allowed). + type: bool + isDefaultExit: + description: Set this to make the fabric border device the gateway of + last resort for this site. Any unknown traffic will be sent to this + fabric border device from edge nodes. (updating this field is not + allowed). + type: bool + localAutonomousSystemNumber: + description: BGP Local autonomous system number of the fabric border + device. Allowed range is 1 to 4294967295. (updating this field is + not allowed). + type: str + prependAutonomousSystemCount: + description: Prepend autonomous system count of the fabric border device. + Allowed range is 1 to 10. + type: int + type: dict + type: dict + deviceRoles: + description: List of the roles of the fabric device. Allowed values are CONTROL_PLANE_NODE, + EDGE_NODE, BORDER_NODE. (updating this field is not allowed). + elements: str + type: list + fabricId: + description: ID of the fabric site/zone of this fabric device. (updating this + field is not allowed). + type: str + id: + description: ID of the fabric device. (updating this field is not allowed). + type: str + networkDeviceId: + description: Network device ID of the fabric device. (updating this field is + not allowed). + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddFabricDevices + description: Complete reference of the AddFabricDevices API. + link: https://developer.cisco.com/docs/dna-center/#!add-fabric-devices +- name: Cisco DNA Center documentation for SDA DeleteAFabricDeviceById + description: Complete reference of the DeleteAFabricDeviceById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-a-fabric-device-by-id +- name: Cisco DNA Center documentation for SDA DeleteFabricDevices + description: Complete reference of the DeleteFabricDevices API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-devices +- name: Cisco DNA Center documentation for SDA UpdateFabricDevices + description: Complete reference of the UpdateFabricDevices API. + link: https://developer.cisco.com/docs/dna-center/#!update-fabric-devices +notes: + - SDK Method used are + sda.Sda.add_fabric_devices, + sda.Sda.delete_a_fabric_device_by_id, + sda.Sda.update_fabric_devices, + + - Paths used are + post /dna/intent/api/v1/sda/fabricDevices, + delete /dna/intent/api/v1/sda/fabricDevices, + delete /dna/intent/api/v1/sda/fabricDevices/{id}, + put /dna/intent/api/v1/sda/fabricDevices, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.sda_fabric_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - borderDeviceSettings: + borderTypes: + - string + layer3Settings: + borderPriority: 0 + importExternalRoutes: true + isDefaultExit: true + localAutonomousSystemNumber: string + prependAutonomousSystemCount: 0 + deviceRoles: + - string + fabricId: string + id: string + networkDeviceId: string + +- name: Delete all + cisco.dnac.sda_fabric_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + deviceRoles: string + fabricId: string + networkDeviceId: string + +- name: Create + cisco.dnac.sda_fabric_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - borderDeviceSettings: + borderTypes: + - string + layer3Settings: + borderPriority: 0 + importExternalRoutes: true + isDefaultExit: true + localAutonomousSystemNumber: string + prependAutonomousSystemCount: 0 + deviceRoles: + - string + fabricId: string + networkDeviceId: string + +- name: Delete by id + cisco.dnac.sda_fabric_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_count_info.py b/plugins/modules/sda_fabric_devices_count_info.py new file mode 100644 index 0000000000..c3aba25bbb --- /dev/null +++ b/plugins/modules/sda_fabric_devices_count_info.py @@ -0,0 +1,79 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_count_info +short_description: Information module for Sda Fabricdevices Count +description: +- Get all Sda Fabricdevices Count. +- Returns the count of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + deviceRoles: + description: + - DeviceRoles query parameter. Device roles of the fabric device. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevicesCount + description: Complete reference of the GetFabricDevicesCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices-count +notes: + - SDK Method used are + sda.Sda.get_fabric_devices_count, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices Count + cisco.dnac.sda_fabric_devices_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + deviceRoles: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_info.py b/plugins/modules/sda_fabric_devices_info.py new file mode 100644 index 0000000000..4c1ee703e0 --- /dev/null +++ b/plugins/modules/sda_fabric_devices_info.py @@ -0,0 +1,108 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_info +short_description: Information module for Sda Fabricdevices +description: +- Get all Sda Fabricdevices. +- Returns a list of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + deviceRoles: + description: + - DeviceRoles query parameter. Device roles of the fabric device. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: float + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevices + description: Complete reference of the GetFabricDevices API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices +notes: + - SDK Method used are + sda.Sda.get_fabric_devices, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices + cisco.dnac.sda_fabric_devices_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + deviceRoles: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "networkDeviceId": "string", + "fabricId": "string", + "deviceRoles": [ + "string" + ], + "borderDeviceSettings": { + "borderTypes": [ + "string" + ], + "layer3Settings": { + "localAutonomousSystemNumber": "string", + "isDefaultExit": true, + "importExternalRoutes": true, + "borderPriority": 0, + "prependAutonomousSystemCount": 0 + } + } + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs.py b/plugins/modules/sda_fabric_devices_layer2_handoffs.py new file mode 100644 index 0000000000..c968009933 --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs.py @@ -0,0 +1,134 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs +short_description: Resource module for Sda Fabricdevices Layer2handoffs +description: +- Manage operations create, update and delete of the resource Sda Fabricdevices Layer2handoffs. +- Adds layer 2 handoffs in fabric devices based on user input. +- Deletes a layer 2 handoff of a fabric device based on id. +- Deletes layer 2 handoffs of a fabric device based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + fabricId: + description: FabricId query parameter. ID of the fabric this device belongs to. + type: str + id: + description: Id path parameter. ID of the layer 2 handoff of a fabric device. + type: str + networkDeviceId: + description: NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + payload: + description: Sda Fabric Devices Layer2 Handoffs's payload. + elements: dict + suboptions: + externalVlanId: + description: External VLAN number into which the fabric must be extended. Allowed + VLAN range is 2-4094 except for reserved vlans (1, 1002-1005, 2046, 4094). + type: int + fabricId: + description: ID of the fabric this device belongs to. + type: str + interfaceName: + description: Interface name of the layer 2 handoff. E.g., GigabitEthernet1/0/4. + type: str + internalVlanId: + description: VLAN number associated with this fabric. Allowed VLAN range is + 2-4094 except for reserved vlans (1, 1002-1005, 2046, 4094). + type: int + networkDeviceId: + description: Network device ID of the fabric device. + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddFabricDevicesLayer2Handoffs + description: Complete reference of the AddFabricDevicesLayer2Handoffs API. + link: https://developer.cisco.com/docs/dna-center/#!add-fabric-devices-layer-2-handoffs +- name: Cisco DNA Center documentation for SDA DeleteFabricDeviceLayer2HandoffById + description: Complete reference of the DeleteFabricDeviceLayer2HandoffById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-device-layer-2-handoff-by-id +- name: Cisco DNA Center documentation for SDA DeleteFabricDeviceLayer2Handoffs + description: Complete reference of the DeleteFabricDeviceLayer2Handoffs API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-device-layer-2-handoffs +notes: + - SDK Method used are + sda.Sda.add_fabric_devices_layer2_handoffs, + sda.Sda.delete_fabric_device_layer2_handoff_by_id, + + - Paths used are + post /dna/intent/api/v1/sda/fabricDevices/layer2Handoffs, + delete /dna/intent/api/v1/sda/fabricDevices/layer2Handoffs, + delete /dna/intent/api/v1/sda/fabricDevices/layer2Handoffs/{id}, + +""" + +EXAMPLES = r""" +- name: Delete all + cisco.dnac.sda_fabric_devices_layer2_handoffs: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + fabricId: string + networkDeviceId: string + +- name: Create + cisco.dnac.sda_fabric_devices_layer2_handoffs: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - externalVlanId: 0 + fabricId: string + interfaceName: string + internalVlanId: 0 + networkDeviceId: string + +- name: Delete by id + cisco.dnac.sda_fabric_devices_layer2_handoffs: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_count_info.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_count_info.py new file mode 100644 index 0000000000..7af6f40eef --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_count_info.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_count_info +short_description: Information module for Sda Fabricdevices Layer2handoffs Count +description: +- Get all Sda Fabricdevices Layer2handoffs Count. +- Returns the count of layer 2 handoffs of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevicesLayer2HandoffsCount + description: Complete reference of the GetFabricDevicesLayer2HandoffsCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices-layer-2-handoffs-count +notes: + - SDK Method used are + sda.Sda.get_fabric_devices_layer2_handoffs_count, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices/layer2Handoffs/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices Layer2handoffs Count + cisco.dnac.sda_fabric_devices_layer2_handoffs_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_info.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_info.py new file mode 100644 index 0000000000..e1d25bc30c --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_info.py @@ -0,0 +1,91 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_info +short_description: Information module for Sda Fabricdevices Layer2handoffs +description: +- Get all Sda Fabricdevices Layer2handoffs. +- Returns a list of layer 2 handoffs of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: float + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevicesLayer2Handoffs + description: Complete reference of the GetFabricDevicesLayer2Handoffs API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices-layer-2-handoffs +notes: + - SDK Method used are + sda.Sda.get_fabric_devices_layer2_handoffs, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices/layer2Handoffs, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices Layer2handoffs + cisco.dnac.sda_fabric_devices_layer2_handoffs_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "networkDeviceId": "string", + "fabricId": "string", + "interfaceName": "string", + "internalVlanId": 0, + "externalVlanId": 0 + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits.py new file mode 100644 index 0000000000..bc8a7f9e4f --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits.py @@ -0,0 +1,209 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_ip_transits +short_description: Resource module for Sda Fabricdevices Layer2handoffs Iptransits +description: +- Manage operations create, update and delete of the resource Sda Fabricdevices Layer2handoffs Iptransits. +- Adds layer 3 handoffs with ip transit in fabric devices based on user input. +- Deletes a layer 3 handoff with ip transit of a fabric device by id. +- Deletes layer 3 handoffs with ip transit of a fabric device based on user input. +- Updates layer 3 handoffs with ip transit of fabric devices based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + fabricId: + description: FabricId query parameter. ID of the fabric this device belongs to. + type: str + id: + description: Id path parameter. ID of the layer 3 handoff with ip transit of a fabric + device to be deleted. + type: str + networkDeviceId: + description: NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + payload: + description: Sda Fabric Devices Layer2 Handoffs Ip Transits's payload. + elements: dict + suboptions: + externalConnectivityIpPoolName: + description: External connectivity ip pool will be used by Catalyst Center to + allocate IP address for the connection between the border node and peer. + type: str + fabricId: + description: ID of the fabric this device belongs to. + type: str + interfaceName: + description: Interface name of the layer 3 handoff ip transit. + type: str + localIpAddress: + description: Local ipv4 address for the selected virtual network. Enter the + IP addresses and subnet mask in the CIDR notation (IP address/prefix-length). + Not applicable if you have already provided an external connectivity ip pool + name. + type: str + localIpv6Address: + description: Local ipv6 address for the selected virtual network. Enter the + IP addresses and subnet mask in the CIDR notation (IP address/prefix-length). + Not applicable if you have already provided an external connectivity ip pool + name. + type: str + networkDeviceId: + description: Network device ID of the fabric device. + type: str + remoteIpAddress: + description: Remote ipv4 address for the selected virtual network. Enter the + IP addresses and subnet mask in the CIDR notation (IP address/prefix-length). + Not applicable if you have already provided an external connectivity ip pool + name. + type: str + remoteIpv6Address: + description: Remote ipv6 address for the selected virtual network. Enter the + IP addresses and subnet mask in the CIDR notation (IP address/prefix-length). + Not applicable if you have already provided an external connectivity ip pool + name. + type: str + tcpMssAdjustment: + description: TCP maximum segment size (mss) value for the layer 3 handoff. Allowed + range is 500-1440. TCP MSS Adjustment value is applicable for the TCP sessions + over both IPv4 and IPv6. + type: int + transitNetworkId: + description: ID of the transit network of the layer 3 handoff ip transit. + type: str + virtualNetworkName: + description: Name of the virtual network associated with this fabric site. + type: str + vlanId: + description: VLAN number for the Switch Virtual Interface (SVI) used to establish + BGP peering with the external domain for the virtual network. Allowed VLAN + range is 2-4094 except for reserved vlans (1, 1002-1005, 2046, 4094). + type: int + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddFabricDevicesLayer3HandoffsWithIpTransit + description: Complete reference of the AddFabricDevicesLayer3HandoffsWithIpTransit API. + link: https://developer.cisco.com/docs/dna-center/#!add-fabric-devices-layer-3-handoffs-with-ip-transit +- name: Cisco DNA Center documentation for SDA DeleteFabricDeviceLayer3HandoffWithIpTransitById + description: Complete reference of the DeleteFabricDeviceLayer3HandoffWithIpTransitById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-device-layer-3-handoff-with-ip-transit-by-id +- name: Cisco DNA Center documentation for SDA DeleteFabricDeviceLayer3HandoffsWithIpTransit + description: Complete reference of the DeleteFabricDeviceLayer3HandoffsWithIpTransit API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-device-layer-3-handoffs-with-ip-transit +- name: Cisco DNA Center documentation for SDA UpdateFabricDevicesLayer3HandoffsWithIpTransit + description: Complete reference of the UpdateFabricDevicesLayer3HandoffsWithIpTransit API. + link: https://developer.cisco.com/docs/dna-center/#!update-fabric-devices-layer-3-handoffs-with-ip-transit +notes: + - SDK Method used are + sda.Sda.add_fabric_devices_layer3_handoffs_with_ip_transit, + sda.Sda.delete_fabric_device_layer3_handoff_with_ip_transit_by_id, + sda.Sda.update_fabric_devices_layer3_handoffs_with_ip_transit, + + - Paths used are + post /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/ipTransits, + delete /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/ipTransits, + delete /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/ipTransits/{id}, + put /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/ipTransits, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.sda_fabric_devices_layer2_handoffs_ip_transits: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - externalConnectivityIpPoolName: string + fabricId: string + interfaceName: string + localIpAddress: string + localIpv6Address: string + networkDeviceId: string + remoteIpAddress: string + remoteIpv6Address: string + tcpMssAdjustment: 0 + transitNetworkId: string + virtualNetworkName: string + vlanId: 0 + +- name: Update all + cisco.dnac.sda_fabric_devices_layer2_handoffs_ip_transits: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - externalConnectivityIpPoolName: string + fabricId: string + id: string + interfaceName: string + localIpAddress: string + localIpv6Address: string + networkDeviceId: string + remoteIpAddress: string + remoteIpv6Address: string + tcpMssAdjustment: 0 + transitNetworkId: string + virtualNetworkName: string + vlanId: 0 + +- name: Delete all + cisco.dnac.sda_fabric_devices_layer2_handoffs_ip_transits: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + fabricId: string + networkDeviceId: string + +- name: Delete by id + cisco.dnac.sda_fabric_devices_layer2_handoffs_ip_transits: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits_count_info.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits_count_info.py new file mode 100644 index 0000000000..92831f8f1b --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits_count_info.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_ip_transits_count_info +short_description: Information module for Sda Fabricdevices Layer2handoffs Iptransits Count +description: +- Get all Sda Fabricdevices Layer2handoffs Iptransits Count. +- Returns the count of layer 3 handoffs with ip transit of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevicesLayer3HandoffsWithIpTransitCount + description: Complete reference of the GetFabricDevicesLayer3HandoffsWithIpTransitCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices-layer-3-handoffs-with-ip-transit-count +notes: + - SDK Method used are + sda.Sda.get_fabric_devices_layer3_handoffs_with_ip_transit_count, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/ipTransits/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices Layer2handoffs Iptransits Count + cisco.dnac.sda_fabric_devices_layer2_handoffs_ip_transits_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits_info.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits_info.py new file mode 100644 index 0000000000..0adfdebe20 --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_ip_transits_info.py @@ -0,0 +1,98 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_ip_transits_info +short_description: Information module for Sda Fabricdevices Layer2handoffs Iptransits +description: +- Get all Sda Fabricdevices Layer2handoffs Iptransits. +- Returns a list of layer 3 handoffs with ip transit of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: float + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevicesLayer3HandoffsWithIpTransit + description: Complete reference of the GetFabricDevicesLayer3HandoffsWithIpTransit API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices-layer-3-handoffs-with-ip-transit +notes: + - SDK Method used are + sda.Sda.get_fabric_devices_layer3_handoffs_with_ip_transit, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/ipTransits, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices Layer2handoffs Iptransits + cisco.dnac.sda_fabric_devices_layer2_handoffs_ip_transits_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "networkDeviceId": "string", + "fabricId": "string", + "transitNetworkId": "string", + "interfaceName": "string", + "externalConnectivityIpPoolName": "string", + "virtualNetworkName": "string", + "vlanId": 0, + "tcpMssAdjustment": 0, + "localIpAddress": "string", + "remoteIpAddress": "string", + "localIpv6Address": "string", + "remoteIpv6Address": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits.py new file mode 100644 index 0000000000..a0097961ed --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits.py @@ -0,0 +1,157 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_sda_transits +short_description: Resource module for Sda Fabricdevices Layer2handoffs Sdatransits +description: +- Manage operations create, update and delete of the resource Sda Fabricdevices Layer2handoffs Sdatransits. +- Adds layer 3 handoffs with sda transit in fabric devices based on user input. +- Deletes layer 3 handoffs with sda transit of a fabric device based on user input. +- Updates layer 3 handoffs with sda transit of fabric devices based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + fabricId: + description: FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + payload: + description: Sda Fabric Devices Layer2 Handoffs Sda Transits's payload. + elements: dict + suboptions: + affinityIdDecider: + description: Affinity id decider value of the border node. When the affinity + id prime value is the same on multiple devices, the affinity id decider value + is used as a tiebreaker. Allowed range is 0-2147483647. The lower the relative + value of affinity id decider, the higher the preference for a destination + border node. + type: int + affinityIdPrime: + description: Affinity id prime value of the border node. It supersedes the border + priority to determine border node preference. Allowed range is 0-2147483647. + The lower the relative value of affinity id prime, the higher the preference + for a destination border node. + type: int + connectedToInternet: + description: Set this true to allow associated site to provide internet access + to other sites through sd-access. + type: bool + fabricId: + description: ID of the fabric this device belongs to. (updating this field is + not allowed). + type: str + isMulticastOverTransitEnabled: + description: Set this true to configure native multicast over multiple sites + that are connected to an sd-access transit. + type: bool + networkDeviceId: + description: Network device ID of the fabric device. (updating this field is + not allowed). + type: str + transitNetworkId: + description: ID of the transit network of the layer 3 handoff sda transit. (updating + this field is not allowed). + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddFabricDevicesLayer3HandoffsWithSdaTransit + description: Complete reference of the AddFabricDevicesLayer3HandoffsWithSdaTransit API. + link: https://developer.cisco.com/docs/dna-center/#!add-fabric-devices-layer-3-handoffs-with-sda-transit +- name: Cisco DNA Center documentation for SDA DeleteFabricDeviceLayer3HandoffsWithSdaTransit + description: Complete reference of the DeleteFabricDeviceLayer3HandoffsWithSdaTransit API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-device-layer-3-handoffs-with-sda-transit +- name: Cisco DNA Center documentation for SDA UpdateFabricDevicesLayer3HandoffsWithSdaTransit + description: Complete reference of the UpdateFabricDevicesLayer3HandoffsWithSdaTransit API. + link: https://developer.cisco.com/docs/dna-center/#!update-fabric-devices-layer-3-handoffs-with-sda-transit +notes: + - SDK Method used are + sda.Sda.add_fabric_devices_layer3_handoffs_with_sda_transit, + sda.Sda.delete_fabric_device_layer3_handoffs_with_sda_transit, + sda.Sda.update_fabric_devices_layer3_handoffs_with_sda_transit, + + - Paths used are + post /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/sdaTransits, + delete /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/sdaTransits, + put /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/sdaTransits, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.sda_fabric_devices_layer2_handoffs_sda_transits: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - affinityIdDecider: 0 + affinityIdPrime: 0 + connectedToInternet: true + fabricId: string + isMulticastOverTransitEnabled: true + networkDeviceId: string + transitNetworkId: string + +- name: Delete all + cisco.dnac.sda_fabric_devices_layer2_handoffs_sda_transits: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + fabricId: string + networkDeviceId: string + +- name: Create + cisco.dnac.sda_fabric_devices_layer2_handoffs_sda_transits: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - affinityIdDecider: 0 + affinityIdPrime: 0 + connectedToInternet: true + fabricId: string + isMulticastOverTransitEnabled: true + networkDeviceId: string + transitNetworkId: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits_count_info.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits_count_info.py new file mode 100644 index 0000000000..6b6d210249 --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits_count_info.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_sda_transits_count_info +short_description: Information module for Sda Fabricdevices Layer2handoffs Sdatransits Count +description: +- Get all Sda Fabricdevices Layer2handoffs Sdatransits Count. +- Returns the count of layer 3 handoffs with sda transit of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevicesLayer3HandoffsWithSdaTransitCount + description: Complete reference of the GetFabricDevicesLayer3HandoffsWithSdaTransitCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices-layer-3-handoffs-with-sda-transit-count +notes: + - SDK Method used are + sda.Sda.get_fabric_devices_layer3_handoffs_with_sda_transit_count, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/sdaTransits/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices Layer2handoffs Sdatransits Count + cisco.dnac.sda_fabric_devices_layer2_handoffs_sda_transits_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits_info.py b/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits_info.py new file mode 100644 index 0000000000..36b4249ff1 --- /dev/null +++ b/plugins/modules/sda_fabric_devices_layer2_handoffs_sda_transits_info.py @@ -0,0 +1,92 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_devices_layer2_handoffs_sda_transits_info +short_description: Information module for Sda Fabricdevices Layer2handoffs Sdatransits +description: +- Get all Sda Fabricdevices Layer2handoffs Sdatransits. +- Returns a list of layer 3 handoffs with sda transit of fabric devices that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the fabric device. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: float + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricDevicesLayer3HandoffsWithSdaTransit + description: Complete reference of the GetFabricDevicesLayer3HandoffsWithSdaTransit API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-devices-layer-3-handoffs-with-sda-transit +notes: + - SDK Method used are + sda.Sda.get_fabric_devices_layer3_handoffs_with_sda_transit, + + - Paths used are + get /dna/intent/api/v1/sda/fabricDevices/layer3Handoffs/sdaTransits, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricdevices Layer2handoffs Sdatransits + cisco.dnac.sda_fabric_devices_layer2_handoffs_sda_transits_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "networkDeviceId": "string", + "fabricId": "string", + "transitNetworkId": "string", + "affinityIdPrime": 0, + "affinityIdDecider": 0, + "connectedToInternet": true, + "isMulticastOverTransitEnabled": true + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_edge_device.py b/plugins/modules/sda_fabric_edge_device.py index 9bcde0422f..375232dc39 100644 --- a/plugins/modules/sda_fabric_edge_device.py +++ b/plugins/modules/sda_fabric_edge_device.py @@ -26,8 +26,8 @@ type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddEdgeDeviceInSDAFabric description: Complete reference of the AddEdgeDeviceInSDAFabric API. @@ -73,7 +73,6 @@ deviceManagementIpAddress: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_edge_device_info.py b/plugins/modules/sda_fabric_edge_device_info.py index a4f6eecc28..e91cca762f 100644 --- a/plugins/modules/sda_fabric_edge_device_info.py +++ b/plugins/modules/sda_fabric_edge_device_info.py @@ -24,8 +24,8 @@ - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetEdgeDeviceFromSDAFabric description: Complete reference of the GetEdgeDeviceFromSDAFabric API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_info.py b/plugins/modules/sda_fabric_info.py index c44290025c..99d7e11271 100644 --- a/plugins/modules/sda_fabric_info.py +++ b/plugins/modules/sda_fabric_info.py @@ -24,7 +24,7 @@ - FabricName query parameter. Fabric Name. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/sda_fabric_site.py b/plugins/modules/sda_fabric_site.py index eed71ad48e..6c8dc5823b 100644 --- a/plugins/modules/sda_fabric_site.py +++ b/plugins/modules/sda_fabric_site.py @@ -31,8 +31,8 @@ description: SiteNameHierarchy query parameter. Site Name Hierarchy. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddSiteInSDAFabric description: Complete reference of the AddSiteInSDAFabric API. @@ -79,7 +79,6 @@ siteNameHierarchy: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_site_info.py b/plugins/modules/sda_fabric_site_info.py index bd2e8c1772..be6e890e33 100644 --- a/plugins/modules/sda_fabric_site_info.py +++ b/plugins/modules/sda_fabric_site_info.py @@ -24,8 +24,8 @@ - SiteNameHierarchy query parameter. Site Name Hierarchy. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetSiteFromSDAFabric description: Complete reference of the GetSiteFromSDAFabric API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_fabric_sites.py b/plugins/modules/sda_fabric_sites.py new file mode 100644 index 0000000000..2a20b982b2 --- /dev/null +++ b/plugins/modules/sda_fabric_sites.py @@ -0,0 +1,123 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_sites +short_description: Resource module for Sda Fabricsites +description: +- Manage operations create, update and delete of the resource Sda Fabricsites. +- Adds a fabric site based on user input. +- Deletes a fabric site based on id. +- Updates a fabric site based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. ID of the fabric site to be deleted. + type: str + payload: + description: Sda Fabric Sites's payload. + elements: dict + suboptions: + authenticationProfileName: + description: Authentication profile used for this fabric. + type: str + isPubSubEnabled: + description: Specifies whether this fabric site will use pub/sub for control + nodes. + type: bool + siteId: + description: ID of the network hierarchy. + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddFabricSite + description: Complete reference of the AddFabricSite API. + link: https://developer.cisco.com/docs/dna-center/#!add-fabric-site +- name: Cisco DNA Center documentation for SDA DeleteFabricSiteById + description: Complete reference of the DeleteFabricSiteById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-site-by-id +- name: Cisco DNA Center documentation for SDA UpdateFabricSite + description: Complete reference of the UpdateFabricSite API. + link: https://developer.cisco.com/docs/dna-center/#!update-fabric-site +notes: + - SDK Method used are + sda.Sda.add_fabric_site, + sda.Sda.delete_fabric_site_by_id, + sda.Sda.update_fabric_site, + + - Paths used are + post /dna/intent/api/v1/sda/fabricSites, + delete /dna/intent/api/v1/sda/fabricSites/{id}, + put /dna/intent/api/v1/sda/fabricSites, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.sda_fabric_sites: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - authenticationProfileName: string + isPubSubEnabled: true + siteId: string + +- name: Update all + cisco.dnac.sda_fabric_sites: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - authenticationProfileName: string + id: string + isPubSubEnabled: true + siteId: string + +- name: Delete by id + cisco.dnac.sda_fabric_sites: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_sites_count_info.py b/plugins/modules/sda_fabric_sites_count_info.py new file mode 100644 index 0000000000..9bc70272ac --- /dev/null +++ b/plugins/modules/sda_fabric_sites_count_info.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_sites_count_info +short_description: Information module for Sda Fabricsites Count +description: +- Get all Sda Fabricsites Count. +- Returns the count of fabric sites that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricSiteCount + description: Complete reference of the GetFabricSiteCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-site-count +notes: + - SDK Method used are + sda.Sda.get_fabric_site_count, + + - Paths used are + get /dna/intent/api/v1/sda/fabricSites/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricsites Count + cisco.dnac.sda_fabric_sites_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_sites_info.py b/plugins/modules/sda_fabric_sites_info.py new file mode 100644 index 0000000000..6e10d0198f --- /dev/null +++ b/plugins/modules/sda_fabric_sites_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_sites_info +short_description: Information module for Sda Fabricsites +description: +- Get all Sda Fabricsites. +- Returns a list of fabric sites that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + id: + description: + - Id query parameter. ID of the fabric site to search for in the database. + type: str + siteId: + description: + - SiteId query parameter. Get the fabric site associated with this network hierarchy. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: int + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: int +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricSites + description: Complete reference of the GetFabricSites API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-sites +notes: + - SDK Method used are + sda.Sda.get_fabric_sites, + + - Paths used are + get /dna/intent/api/v1/sda/fabricSites, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabricsites + cisco.dnac.sda_fabric_sites_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + id: string + siteId: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "siteId": "string", + "authenticationProfileName": "string", + "isPubSubEnabled": true + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_zones.py b/plugins/modules/sda_fabric_zones.py new file mode 100644 index 0000000000..2f5ca3bfcb --- /dev/null +++ b/plugins/modules/sda_fabric_zones.py @@ -0,0 +1,120 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_zones +short_description: Resource module for Sda Fabriczones +description: +- Manage operations create, update and delete of the resource Sda Fabriczones. +- Adds a fabric zone based on user input. +- Deletes a fabric zone based on id. +- Updates a fabric zone based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. ID of the fabric zone to be deleted. + type: str + payload: + description: Sda Fabric Zones's payload. + elements: dict + suboptions: + authenticationProfileName: + description: Authentication profile used for this fabric. + type: str + id: + description: ID of the fabric zone (updating this field is not allowed). + type: str + siteId: + description: ID of the network hierarchy (updating this field is not allowed). + type: str + type: list +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddFabricZone + description: Complete reference of the AddFabricZone API. + link: https://developer.cisco.com/docs/dna-center/#!add-fabric-zone +- name: Cisco DNA Center documentation for SDA DeleteFabricZoneById + description: Complete reference of the DeleteFabricZoneById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-fabric-zone-by-id +- name: Cisco DNA Center documentation for SDA UpdateFabricZone + description: Complete reference of the UpdateFabricZone API. + link: https://developer.cisco.com/docs/dna-center/#!update-fabric-zone +notes: + - SDK Method used are + sda.Sda.add_fabric_zone, + sda.Sda.delete_fabric_zone_by_id, + sda.Sda.update_fabric_zone, + + - Paths used are + post /dna/intent/api/v1/sda/fabricZones, + delete /dna/intent/api/v1/sda/fabricZones/{id}, + put /dna/intent/api/v1/sda/fabricZones, + +""" + +EXAMPLES = r""" +- name: Update all + cisco.dnac.sda_fabric_zones: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - authenticationProfileName: string + id: string + siteId: string + +- name: Create + cisco.dnac.sda_fabric_zones: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - authenticationProfileName: string + siteId: string + +- name: Delete by id + cisco.dnac.sda_fabric_zones: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_zones_count_info.py b/plugins/modules/sda_fabric_zones_count_info.py new file mode 100644 index 0000000000..b925a188de --- /dev/null +++ b/plugins/modules/sda_fabric_zones_count_info.py @@ -0,0 +1,64 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_zones_count_info +short_description: Information module for Sda Fabriczones Count +description: +- Get all Sda Fabriczones Count. +- Returns the count of fabric zones that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricZoneCount + description: Complete reference of the GetFabricZoneCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-zone-count +notes: + - SDK Method used are + sda.Sda.get_fabric_zone_count, + + - Paths used are + get /dna/intent/api/v1/sda/fabricZones/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabriczones Count + cisco.dnac.sda_fabric_zones_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_fabric_zones_info.py b/plugins/modules/sda_fabric_zones_info.py new file mode 100644 index 0000000000..fed42f535a --- /dev/null +++ b/plugins/modules/sda_fabric_zones_info.py @@ -0,0 +1,88 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_fabric_zones_info +short_description: Information module for Sda Fabriczones +description: +- Get all Sda Fabriczones. +- Returns a list of fabric zones that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + id: + description: + - Id query parameter. ID of the fabric zone to search for in the database. + type: str + siteId: + description: + - SiteId query parameter. Get the fabric zone associated with this network hierarchy. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: int + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: int +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetFabricZones + description: Complete reference of the GetFabricZones API. + link: https://developer.cisco.com/docs/dna-center/#!get-fabric-zones +notes: + - SDK Method used are + sda.Sda.get_fabric_zones, + + - Paths used are + get /dna/intent/api/v1/sda/fabricZones, + +""" + +EXAMPLES = r""" +- name: Get all Sda Fabriczones + cisco.dnac.sda_fabric_zones_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + id: string + siteId: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "siteId": "string", + "authenticationProfileName": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_multicast.py b/plugins/modules/sda_multicast.py index 6e1045c5d0..10d99b81d1 100644 --- a/plugins/modules/sda_multicast.py +++ b/plugins/modules/sda_multicast.py @@ -56,8 +56,8 @@ description: Full path of sda Fabric Site. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddMulticastInSDAFabric description: Complete reference of the AddMulticastInSDAFabric API. @@ -113,7 +113,6 @@ siteNameHierarchy: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_multicast_info.py b/plugins/modules/sda_multicast_info.py index 2f4ae1218b..ac7fefcaa6 100644 --- a/plugins/modules/sda_multicast_info.py +++ b/plugins/modules/sda_multicast_info.py @@ -24,8 +24,8 @@ - SiteNameHierarchy query parameter. Fabric site name hierarchy. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetMulticastDetailsFromSDAFabric description: Complete reference of the GetMulticastDetailsFromSDAFabric API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_port_assignment_for_access_point.py b/plugins/modules/sda_port_assignment_for_access_point.py index c8280407db..88ad55d724 100644 --- a/plugins/modules/sda_port_assignment_for_access_point.py +++ b/plugins/modules/sda_port_assignment_for_access_point.py @@ -41,8 +41,8 @@ type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddPortAssignmentForAccessPointInSDAFabric description: Complete reference of the AddPortAssignmentForAccessPointInSDAFabric API. @@ -93,7 +93,6 @@ interfaceName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_port_assignment_for_access_point_info.py b/plugins/modules/sda_port_assignment_for_access_point_info.py index 3cdb7cd3af..8cc99924d0 100644 --- a/plugins/modules/sda_port_assignment_for_access_point_info.py +++ b/plugins/modules/sda_port_assignment_for_access_point_info.py @@ -29,8 +29,8 @@ - InterfaceName query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetPortAssignmentForAccessPointInSDAFabric description: Complete reference of the GetPortAssignmentForAccessPointInSDAFabric API. @@ -60,7 +60,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_port_assignment_for_user_device.py b/plugins/modules/sda_port_assignment_for_user_device.py index 58664b8e2e..207dc6130e 100644 --- a/plugins/modules/sda_port_assignment_for_user_device.py +++ b/plugins/modules/sda_port_assignment_for_user_device.py @@ -54,8 +54,8 @@ type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddPortAssignmentForUserDeviceInSDAFabric description: Complete reference of the AddPortAssignmentForUserDeviceInSDAFabric API. @@ -110,7 +110,6 @@ voiceIpAddressPoolName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_port_assignment_for_user_device_info.py b/plugins/modules/sda_port_assignment_for_user_device_info.py index 2fdbee0464..ad5b7cd6d1 100644 --- a/plugins/modules/sda_port_assignment_for_user_device_info.py +++ b/plugins/modules/sda_port_assignment_for_user_device_info.py @@ -28,8 +28,8 @@ - InterfaceName query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetPortAssignmentForUserDeviceInSDAFabric description: Complete reference of the GetPortAssignmentForUserDeviceInSDAFabric API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_port_assignments.py b/plugins/modules/sda_port_assignments.py new file mode 100644 index 0000000000..ccaded080d --- /dev/null +++ b/plugins/modules/sda_port_assignments.py @@ -0,0 +1,188 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_port_assignments +short_description: Resource module for Sda Portassignments +description: +- Manage operations create, update and delete of the resource Sda Portassignments. +- Adds port assignments based on user input. +- Deletes a port assignment based on id. +- Deletes port assignments based on user input. +- Updates port assignments based on user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + dataVlanName: + description: DataVlanName query parameter. Data VLAN name of the port assignment. + type: str + fabricId: + description: FabricId query parameter. ID of the fabric this device belongs to. + type: str + id: + description: Id path parameter. ID of the port assignment. + type: str + interfaceName: + description: InterfaceName query parameter. Interface name of the port assignment. + type: str + networkDeviceId: + description: NetworkDeviceId query parameter. Network device ID of the port assignment. + type: str + payload: + description: Sda Port Assignments's payload. + elements: dict + suboptions: + authenticateTemplateName: + description: Authenticate template name of the port assignment. + type: str + connectedDeviceType: + description: Connected device type of the port assignment. + type: str + dataVlanName: + description: Data VLAN name of the port assignment. + type: str + fabricId: + description: ID of the fabric this device belongs to. + type: str + interfaceDescription: + description: Interface description of the port assignment. + type: str + interfaceName: + description: Interface name of the port assignment. + type: str + networkDeviceId: + description: Network device ID of the port assignment. + type: str + scalableGroupName: + description: Scalable group name of the port assignment. + type: str + voiceVlanName: + description: Voice VLAN name of the port assignment. + type: str + type: list + voiceVlanName: + description: VoiceVlanName query parameter. Voice VLAN name of the port assignment. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA AddPortAssignments + description: Complete reference of the AddPortAssignments API. + link: https://developer.cisco.com/docs/dna-center/#!add-port-assignments +- name: Cisco DNA Center documentation for SDA DeletePortAssignmentById + description: Complete reference of the DeletePortAssignmentById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-port-assignment-by-id +- name: Cisco DNA Center documentation for SDA DeletePortAssignments + description: Complete reference of the DeletePortAssignments API. + link: https://developer.cisco.com/docs/dna-center/#!delete-port-assignments +- name: Cisco DNA Center documentation for SDA UpdatePortAssignments + description: Complete reference of the UpdatePortAssignments API. + link: https://developer.cisco.com/docs/dna-center/#!update-port-assignments +notes: + - SDK Method used are + sda.Sda.add_port_assignments, + sda.Sda.delete_port_assignment_by_id, + sda.Sda.update_port_assignments, + + - Paths used are + post /dna/intent/api/v1/sda/portAssignments, + delete /dna/intent/api/v1/sda/portAssignments, + delete /dna/intent/api/v1/sda/portAssignments/{id}, + put /dna/intent/api/v1/sda/portAssignments, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.sda_port_assignments: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - authenticateTemplateName: string + connectedDeviceType: string + dataVlanName: string + fabricId: string + interfaceDescription: string + interfaceName: string + networkDeviceId: string + scalableGroupName: string + voiceVlanName: string + +- name: Update all + cisco.dnac.sda_port_assignments: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - authenticateTemplateName: string + connectedDeviceType: string + dataVlanName: string + fabricId: string + id: string + interfaceDescription: string + interfaceName: string + networkDeviceId: string + scalableGroupName: string + voiceVlanName: string + +- name: Delete all + cisco.dnac.sda_port_assignments: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + dataVlanName: string + fabricId: string + interfaceName: string + networkDeviceId: string + voiceVlanName: string + +- name: Delete by id + cisco.dnac.sda_port_assignments: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_port_assignments_count_info.py b/plugins/modules/sda_port_assignments_count_info.py new file mode 100644 index 0000000000..6c81f99f6d --- /dev/null +++ b/plugins/modules/sda_port_assignments_count_info.py @@ -0,0 +1,89 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_port_assignments_count_info +short_description: Information module for Sda Portassignments Count +description: +- Get all Sda Portassignments Count. +- Returns the count of port assignments that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the port assignment. + type: str + interfaceName: + description: + - InterfaceName query parameter. Interface name of the port assignment. + type: str + dataVlanName: + description: + - DataVlanName query parameter. Data VLAN name of the port assignment. + type: str + voiceVlanName: + description: + - VoiceVlanName query parameter. Voice VLAN name of the port assignment. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetPortAssignmentCount + description: Complete reference of the GetPortAssignmentCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-port-assignment-count +notes: + - SDK Method used are + sda.Sda.get_port_assignment_count, + + - Paths used are + get /dna/intent/api/v1/sda/portAssignments/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Portassignments Count + cisco.dnac.sda_port_assignments_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + interfaceName: string + dataVlanName: string + voiceVlanName: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_port_assignments_info.py b/plugins/modules/sda_port_assignments_info.py new file mode 100644 index 0000000000..817d48f436 --- /dev/null +++ b/plugins/modules/sda_port_assignments_info.py @@ -0,0 +1,110 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_port_assignments_info +short_description: Information module for Sda Portassignments +description: +- Get all Sda Portassignments. +- Returns a list of port assignments that match the provided query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + fabricId: + description: + - FabricId query parameter. ID of the fabric this device belongs to. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. Network device ID of the port assignment. + type: str + interfaceName: + description: + - InterfaceName query parameter. Interface Name of the port assignment. + type: str + dataVlanName: + description: + - DataVlanName query parameter. Data VLAN name of the port assignment. + type: str + voiceVlanName: + description: + - VoiceVlanName query parameter. Voice VLAN name of the port assignment. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: float + limit: + description: + - Limit query parameter. Maximum number of records to return. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetPortAssignments + description: Complete reference of the GetPortAssignments API. + link: https://developer.cisco.com/docs/dna-center/#!get-port-assignments +notes: + - SDK Method used are + sda.Sda.get_port_assignments, + + - Paths used are + get /dna/intent/api/v1/sda/portAssignments, + +""" + +EXAMPLES = r""" +- name: Get all Sda Portassignments + cisco.dnac.sda_port_assignments_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + fabricId: string + networkDeviceId: string + interfaceName: string + dataVlanName: string + voiceVlanName: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "fabricId": "string", + "networkDeviceId": "string", + "interfaceName": "string", + "connectedDeviceType": "string", + "dataVlanName": "string", + "voiceVlanName": "string", + "authenticateTemplateName": "string", + "scalableGroupName": "string", + "interfaceDescription": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_provision_device.py b/plugins/modules/sda_provision_device.py index 5940634b8f..ac7b8ffe70 100644 --- a/plugins/modules/sda_provision_device.py +++ b/plugins/modules/sda_provision_device.py @@ -26,8 +26,8 @@ description: SiteNameHierarchy of the provisioned device. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA ProvisionWiredDevice description: Complete reference of the ProvisionWiredDevice API. @@ -91,7 +91,6 @@ siteNameHierarchy: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_provision_device_info.py b/plugins/modules/sda_provision_device_info.py index ae78549ec7..09a219a39f 100644 --- a/plugins/modules/sda_provision_device_info.py +++ b/plugins/modules/sda_provision_device_info.py @@ -24,8 +24,8 @@ - DeviceManagementIpAddress query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetProvisionedWiredDevice description: Complete reference of the GetProvisionedWiredDevice API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_provision_devices.py b/plugins/modules/sda_provision_devices.py new file mode 100644 index 0000000000..69dff062ba --- /dev/null +++ b/plugins/modules/sda_provision_devices.py @@ -0,0 +1,141 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_provision_devices +short_description: Resource module for Sda Provisiondevices +description: +- Manage operations create, update and delete of the resource Sda Provisiondevices. +- Provisions network devices to respective Sites based on user input. +- Delete provisioned devices based on query parameters. +- Deletes provisioned device based on Id. +- Re-provisions network devices to the site based on the user input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + id: + description: Id path parameter. ID of provisioned device. + type: str + networkDeviceId: + description: NetworkDeviceId query parameter. ID of the network device. + type: str + payload: + description: Sda Provision Devices's payload. + elements: dict + suboptions: + networkDeviceId: + description: ID of network device to be provisioned. + type: str + siteId: + description: ID of the site this network device needs to be provisioned. + type: str + type: list + siteId: + description: SiteId query parameter. ID of the site hierarchy. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA ProvisionDevices + description: Complete reference of the ProvisionDevices API. + link: https://developer.cisco.com/docs/dna-center/#!provision-devices +- name: Cisco DNA Center documentation for SDA DeleteProvisionedDeviceById + description: Complete reference of the DeleteProvisionedDeviceById API. + link: https://developer.cisco.com/docs/dna-center/#!delete-provisioned-device-by-id +- name: Cisco DNA Center documentation for SDA DeleteProvisionedDevices + description: Complete reference of the DeleteProvisionedDevices API. + link: https://developer.cisco.com/docs/dna-center/#!delete-provisioned-devices +- name: Cisco DNA Center documentation for SDA ReProvisionDevices + description: Complete reference of the ReProvisionDevices API. + link: https://developer.cisco.com/docs/dna-center/#!re-provision-devices +notes: + - SDK Method used are + sda.Sda.delete_provisioned_device_by_id, + sda.Sda.provision_devices, + sda.Sda.re_provision_devices, + + - Paths used are + post /dna/intent/api/v1/sda/provisionDevices, + delete /dna/intent/api/v1/sda/provisionDevices, + delete /dna/intent/api/v1/sda/provisionDevices/{id}, + put /dna/intent/api/v1/sda/provisionDevices, + +""" + +EXAMPLES = r""" +- name: Delete all + cisco.dnac.sda_provision_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + networkDeviceId: string + siteId: string + +- name: Create + cisco.dnac.sda_provision_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - networkDeviceId: string + siteId: string + +- name: Update all + cisco.dnac.sda_provision_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + payload: + - id: string + networkDeviceId: string + siteId: string + +- name: Delete by id + cisco.dnac.sda_provision_devices: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + id: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_provision_devices_count_info.py b/plugins/modules/sda_provision_devices_count_info.py new file mode 100644 index 0000000000..b733a2ad75 --- /dev/null +++ b/plugins/modules/sda_provision_devices_count_info.py @@ -0,0 +1,69 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_provision_devices_count_info +short_description: Information module for Sda Provisiondevices Count +description: +- Get all Sda Provisiondevices Count. +- Returns the count of provisioned devices based on query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + siteId: + description: + - SiteId query parameter. ID of the site hierarchy. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetProvisionedDevicesCount + description: Complete reference of the GetProvisionedDevicesCount API. + link: https://developer.cisco.com/docs/dna-center/#!get-provisioned-devices-count +notes: + - SDK Method used are + sda.Sda.get_provisioned_devices_count, + + - Paths used are + get /dna/intent/api/v1/sda/provisionDevices/count, + +""" + +EXAMPLES = r""" +- name: Get all Sda Provisiondevices Count + cisco.dnac.sda_provision_devices_count_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + siteId: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "count": 0 + }, + "version": "string" + } +""" diff --git a/plugins/modules/sda_provision_devices_info.py b/plugins/modules/sda_provision_devices_info.py new file mode 100644 index 0000000000..464cf3ec1e --- /dev/null +++ b/plugins/modules/sda_provision_devices_info.py @@ -0,0 +1,93 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_provision_devices_info +short_description: Information module for Sda Provisiondevices +description: +- Get all Sda Provisiondevices. +- Returns the list of provisioned devices based on query parameters. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + id: + description: + - Id query parameter. ID of the provisioned device. + type: str + networkDeviceId: + description: + - NetworkDeviceId query parameter. ID of the network device. + type: str + siteId: + description: + - SiteId query parameter. ID of the site hierarchy. + type: str + offset: + description: + - Offset query parameter. Starting record for pagination. + type: float + limit: + description: + - Limit query parameter. Maximum number of devices to return. + type: float +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for SDA GetProvisionedDevices + description: Complete reference of the GetProvisionedDevices API. + link: https://developer.cisco.com/docs/dna-center/#!get-provisioned-devices +notes: + - SDK Method used are + sda.Sda.get_provisioned_devices, + + - Paths used are + get /dna/intent/api/v1/sda/provisionDevices, + +""" + +EXAMPLES = r""" +- name: Get all Sda Provisiondevices + cisco.dnac.sda_provision_devices_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + id: string + networkDeviceId: string + siteId: string + offset: 0 + limit: 0 + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": [ + { + "id": "string", + "siteId": "string", + "networkDeviceId": "string" + } + ], + "version": "string" + } +""" diff --git a/plugins/modules/sda_site_member_member_info.py b/plugins/modules/sda_site_member_member_info.py new file mode 100644 index 0000000000..f79e95e028 --- /dev/null +++ b/plugins/modules/sda_site_member_member_info.py @@ -0,0 +1,141 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: sda_site_member_member_info +short_description: Information module for Sda Site Member Member +description: +- Get all Sda Site Member Member. +- API to get devices that are assigned to a site. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + id: + description: + - Id path parameter. Site Id. + type: str + offset: + description: + - Offset query parameter. Offset/starting index for pagination. + type: str + limit: + description: + - Limit query parameter. Number of devices to be listed. Default and max supported value is 500. + type: str + memberType: + description: + - MemberType query parameter. Member type (This API only supports the 'networkdevice' type). + type: str + level: + description: + - > + Level query parameter. Depth of site hierarchy to be considered to list the devices. If the provided value + is -1, devices for all child sites will be listed. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites GetDevicesThatAreAssignedToASite + description: Complete reference of the GetDevicesThatAreAssignedToASite API. + link: https://developer.cisco.com/docs/dna-center/#!get-devices-that-are-assigned-to-a-site +notes: + - SDK Method used are + sites.Sites.get_devices_that_are_assigned_to_a_site, + + - Paths used are + get /dna/intent/api/v1/site-member/{id}/member, + +""" + +EXAMPLES = r""" +- name: Get all Sda Site Member Member + cisco.dnac.sda_site_member_member_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + offset: string + limit: string + memberType: string + level: string + id: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "instanceUuid": "string", + "instanceId": 0, + "authEntityId": 0, + "authEntityClass": 0, + "instanceTenantId": "string", + "deployPending": "string", + "instanceVersion": 0, + "apManagerInterfaceIp": "string", + "associatedWlcIp": "string", + "bootDateTime": "string", + "collectionInterval": "string", + "collectionIntervalValue": "string", + "collectionStatus": "string", + "description": "string", + "deviceSupportLevel": "string", + "dnsResolvedManagementAddress": "string", + "family": "string", + "hostname": "string", + "interfaceCount": "string", + "inventoryStatusDetail": "string", + "lastUpdateTime": 0, + "lastUpdated": "string", + "lineCardCount": "string", + "lineCardId": "string", + "lastDeviceResyncStartTime": "string", + "macAddress": "string", + "managedAtleastOnce": true, + "managementIpAddress": "string", + "managementState": "string", + "memorySize": "string", + "paddedMgmtIpAddress": "string", + "pendingSyncRequestsCount": "string", + "platformId": "string", + "reachabilityFailureReason": "string", + "reachabilityStatus": "string", + "reasonsForDeviceResync": "string", + "reasonsForPendingSyncRequests": "string", + "role": "string", + "roleSource": "string", + "serialNumber": "string", + "series": "string", + "snmpContact": "string", + "snmpLocation": "string", + "softwareType": "string", + "softwareVersion": "string", + "tagCount": "string", + "type": "string", + "upTime": "string", + "uptimeSeconds": 0, + "vendor": "string", + "displayName": "string" + } + ] +""" diff --git a/plugins/modules/sda_virtual_network.py b/plugins/modules/sda_virtual_network.py index 09d01e5ed2..f2030d954b 100644 --- a/plugins/modules/sda_virtual_network.py +++ b/plugins/modules/sda_virtual_network.py @@ -24,8 +24,8 @@ description: VirtualNetworkName query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddVNInFabric description: Complete reference of the AddVNInFabric API. @@ -72,7 +72,6 @@ virtualNetworkName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_virtual_network_info.py b/plugins/modules/sda_virtual_network_info.py index 560c9179ff..c0e11c7e13 100644 --- a/plugins/modules/sda_virtual_network_info.py +++ b/plugins/modules/sda_virtual_network_info.py @@ -28,8 +28,8 @@ - SiteNameHierarchy query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetVNFromSDAFabric description: Complete reference of the GetVNFromSDAFabric API. @@ -59,7 +59,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -70,9 +69,12 @@ "siteNameHierarchy": "string", "virtualNetworkName": "string", "fabricName": "string", - "isInfraVN": "string", - "isDefaultVN": "string", + "isInfraVN": true, + "isDefaultVN": true, + "virtualNetworkContextId": "string", + "virtualNetworkId": "string", "status": "string", - "description": "string" + "description": "string", + "executionId": "string" } """ diff --git a/plugins/modules/sda_virtual_network_ip_pool.py b/plugins/modules/sda_virtual_network_ip_pool.py index 71bdf744f1..f13be8baf8 100644 --- a/plugins/modules/sda_virtual_network_ip_pool.py +++ b/plugins/modules/sda_virtual_network_ip_pool.py @@ -83,8 +83,8 @@ type: str version_added: 4.0.0 requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddIPPoolInSDAVirtualNetwork description: Complete reference of the AddIPPoolInSDAVirtualNetwork API. @@ -146,7 +146,6 @@ vlanName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_virtual_network_ip_pool_info.py b/plugins/modules/sda_virtual_network_ip_pool_info.py index 35de542c63..cffc2e9a34 100644 --- a/plugins/modules/sda_virtual_network_ip_pool_info.py +++ b/plugins/modules/sda_virtual_network_ip_pool_info.py @@ -31,11 +31,13 @@ ipPoolName: version_added: "4.0.0" description: - - IpPoolName query parameter. + - > + IpPoolName query parameter. IpPoolName. Note Use vlanName as a value for this parameter if same ip pool is + assigned to multiple virtual networks (e.g.. IpPoolName=vlan1021). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetIPPoolFromSDAVirtualNetwork description: Complete reference of the GetIPPoolFromSDAVirtualNetwork API. @@ -66,7 +68,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_virtual_network_v2.py b/plugins/modules/sda_virtual_network_v2.py index 27bffd8d97..ecb7822d71 100644 --- a/plugins/modules/sda_virtual_network_v2.py +++ b/plugins/modules/sda_virtual_network_v2.py @@ -32,8 +32,8 @@ description: Virtual Network Name to be assigned at global level. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA AddVirtualNetworkWithScalableGroups description: Complete reference of the AddVirtualNetworkWithScalableGroups API. @@ -103,7 +103,6 @@ virtualNetworkName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sda_virtual_network_v2_info.py b/plugins/modules/sda_virtual_network_v2_info.py index fc73454d14..14e78cdc47 100644 --- a/plugins/modules/sda_virtual_network_v2_info.py +++ b/plugins/modules/sda_virtual_network_v2_info.py @@ -24,8 +24,8 @@ - VirtualNetworkName query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for SDA GetVirtualNetworkWithScalableGroups description: Complete reference of the GetVirtualNetworkWithScalableGroups API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -68,7 +67,9 @@ "string" ], "vManageVpnId": "string", + "virtualNetworkContextId": "string", "status": "string", - "description": "string" + "description": "string", + "executionId": "string" } """ diff --git a/plugins/modules/security_advisories_devices_info.py b/plugins/modules/security_advisories_devices_info.py index 977fe48cd8..9cd619db2d 100644 --- a/plugins/modules/security_advisories_devices_info.py +++ b/plugins/modules/security_advisories_devices_info.py @@ -24,8 +24,8 @@ - AdvisoryId path parameter. Advisory ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Security Advisories GetDevicesPerAdvisory description: Complete reference of the GetDevicesPerAdvisory API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/security_advisories_ids_per_device_info.py b/plugins/modules/security_advisories_ids_per_device_info.py index 47f2db3968..b94f4128ef 100644 --- a/plugins/modules/security_advisories_ids_per_device_info.py +++ b/plugins/modules/security_advisories_ids_per_device_info.py @@ -10,7 +10,7 @@ short_description: Information module for Security Advisories Ids Per Device description: - Get Security Advisories Ids Per Device by id. -- Retrieves list of advisory IDs for a device. +- Retrieves advisory device details for a device. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -24,15 +24,15 @@ - DeviceId path parameter. Device instance UUID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Security Advisories GetAdvisoryIDsPerDevice - description: Complete reference of the GetAdvisoryIDsPerDevice API. - link: https://developer.cisco.com/docs/dna-center/#!get-advisory-i-ds-per-device +- name: Cisco DNA Center documentation for Security Advisories GetAdvisoryDeviceDetail + description: Complete reference of the GetAdvisoryDeviceDetail API. + link: https://developer.cisco.com/docs/dna-center/#!get-advisory-device-detail notes: - SDK Method used are - security_advisories.SecurityAdvisories.get_advisory_ids_per_device, + security_advisories.SecurityAdvisories.get_advisory_device_detail, - Paths used are get /dna/intent/api/v1/security-advisory/device/{deviceId}, @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -62,14 +61,17 @@ type: dict sample: > { - "response": [ - { - "deviceId": "string", - "advisoryIds": [ - "string" - ] - } - ], + "response": { + "deviceId": "string", + "advisoryIds": [ + "string" + ], + "hiddenAdvisoryCount": 0, + "scanMode": "string", + "scanStatus": "string", + "comments": "string", + "lastScanTime": 0 + }, "version": "string" } """ diff --git a/plugins/modules/security_advisories_info.py b/plugins/modules/security_advisories_info.py index a2d8603167..755e0d2cab 100644 --- a/plugins/modules/security_advisories_info.py +++ b/plugins/modules/security_advisories_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Security Advisories GetAdvisoriesList description: Complete reference of the GetAdvisoriesList API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -57,21 +56,20 @@ type: dict sample: > { - "response": [ - { - "advisoryId": "string", - "deviceCount": 0, - "hiddenDeviceCount": 0, - "cves": [ - "string" - ], - "publicationUrl": "string", - "sir": "string", - "detectionType": "string", - "defaultDetectionType": "string", - "defaultConfigMatchPattern": "string" - } - ], + "response": { + "advisoryId": "string", + "deviceCount": 0, + "hiddenDeviceCount": 0, + "cves": [ + "string" + ], + "publicationUrl": "string", + "sir": "string", + "detectionType": "string", + "defaultDetectionType": "string", + "defaultConfigMatchPattern": "string", + "fixedVersions": {} + }, "version": "string" } """ diff --git a/plugins/modules/security_advisories_per_device_info.py b/plugins/modules/security_advisories_per_device_info.py index 486bb46541..0ba2e4a88f 100644 --- a/plugins/modules/security_advisories_per_device_info.py +++ b/plugins/modules/security_advisories_per_device_info.py @@ -24,8 +24,8 @@ - DeviceId path parameter. Device instance UUID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Security Advisories GetAdvisoriesPerDevice description: Complete reference of the GetAdvisoriesPerDevice API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -62,21 +61,20 @@ type: dict sample: > { - "response": [ - { - "advisoryId": "string", - "deviceCount": 0, - "hiddenDeviceCount": 0, - "cves": [ - "string" - ], - "publicationUrl": "string", - "sir": "string", - "detectionType": "string", - "defaultDetectionType": "string", - "defaultConfigMatchPattern": "string" - } - ], + "response": { + "advisoryId": "string", + "deviceCount": 0, + "hiddenDeviceCount": 0, + "cves": [ + "string" + ], + "publicationUrl": "string", + "sir": "string", + "detectionType": "string", + "defaultDetectionType": "string", + "defaultConfigMatchPattern": "string", + "fixedVersions": {} + }, "version": "string" } """ diff --git a/plugins/modules/security_advisories_summary_info.py b/plugins/modules/security_advisories_summary_info.py index 88440acebf..2485c288a9 100644 --- a/plugins/modules/security_advisories_summary_info.py +++ b/plugins/modules/security_advisories_summary_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Security Advisories GetAdvisoriesSummary description: Complete reference of the GetAdvisoriesSummary API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -58,33 +57,39 @@ sample: > { "response": { - "NA": { - "CONFIG": 0, - "VERSION": 0, - "TOTAL": 0 - }, "INFORMATIONAL": { "CONFIG": 0, + "CUSTOM_CONFIG": 0, "VERSION": 0, "TOTAL": 0 }, "LOW": { "CONFIG": 0, + "CUSTOM_CONFIG": 0, "VERSION": 0, "TOTAL": 0 }, "MEDIUM": { "CONFIG": 0, + "CUSTOM_CONFIG": 0, "VERSION": 0, "TOTAL": 0 }, "HIGH": { "CONFIG": 0, + "CUSTOM_CONFIG": 0, "VERSION": 0, "TOTAL": 0 }, "CRITICAL": { "CONFIG": 0, + "CUSTOM_CONFIG": 0, + "VERSION": 0, + "TOTAL": 0 + }, + "NA": { + "CONFIG": 0, + "CUSTOM_CONFIG": 0, "VERSION": 0, "TOTAL": 0 } diff --git a/plugins/modules/sensor.py b/plugins/modules/sensor.py index c98887c451..9b7964d3f0 100644 --- a/plugins/modules/sensor.py +++ b/plugins/modules/sensor.py @@ -22,73 +22,578 @@ elements: dict suboptions: bands: - description: Bands. + description: The WIFI bands. type: str numberOfApsToTest: - description: Number Of Aps To Test. - type: str + description: Number of APs to test. + type: int rssiThreshold: - description: Rssi Threshold. - type: str + description: RSSI threshold. + type: int type: list connection: - description: Connection. + description: Connection type of test WIRED, WIRELESS, BOTH. + type: str + encryptionMode: + description: Encryption mode. type: str + locationInfoList: + description: Sensor's locationInfoList. + elements: dict + suboptions: + allSensors: + description: Use all sensors in the site for test. + type: bool + customManagementVlan: + description: Custom Management VLAN. + type: bool + locationId: + description: Site UUID. + type: str + locationType: + description: Site type. + type: str + macAddressList: + description: MAC addresses. + elements: str + type: list + managementVlan: + description: Management VLAN. + type: str + siteHierarchy: + description: Site name hierarhy. + type: str + type: list modelVersion: - description: Model Version. + description: Test template object model version (must be 2). type: int name: - description: Name. + description: The sensor test template name. + type: str + profiles: + description: Sensor's profiles. + elements: dict + suboptions: + authProtocol: + description: Auth protocol. + type: str + authType: + description: Authentication type OPEN, WPA2_PSK, WPA2_EaP, WEB_AUTH, MAB, DOT1X, + OTHER. + type: str + certdownloadurl: + description: Certificate download URL. + type: str + certfilename: + description: Auth certificate file name. + type: str + certpassphrase: + description: Certificate password phrase. + type: str + certstatus: + description: Certificate status INACTIVE or ACTIVE. + type: str + certxferprotocol: + description: Certificate transfering protocol HTTP or HTTPS. + type: str + deviceType: + description: Device Type. + type: str + eapMethod: + description: WPA2_EAP methods EAP-FAST, PEAP-MSCHAPv2, EAP-TLS, PEAP-TLS, EAP-TTLS-MSCHAPv2, + EAP-TTLS-PAP, EAP-TTLS-CHAP, EAP-FAST-GTC, EAP-PEAP-GTC. + type: str + extWebAuth: + description: Indication of using external WEB Auth. + type: bool + extWebAuthAccessUrl: + description: External WEB Auth access URL. + type: str + extWebAuthHtmlTag: + description: Sensor's extWebAuthHtmlTag. + elements: dict + suboptions: + label: + description: Label. + type: str + tag: + description: Tag. + type: str + value: + description: Value. + type: str + type: list + extWebAuthPortal: + description: External authentication portal. + type: str + extWebAuthVirtualIp: + description: External WEB Auth virtual IP. + type: str + locationVlanList: + description: Sensor's locationVlanList. + elements: dict + suboptions: + locationId: + description: Site UUID. + type: str + vlans: + description: Array of VLANs. + elements: str + type: list + type: list + password: + description: Password string for onboarding SSID. + type: str + passwordType: + description: SSID password type ASCII or HEX. + type: str + profileName: + description: Profile name. + type: str + psk: + description: Password of SSID when passwordType is ASCII. + type: str + qosPolicy: + description: QoS policy PlATINUM, GOLD, SILVER, BRONZE. + type: str + scep: + description: Secure certificate enrollment protocol true or false or null for + not applicable. + type: bool + tests: + description: Sensor's tests. + elements: dict + suboptions: + config: + description: Sensor's config. + elements: dict + suboptions: + direction: + description: IPerf direction (UPLOAD, DOWNLOAD, BOTH). + type: str + domains: + description: DNS domain name. + elements: str + type: list + downlinkTest: + description: Downlink test. + type: bool + endPort: + description: IPerf end port. + type: int + exitCommand: + description: Exit command. + type: str + finalPrompt: + description: Final prompt. + type: str + ndtServer: + description: NDT server. + type: str + ndtServerPath: + description: NDT server path. + type: str + ndtServerPort: + description: NDT server port. + type: str + numPackets: + description: Number of packets. + type: int + password: + description: Password. + type: str + passwordPrompt: + description: Password prompt. + type: str + pathToDownload: + description: File path for file transfer. + type: str + port: + description: Radius or WEB server port. + type: int + probeType: + description: Probe type. + type: str + protocol: + description: Protocol used by file transfer, IPerf, mail server, and + radius (TCP, UDP, FTP, POP3, IMAP, CHAP, PAP). + type: str + proxyPassword: + description: Proxy password. + type: str + proxyPort: + description: Proxy port. + type: str + proxyServer: + description: Proxy server. + type: str + proxyUserName: + description: Proxy user name. + type: str + server: + description: Ping, file transfer, mail, radius, ssh, or telnet server. + type: str + servers: + description: IPerf server list. + elements: str + type: list + sharedSecret: + description: Shared secret. + type: str + startPort: + description: IPerf start port. + type: int + transferType: + description: File transfer type (UPLOAD, DOWNLOAD, BOTH). + type: str + udpBandwidth: + description: IPerf UDP bandwidth. + type: int + uplinkTest: + description: Uplink test. + type: bool + url: + description: URL. + type: str + userName: + description: User name. + type: str + userNamePrompt: + description: User name prompt. + type: str + type: list + name: + description: Name of the test. + type: str + type: list + username: + description: User name string for onboarding SSID. + type: str + vlan: + description: VLAN. + type: str + whiteList: + description: Indication of being on allowed list. + type: bool + type: list + runNow: + description: Run now (YES, NO). type: str + sensors: + description: Sensor's sensors. + elements: dict + suboptions: + allSensorAddition: + description: Is all sensor addition. + type: bool + assigned: + description: Is assigned. + type: bool + configUpdated: + description: Configuration updated YES, NO. + type: str + hostName: + description: Host name. + type: str + iPerfInfo: + description: A string-stringList iPerf information. + type: dict + id: + description: Sensor ID. + type: str + ipAddress: + description: IP address. + type: str + locationId: + description: Site UUID. + type: str + macAddress: + description: MAC address. + type: str + markedForUninstall: + description: Is marked for uninstall. + type: bool + name: + description: Sensor name. + type: str + runNow: + description: Run now YES, NO. + type: str + sensorType: + description: Sensor type. + type: str + servicePolicy: + description: Service policy. + type: str + status: + description: Sensor device status UP, DOWN, REBOOT. + type: str + switchMac: + description: Switch MAC address. + type: str + switchSerialNumber: + description: Switch serial number. + type: str + switchUuid: + description: Switch device UUID. + type: str + targetAPs: + description: Array of target APs. + elements: str + type: list + testMacAddresses: + description: A string-string test MAC address. + type: dict + wiredApplicationMessage: + description: Wired application message. + type: str + wiredApplicationStatus: + description: Wired application status. + type: str + xorSensor: + description: Is XOR sensor. + type: bool + type: list ssids: description: Sensor's ssids. elements: dict suboptions: + authProtocol: + description: Auth protocol. + type: str authType: - description: Auth Type. + description: Authentication type OPEN, WPA2_PSK, WPA2_EaP, WEB_AUTH, MAB, DOT1X, + OTHER. type: str - categories: - description: Categories. - elements: str + bands: + description: WIFI bands 2.4GHz or 5GHz. + type: str + certdownloadurl: + description: Certificate download URL. + type: str + certfilename: + description: Auth certificate file name. + type: str + certpassphrase: + description: Certificate password phrase. + type: str + certstatus: + description: Certificate status INACTIVE or ACTIVE. + type: str + certxferprotocol: + description: Certificate transfering protocol HTTP or HTTPS. + type: str + eapMethod: + description: WPA2_EAP methods EAP-FAST, PEAP-MSCHAPv2, EAP-TLS, PEAP-TLS, EAP-TTLS-MSCHAPv2, + EAP-TTLS-PAP, EAP-TTLS-CHAP, EAP-FAST-GTC, EAP-PEAP-GTC. + type: str + extWebAuth: + description: Indication of using external WEB Auth. + type: bool + extWebAuthAccessUrl: + description: External WEB Auth access URL. + type: str + extWebAuthHtmlTag: + description: Sensor's extWebAuthHtmlTag. + elements: dict + suboptions: + label: + description: Label. + type: str + tag: + description: Tag. + type: str + value: + description: Value. + type: str type: list + extWebAuthPortal: + description: External authentication portal. + type: str + extWebAuthVirtualIp: + description: External WEB Auth virtual IP. + type: str + layer3webAuthEmailAddress: + description: Layer 3 WEB Auth email address. + type: str + layer3webAuthpassword: + description: Layer 3 WEB Auth password. + type: str + layer3webAuthsecurity: + description: Layer 3 WEB Auth security. + type: str + layer3webAuthuserName: + description: Layer 3 WEB Auth user name. + type: str + password: + description: Password string for onboarding SSID. + type: str + passwordType: + description: SSID password type ASCII or HEX. + type: str profileName: - description: Profile Name. + description: The SSID profile name string. + type: str + proxyPassword: + description: Proxy server password. + type: str + proxyPort: + description: Proxy server port. + type: str + proxyServer: + description: Proxy server for onboarding SSID. + type: str + proxyUserName: + description: Proxy server user name. type: str psk: - description: Psk. + description: Password of SSID when passwordType is ASCII. type: str qosPolicy: - description: Qos Policy. + description: QoS policy PlATINUM, GOLD, SILVER, BRONZE. type: str + scep: + description: Secure certificate enrollment protocol true or false or null for + not applicable. + type: bool ssid: - description: Ssid. + description: The SSID string. type: str tests: description: Sensor's tests. elements: dict suboptions: config: - description: Config. + description: Sensor's config. elements: dict + suboptions: + direction: + description: IPerf direction (UPLOAD, DOWNLOAD, BOTH). + type: str + domains: + description: DNS domain name. + elements: str + type: list + downlinkTest: + description: Downlink test. + type: bool + endPort: + description: IPerf end port. + type: int + exitCommand: + description: Exit command. + type: str + finalPrompt: + description: Final prompt. + type: str + ndtServer: + description: NDT server. + type: str + ndtServerPath: + description: NDT server path. + type: str + ndtServerPort: + description: NDT server port. + type: str + numPackets: + description: Number of packets. + type: int + password: + description: Password. + type: str + passwordPrompt: + description: Password prompt. + type: str + pathToDownload: + description: File path for file transfer. + type: str + port: + description: Radius or WEB server port. + type: int + probeType: + description: Probe type. + type: str + protocol: + description: Protocol used by file transfer, IPerf, mail server, and + radius (TCP, UDP, FTP, POP3, IMAP, CHAP, PAP). + type: str + proxyPassword: + description: Proxy password. + type: str + proxyPort: + description: Proxy port. + type: str + proxyServer: + description: Proxy server. + type: str + proxyUserName: + description: Proxy user name. + type: str + server: + description: Ping, file transfer, mail, radius, ssh, or telnet server. + type: str + servers: + description: IPerf server list. + elements: str + type: list + sharedSecret: + description: Shared secret. + type: str + startPort: + description: IPerf start port. + type: int + transferType: + description: File transfer type (UPLOAD, DOWNLOAD, BOTH). + type: str + udpBandwidth: + description: IPerf UDP bandwidth. + type: int + uplinkTest: + description: Uplink test. + type: bool + url: + description: URL. + type: str + userName: + description: User name. + type: str + userNamePrompt: + description: User name prompt. + type: str type: list name: - description: Name. + description: Name of the test. type: str type: list thirdParty: description: Sensor's thirdParty. suboptions: selected: - description: Selected. + description: True the SSID is third party. type: bool type: dict + username: + description: User name string for onboarding SSID. + type: str + whiteList: + description: Indication of being on allowed list. + type: bool + wlanId: + description: WLAN ID. + type: int + wlc: + description: WLC IP addres. + type: str type: list templateName: description: TemplateName query parameter. type: str + version: + description: The sensor test template version (must be 2). + type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sensors CreateSensorTestTemplate description: Complete reference of the CreateSensorTestTemplate API. @@ -120,25 +625,188 @@ state: present apCoverage: - bands: string - numberOfApsToTest: string - rssiThreshold: string + numberOfApsToTest: 0 + rssiThreshold: 0 connection: string + encryptionMode: string + locationInfoList: + - allSensors: true + customManagementVlan: true + locationId: string + locationType: string + macAddressList: + - string + managementVlan: string + siteHierarchy: string modelVersion: 0 name: string - ssids: - - authType: string - categories: + profiles: + - authProtocol: string + authType: string + certdownloadurl: string + certfilename: string + certpassphrase: string + certstatus: string + certxferprotocol: string + deviceType: string + eapMethod: string + extWebAuth: true + extWebAuthAccessUrl: string + extWebAuthHtmlTag: + - label: string + tag: string + value: string + extWebAuthPortal: string + extWebAuthVirtualIp: string + locationVlanList: + - locationId: string + vlans: + - string + password: string + passwordType: string + profileName: string + psk: string + qosPolicy: string + scep: true + tests: + - config: + - direction: string + domains: + - string + downlinkTest: true + endPort: 0 + exitCommand: string + finalPrompt: string + ndtServer: string + ndtServerPath: string + ndtServerPort: string + numPackets: 0 + password: string + passwordPrompt: string + pathToDownload: string + port: 0 + probeType: string + protocol: string + proxyPassword: string + proxyPort: string + proxyServer: string + proxyUserName: string + server: string + servers: + - string + sharedSecret: string + startPort: 0 + transferType: string + udpBandwidth: 0 + uplinkTest: true + url: string + userName: string + userNamePrompt: string + name: string + username: string + vlan: string + whiteList: true + runNow: string + sensors: + - allSensorAddition: true + assigned: true + configUpdated: string + hostName: string + iPerfInfo: {} + id: string + ipAddress: string + locationId: string + macAddress: string + markedForUninstall: true + name: string + runNow: string + sensorType: string + servicePolicy: string + status: string + switchMac: string + switchSerialNumber: string + switchUuid: string + targetAPs: - string + testMacAddresses: {} + wiredApplicationMessage: string + wiredApplicationStatus: string + xorSensor: true + ssids: + - authProtocol: string + authType: string + bands: string + certdownloadurl: string + certfilename: string + certpassphrase: string + certstatus: string + certxferprotocol: string + eapMethod: string + extWebAuth: true + extWebAuthAccessUrl: string + extWebAuthHtmlTag: + - label: string + tag: string + value: string + extWebAuthPortal: string + extWebAuthVirtualIp: string + layer3webAuthEmailAddress: string + layer3webAuthpassword: string + layer3webAuthsecurity: string + layer3webAuthuserName: string + password: string + passwordType: string profileName: string + proxyPassword: string + proxyPort: string + proxyServer: string + proxyUserName: string psk: string qosPolicy: string + scep: true ssid: string tests: - config: - - {} + - direction: string + domains: + - string + downlinkTest: true + endPort: 0 + exitCommand: string + finalPrompt: string + ndtServer: string + ndtServerPath: string + ndtServerPort: string + numPackets: 0 + password: string + passwordPrompt: string + pathToDownload: string + port: 0 + probeType: string + protocol: string + proxyPassword: string + proxyPort: string + proxyServer: string + proxyUserName: string + server: string + servers: + - string + sharedSecret: string + startPort: 0 + transferType: string + udpBandwidth: 0 + uplinkTest: true + url: string + userName: string + userNamePrompt: string name: string thirdParty: selected: true + username: string + whiteList: true + wlanId: 0 + wlc: string + version: 0 - name: Delete all cisco.dnac.sensor: @@ -153,7 +821,6 @@ templateName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -163,71 +830,202 @@ { "version": "string", "response": { - "_id": "string", "name": "string", + "_id": "string", "version": 0, "modelVersion": 0, "startTime": 0, "lastModifiedTime": 0, "numAssociatedSensor": 0, - "location": {}, - "siteHierarchy": {}, + "location": "string", + "siteHierarchy": "string", "status": "string", "connection": "string", - "frequency": {}, + "actionInProgress": "string", + "frequency": { + "value": 0, + "unit": "string" + }, "rssiThreshold": 0, "numNeighborAPThreshold": 0, "scheduleInDays": 0, "wlans": [ - {} + "string" ], "ssids": [ { - "bands": {}, + "bands": "string", "ssid": "string", "profileName": "string", - "authType": "string", - "authTypeRcvd": {}, - "psk": "string", - "username": {}, - "password": {}, - "eapMethod": {}, - "scep": true, - "authProtocol": {}, - "certfilename": {}, - "certxferprotocol": "string", - "certstatus": "string", - "certpassphrase": {}, - "certdownloadurl": {}, "numAps": 0, "numSensors": 0, - "layer3webAuthsecurity": {}, - "layer3webAuthuserName": {}, - "layer3webAuthpassword": {}, - "extWebAuthVirtualIp": {}, - "layer3webAuthEmailAddress": {}, - "qosPolicy": "string", - "extWebAuth": true, - "whiteList": true, - "extWebAuthPortal": {}, - "extWebAuthAccessUrl": {}, - "extWebAuthHtmlTag": [ - {} - ], + "layer3webAuthsecurity": "string", + "layer3webAuthuserName": "string", + "layer3webAuthpassword": "string", + "layer3webAuthEmailAddress": "string", "thirdParty": { "selected": true }, "id": 0, "wlanId": 0, - "wlc": {}, + "wlc": "string", "validFrom": 0, "validTo": 0, "status": "string", + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "authType": "string", + "psk": "string", + "username": "string", + "password": "string", + "passwordType": "string", + "eapMethod": "string", + "scep": true, + "authProtocol": "string", + "certfilename": "string", + "certxferprotocol": "string", + "certstatus": "string", + "certpassphrase": "string", + "certdownloadurl": "string", + "extWebAuthVirtualIp": "string", + "extWebAuth": true, + "whiteList": true, + "extWebAuthPortal": "string", + "extWebAuthAccessUrl": "string", + "extWebAuthHtmlTag": [ + { + "label": "string", + "tag": "string", + "value": "string" + } + ], + "qosPolicy": "string", + "tests": [ + { + "name": "string", + "config": [ + { + "domains": [ + "string" + ], + "server": "string", + "userName": "string", + "password": "string", + "url": "string", + "port": 0, + "protocol": "string", + "servers": [ + "string" + ], + "direction": "string", + "startPort": 0, + "endPort": 0, + "udpBandwidth": 0, + "probeType": "string", + "numPackets": 0, + "pathToDownload": "string", + "transferType": "string", + "sharedSecret": "string", + "ndtServer": "string", + "ndtServerPort": "string", + "ndtServerPath": "string", + "uplinkTest": true, + "downlinkTest": true, + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "userNamePrompt": "string", + "passwordPrompt": "string", + "exitCommand": "string", + "finalPrompt": "string" + } + ] + } + ] + } + ], + "profiles": [ + { + "authType": "string", + "psk": "string", + "username": "string", + "password": "string", + "passwordType": "string", + "eapMethod": "string", + "scep": true, + "authProtocol": "string", + "certfilename": "string", + "certxferprotocol": "string", + "certstatus": "string", + "certpassphrase": "string", + "certdownloadurl": "string", + "extWebAuthVirtualIp": "string", + "extWebAuth": true, + "whiteList": true, + "extWebAuthPortal": "string", + "extWebAuthAccessUrl": "string", + "extWebAuthHtmlTag": [ + { + "label": "string", + "tag": "string", + "value": "string" + } + ], + "qosPolicy": "string", "tests": [ { "name": "string", "config": [ - {} + { + "domains": [ + "string" + ], + "server": "string", + "userName": "string", + "password": "string", + "url": "string", + "port": 0, + "protocol": "string", + "servers": [ + "string" + ], + "direction": "string", + "startPort": 0, + "endPort": 0, + "udpBandwidth": 0, + "probeType": "string", + "numPackets": 0, + "pathToDownload": "string", + "transferType": "string", + "sharedSecret": "string", + "ndtServer": "string", + "ndtServerPort": "string", + "ndtServerPath": "string", + "uplinkTest": true, + "downlinkTest": true, + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "userNamePrompt": "string", + "passwordPrompt": "string", + "exitCommand": "string", + "finalPrompt": "string" + } + ] + } + ], + "profileName": "string", + "deviceType": "string", + "vlan": "string", + "locationVlanList": [ + { + "locationId": "string", + "vlans": [ + "string" ] } ] @@ -239,12 +1037,46 @@ "encryptionMode": "string", "runNow": "string", "locationInfoList": [ - {} + { + "locationId": "string", + "locationType": "string", + "allSensors": true, + "siteHierarchy": "string", + "macAddressList": [ + "string" + ], + "managementVlan": "string", + "customManagementVlan": true + } ], - "schedule": {}, - "tests": {}, "sensors": [ - {} + { + "name": "string", + "macAddress": "string", + "switchMac": "string", + "switchUuid": "string", + "switchSerialNumber": "string", + "markedForUninstall": true, + "ipAddress": "string", + "hostName": "string", + "wiredApplicationStatus": "string", + "wiredApplicationMessage": "string", + "assigned": true, + "status": "string", + "xorSensor": true, + "targetAPs": [ + "string" + ], + "runNow": "string", + "locationId": "string", + "allSensorAddition": true, + "configUpdated": "string", + "sensorType": "string", + "testMacAddresses": {}, + "id": "string", + "servicePolicy": "string", + "iPerfInfo": {} + } ], "apCoverage": [ { @@ -252,11 +1084,7 @@ "numberOfApsToTest": 0, "rssiThreshold": 0 } - ], - "testDurationEstimate": 0, - "testTemplate": true, - "legacyTestSuite": true, - "tenantId": {} + ] } } """ diff --git a/plugins/modules/sensor_info.py b/plugins/modules/sensor_info.py index 2955ceac13..479c1b4f9f 100644 --- a/plugins/modules/sensor_info.py +++ b/plugins/modules/sensor_info.py @@ -24,8 +24,8 @@ - SiteId query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sensors Sensors description: Complete reference of the Sensors API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -76,13 +75,13 @@ "version": "string", "lastSeen": 0, "type": "string", - "sshConfig": { + "ssh": { "sshState": "string", "sshUserName": "string", "sshPassword": "string", "enablePassword": "string" }, - "isLEDEnabled": true + "led": true } ] } diff --git a/plugins/modules/sensor_test_run.py b/plugins/modules/sensor_test_run.py index cb800c9687..c1aaac43dc 100644 --- a/plugins/modules/sensor_test_run.py +++ b/plugins/modules/sensor_test_run.py @@ -20,8 +20,8 @@ description: Template Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sensors RunNowSensorTest description: Complete reference of the RunNowSensorTest API. @@ -48,7 +48,6 @@ templateName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sensor_test_template_duplicate.py b/plugins/modules/sensor_test_template_duplicate.py index 85cad96d2c..f0df5aab78 100644 --- a/plugins/modules/sensor_test_template_duplicate.py +++ b/plugins/modules/sensor_test_template_duplicate.py @@ -17,14 +17,14 @@ author: Rafael Campos (@racampos) options: newTemplateName: - description: New Template Name. + description: Destination test template name. type: str templateName: - description: Template Name. + description: Source test template name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sensors DuplicateSensorTestTemplate description: Complete reference of the DuplicateSensorTestTemplate API. @@ -52,7 +52,6 @@ templateName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -62,71 +61,202 @@ { "version": "string", "response": { - "_id": "string", "name": "string", + "_id": "string", "version": 0, "modelVersion": 0, "startTime": 0, "lastModifiedTime": 0, "numAssociatedSensor": 0, - "location": {}, - "siteHierarchy": {}, + "location": "string", + "siteHierarchy": "string", "status": "string", "connection": "string", - "frequency": {}, + "actionInProgress": "string", + "frequency": { + "value": 0, + "unit": "string" + }, "rssiThreshold": 0, "numNeighborAPThreshold": 0, "scheduleInDays": 0, "wlans": [ - {} + "string" ], "ssids": [ { - "bands": {}, + "bands": "string", "ssid": "string", "profileName": "string", - "authType": "string", - "authTypeRcvd": {}, - "psk": "string", - "username": {}, - "password": {}, - "eapMethod": {}, - "scep": true, - "authProtocol": {}, - "certfilename": {}, - "certxferprotocol": "string", - "certstatus": "string", - "certpassphrase": {}, - "certdownloadurl": {}, "numAps": 0, "numSensors": 0, - "layer3webAuthsecurity": {}, - "layer3webAuthuserName": {}, - "layer3webAuthpassword": {}, - "extWebAuthVirtualIp": {}, - "layer3webAuthEmailAddress": {}, - "qosPolicy": "string", - "extWebAuth": true, - "whiteList": true, - "extWebAuthPortal": {}, - "extWebAuthAccessUrl": {}, - "extWebAuthHtmlTag": [ - {} - ], + "layer3webAuthsecurity": "string", + "layer3webAuthuserName": "string", + "layer3webAuthpassword": "string", + "layer3webAuthEmailAddress": "string", "thirdParty": { "selected": true }, "id": 0, "wlanId": 0, - "wlc": {}, + "wlc": "string", "validFrom": 0, "validTo": 0, "status": "string", + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "authType": "string", + "psk": "string", + "username": "string", + "password": "string", + "passwordType": "string", + "eapMethod": "string", + "scep": true, + "authProtocol": "string", + "certfilename": "string", + "certxferprotocol": "string", + "certstatus": "string", + "certpassphrase": "string", + "certdownloadurl": "string", + "extWebAuthVirtualIp": "string", + "extWebAuth": true, + "whiteList": true, + "extWebAuthPortal": "string", + "extWebAuthAccessUrl": "string", + "extWebAuthHtmlTag": [ + { + "label": "string", + "tag": "string", + "value": "string" + } + ], + "qosPolicy": "string", "tests": [ { "name": "string", "config": [ - {} + { + "domains": [ + "string" + ], + "server": "string", + "userName": "string", + "password": "string", + "url": "string", + "port": 0, + "protocol": "string", + "servers": [ + "string" + ], + "direction": "string", + "startPort": 0, + "endPort": 0, + "udpBandwidth": 0, + "probeType": "string", + "numPackets": 0, + "pathToDownload": "string", + "transferType": "string", + "sharedSecret": "string", + "ndtServer": "string", + "ndtServerPort": "string", + "ndtServerPath": "string", + "uplinkTest": true, + "downlinkTest": true, + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "userNamePrompt": "string", + "passwordPrompt": "string", + "exitCommand": "string", + "finalPrompt": "string" + } + ] + } + ] + } + ], + "profiles": [ + { + "authType": "string", + "psk": "string", + "username": "string", + "password": "string", + "passwordType": "string", + "eapMethod": "string", + "scep": true, + "authProtocol": "string", + "certfilename": "string", + "certxferprotocol": "string", + "certstatus": "string", + "certpassphrase": "string", + "certdownloadurl": "string", + "extWebAuthVirtualIp": "string", + "extWebAuth": true, + "whiteList": true, + "extWebAuthPortal": "string", + "extWebAuthAccessUrl": "string", + "extWebAuthHtmlTag": [ + { + "label": "string", + "tag": "string", + "value": "string" + } + ], + "qosPolicy": "string", + "tests": [ + { + "name": "string", + "config": [ + { + "domains": [ + "string" + ], + "server": "string", + "userName": "string", + "password": "string", + "url": "string", + "port": 0, + "protocol": "string", + "servers": [ + "string" + ], + "direction": "string", + "startPort": 0, + "endPort": 0, + "udpBandwidth": 0, + "probeType": "string", + "numPackets": 0, + "pathToDownload": "string", + "transferType": "string", + "sharedSecret": "string", + "ndtServer": "string", + "ndtServerPort": "string", + "ndtServerPath": "string", + "uplinkTest": true, + "downlinkTest": true, + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "userNamePrompt": "string", + "passwordPrompt": "string", + "exitCommand": "string", + "finalPrompt": "string" + } + ] + } + ], + "profileName": "string", + "deviceType": "string", + "vlan": "string", + "locationVlanList": [ + { + "locationId": "string", + "vlans": [ + "string" ] } ] @@ -144,36 +274,40 @@ "allSensors": true, "siteHierarchy": "string", "macAddressList": [ - {} - ] + "string" + ], + "managementVlan": "string", + "customManagementVlan": true } ], - "schedule": { - "testScheduleMode": "string", - "scheduleRange": [ - { - "timeRange": [ - { - "from": "string", - "to": "string", - "frequency": { - "value": 0, - "unit": "string" - } - } - ], - "day": "string" - } - ], - "startTime": 0, - "frequency": { - "value": 0, - "unit": "string" - } - }, - "tests": {}, "sensors": [ - {} + { + "name": "string", + "macAddress": "string", + "switchMac": "string", + "switchUuid": "string", + "switchSerialNumber": "string", + "markedForUninstall": true, + "ipAddress": "string", + "hostName": "string", + "wiredApplicationStatus": "string", + "wiredApplicationMessage": "string", + "assigned": true, + "status": "string", + "xorSensor": true, + "targetAPs": [ + "string" + ], + "runNow": "string", + "locationId": "string", + "allSensorAddition": true, + "configUpdated": "string", + "sensorType": "string", + "testMacAddresses": {}, + "id": "string", + "servicePolicy": "string", + "iPerfInfo": {} + } ], "apCoverage": [ { @@ -181,11 +315,7 @@ "numberOfApsToTest": 0, "rssiThreshold": 0 } - ], - "testDurationEstimate": 0, - "testTemplate": true, - "legacyTestSuite": true, - "tenantId": {} + ] } } """ diff --git a/plugins/modules/sensor_test_template_edit.py b/plugins/modules/sensor_test_template_edit.py index b8bf3f3b42..fd9ef70829 100644 --- a/plugins/modules/sensor_test_template_edit.py +++ b/plugins/modules/sensor_test_template_edit.py @@ -16,75 +16,659 @@ - cisco.dnac.module author: Rafael Campos (@racampos) options: + _id: + description: The sensor test template unique identifier, generated at test creation + time. + type: str + actionInProgress: + description: Indication of inprogress action. + type: str + apCoverage: + description: Sensor Test Template Edit's apCoverage. + elements: dict + suboptions: + bands: + description: The WIFI bands. + type: str + numberOfApsToTest: + description: Number of APs to test. + type: int + rssiThreshold: + description: RSSI threshold. + type: int + type: list + connection: + description: Connection type of test WIRED, WIRELESS, BOTH. + type: str + encryptionMode: + description: Encryption mode. + type: str + frequency: + description: Sensor Test Template Edit's frequency. + suboptions: + unit: + description: Unit of the time value (NANOSECONDS, MICROSECONDS, MILLISECONDS, + SECONDS, MINUTES, HOURS, DAYS). + type: str + value: + description: Value of the unit. + type: int + type: dict + lastModifiedTime: + description: Last modify time. + type: int + location: + description: Location string. + type: str locationInfoList: description: Sensor Test Template Edit's locationInfoList. elements: dict suboptions: allSensors: - description: All Sensors. + description: Use all sensors in the site for test. + type: bool + customManagementVlan: + description: Custom Management VLAN. type: bool locationId: - description: Location Id. + description: Site UUID. type: str locationType: - description: Location Type. + description: Site type. + type: str + macAddressList: + description: MAC addresses. + elements: str + type: list + managementVlan: + description: Management VLAN. type: str siteHierarchy: - description: Site Hierarchy. + description: Site name hierarhy. type: str type: list - schedule: - description: Sensor Test Template Edit's schedule. + modelVersion: + description: Test template object model version (must be 2). + type: int + name: + description: The sensor test template name, which is the same as in 'templateName'. + type: str + numAssociatedSensor: + description: Number of associated sensor. + type: int + numNeighborAPThreshold: + description: Number of neighboring AP threshold. + type: int + profiles: + description: Sensor Test Template Edit's profiles. + elements: dict suboptions: - frequency: - description: Sensor Test Template Edit's frequency. + authProtocol: + description: Auth protocol. + type: str + authType: + description: Authentication type OPEN, WPA2_PSK, WPA2_EAP, WEB_AUTH, MAB, DOT1X, + OTHER. + type: str + certdownloadurl: + description: Certificate download URL. + type: str + certfilename: + description: Auth certificate file name. + type: str + certpassphrase: + description: Certificate password phrase. + type: str + certstatus: + description: Certificate status INACTIVE or ACTIVE. + type: str + certxferprotocol: + description: Certificate transfering protocol HTTP or HTTPS. + type: str + deviceType: + description: Device Type. + type: str + eapMethod: + description: WPA2_EAP methods EAP-FAST, PEAP-MSCHAPv2, EAP-TLS, PEAP-TLS, EAP-TTLS-MSCHAPv2, + EAP-TTLS-PAP, EAP-TTLS-CHAP, EAP-FAST-GTC, EAP-PEAP-GTC. + type: str + extWebAuth: + description: Indication of using external WEB Auth. + type: bool + extWebAuthAccessUrl: + description: External WEB Auth access URL. + type: str + extWebAuthHtmlTag: + description: Sensor Test Template Edit's extWebAuthHtmlTag. + elements: dict suboptions: - unit: - description: Unit. + label: + description: Label. + type: str + tag: + description: Tag. type: str value: description: Value. - type: int + type: str + type: list + extWebAuthPortal: + description: External authentication portal. + type: str + extWebAuthVirtualIp: + description: External WEB Auth virtual IP. + type: str + locationVlanList: + description: Sensor Test Template Edit's locationVlanList. + elements: dict + suboptions: + locationId: + description: Site UUID. + type: str + vlans: + description: Array of VLANs. + elements: str + type: list + type: list + password: + description: Password string for onboarding SSID. + type: str + passwordType: + description: SSID password type ASCII or HEX. + type: str + profileName: + description: Profile name. + type: str + psk: + description: Password of SSID when passwordType is ASCII. + type: str + qosPolicy: + description: QoS policy PlATINUM, GOLD, SILVER, BRONZE. + type: str + scep: + description: Secure certificate enrollment protocol true or false or null for + not applicable. + type: bool + tests: + description: Sensor Test Template Edit's tests. + elements: dict + suboptions: + config: + description: Sensor Test Template Edit's config. + elements: dict + suboptions: + direction: + description: IPerf direction (UPLOAD, DOWNLOAD, BOTH). + type: str + domains: + description: DNS domain name. + elements: str + type: list + downlinkTest: + description: Downlink test. + type: bool + endPort: + description: IPerf end port. + type: int + exitCommand: + description: Exit command. + type: str + finalPrompt: + description: Final prompt. + type: str + ndtServer: + description: NDT server. + type: str + ndtServerPath: + description: NDT server path. + type: str + ndtServerPort: + description: NDT server port. + type: str + numPackets: + description: Number of packets. + type: int + password: + description: Password. + type: str + passwordPrompt: + description: Password prompt. + type: str + pathToDownload: + description: File path for file transfer. + type: str + port: + description: Radius or WEB server port. + type: int + probeType: + description: Probe type. + type: str + protocol: + description: Protocol used by file transfer, IPerf, mail server, and + radius (TCP, UDP, FTP, POP3, IMAP, CHAP, PAP). + type: str + proxyPassword: + description: Proxy password. + type: str + proxyPort: + description: Proxy port. + type: str + proxyServer: + description: Proxy server. + type: str + proxyUserName: + description: Proxy user name. + type: str + server: + description: Ping, file transfer, mail, radius, ssh, or telnet server. + type: str + servers: + description: IPerf server list. + elements: str + type: list + sharedSecret: + description: Shared secret. + type: str + startPort: + description: IPerf start port. + type: int + transferType: + description: File transfer type (UPLOAD, DOWNLOAD, BOTH). + type: str + udpBandwidth: + description: IPerf UDP bandwidth. + type: int + uplinkTest: + description: Uplink test. + type: bool + url: + description: URL. + type: str + userName: + description: User name. + type: str + userNamePrompt: + description: User name prompt. + type: str + type: list + name: + description: Name of the test. + type: str + type: list + username: + description: User name string for onboarding SSID. + type: str + vlan: + description: VLAN. + type: str + whiteList: + description: Indication of being on allowed list. + type: bool + type: list + radioAsSensorRemoved: + description: Radio as sensor removed. + type: bool + rssiThreshold: + description: RSSI threshold. + type: int + runNow: + description: Run now (YES, NO). + type: str + scheduleInDays: + description: Bit-wise value of scheduled test days. + type: int + sensors: + description: Sensor Test Template Edit's sensors. + elements: dict + suboptions: + allSensorAddition: + description: Is all sensor addition. + type: bool + assigned: + description: Is assigned. + type: bool + configUpdated: + description: Configuration updated YES, NO. + type: str + hostName: + description: Host name. + type: str + iPerfInfo: + description: A string-stringList iPerf information. + type: dict + id: + description: Sensor ID. + type: str + ipAddress: + description: IP address. + type: str + locationId: + description: Site UUID. + type: str + macAddress: + description: MAC address. + type: str + markedForUninstall: + description: Is marked for uninstall. + type: bool + name: + description: Sensor name. + type: str + runNow: + description: Run now YES, NO. + type: str + sensorType: + description: Sensor type. + type: str + servicePolicy: + description: Service policy. + type: str + status: + description: Sensor device status UP, DOWN, REBOOT. + type: str + switchMac: + description: Switch MAC address. + type: str + switchSerialNumber: + description: Switch serial number. + type: str + switchUuid: + description: Switch device UUID. + type: str + targetAPs: + description: Array of target APs. + elements: str + type: list + testMacAddresses: + description: A string-string test MAC address. type: dict - scheduleRange: - description: Sensor Test Template Edit's scheduleRange. + wiredApplicationMessage: + description: Wired application message. + type: str + wiredApplicationStatus: + description: Wired application status. + type: str + xorSensor: + description: Is XOR sensor. + type: bool + type: list + showWlcUpgradeBanner: + description: Show WLC upgrade banner. + type: bool + siteHierarchy: + description: Site hierarchy. + type: str + ssids: + description: Sensor Test Template Edit's ssids. + elements: dict + suboptions: + authProtocol: + description: Auth protocol. + type: str + authType: + description: Authentication type OPEN, WPA2_PSK, WPA2_EAP, WEB_AUTH, MAB, DOT1X, + OTHER. + type: str + bands: + description: WIFI bands 2.4GHz or 5GHz. + type: str + certdownloadurl: + description: Certificate download URL. + type: str + certfilename: + description: Auth certificate file name. + type: str + certpassphrase: + description: Certificate password phrase. + type: str + certstatus: + description: Certificate status INACTIVE or ACTIVE. + type: str + certxferprotocol: + description: Certificate transfering protocol HTTP or HTTPS. + type: str + eapMethod: + description: WPA2_EAP methods EAP-FAST, PEAP-MSCHAPv2, EAP-TLS, PEAP-TLS, EAP-TTLS-MSCHAPv2, + EAP-TTLS-PAP, EAP-TTLS-CHAP, EAP-FAST-GTC, EAP-PEAP-GTC. + type: str + extWebAuth: + description: Indication of using external WEB Auth. + type: bool + extWebAuthAccessUrl: + description: External WEB Auth access URL. + type: str + extWebAuthHtmlTag: + description: Sensor Test Template Edit's extWebAuthHtmlTag. elements: dict suboptions: - day: - description: Day. + label: + description: Label. type: str - timeRange: - description: Sensor Test Template Edit's timeRange. + tag: + description: Tag. + type: str + value: + description: Value. + type: str + type: list + extWebAuthPortal: + description: External authentication portal. + type: str + extWebAuthVirtualIp: + description: External WEB Auth virtual IP. + type: str + id: + description: Identification number. + type: int + layer3webAuthEmailAddress: + description: Layer 3 WEB Auth email address. + type: str + layer3webAuthpassword: + description: Layer 3 WEB Auth password. + type: str + layer3webAuthsecurity: + description: Layer 3 WEB Auth security. + type: str + layer3webAuthuserName: + description: Layer 3 WEB Auth user name. + type: str + numAps: + description: Number of APs in the test. + type: int + numSensors: + description: Number of Sensors in the test. + type: int + password: + description: Password string for onboarding SSID. + type: str + passwordType: + description: SSID password type ASCII or HEX. + type: str + profileName: + description: The SSID profile name string. + type: str + proxyPassword: + description: Proxy server password. + type: str + proxyPort: + description: Proxy server port. + type: str + proxyServer: + description: Proxy server for onboarding SSID. + type: str + proxyUserName: + description: Proxy server user name. + type: str + psk: + description: Password of SSID when passwordType is ASCII. + type: str + qosPolicy: + description: QoS policy PlATINUM, GOLD, SILVER, BRONZE. + type: str + scep: + description: Secure certificate enrollment protocol true or false or null for + not applicable. + type: bool + ssid: + description: The SSID string. + type: str + status: + description: WLAN status ENABLED or DISABLED. + type: str + tests: + description: Sensor Test Template Edit's tests. + elements: dict + suboptions: + config: + description: Sensor Test Template Edit's config. elements: dict suboptions: - frequency: - description: Sensor Test Template Edit's frequency. - suboptions: - unit: - description: Unit. - type: str - value: - description: Value. - type: int - type: dict - from: - description: From. - type: str - to: - description: To. + direction: + description: IPerf direction (UPLOAD, DOWNLOAD, BOTH). + type: str + domains: + description: DNS domain name. + elements: str + type: list + downlinkTest: + description: Downlink test. + type: bool + endPort: + description: IPerf end port. + type: int + exitCommand: + description: Exit command. + type: str + finalPrompt: + description: Final prompt. + type: str + ndtServer: + description: NDT server. + type: str + ndtServerPath: + description: NDT server path. + type: str + ndtServerPort: + description: NDT server port. + type: str + numPackets: + description: Number of packets. + type: int + password: + description: Password. + type: str + passwordPrompt: + description: Password prompt. + type: str + pathToDownload: + description: File path for file transfer. + type: str + port: + description: Radius or WEB server port. + type: int + probeType: + description: Probe type. + type: str + protocol: + description: Protocol used by file transfer, IPerf, mail server, and + radius (TCP, UDP, FTP, POP3, IMAP, CHAP, PAP). + type: str + proxyPassword: + description: Proxy password. + type: str + proxyPort: + description: Proxy port. + type: str + proxyServer: + description: Proxy server. + type: str + proxyUserName: + description: Proxy user name. + type: str + server: + description: Ping, file transfer, mail, radius, ssh, or telnet server. + type: str + servers: + description: IPerf server list. + elements: str + type: list + sharedSecret: + description: Shared secret. + type: str + startPort: + description: IPerf start port. + type: int + transferType: + description: File transfer type (UPLOAD, DOWNLOAD, BOTH). + type: str + udpBandwidth: + description: IPerf UDP bandwidth. + type: int + uplinkTest: + description: Uplink test. + type: bool + url: + description: URL. + type: str + userName: + description: User name. + type: str + userNamePrompt: + description: User name prompt. type: str type: list + name: + description: Name of the test. + type: str type: list - testScheduleMode: - description: Test Schedule Mode. + thirdParty: + description: Sensor Test Template Edit's thirdParty. + suboptions: + selected: + description: True the SSID is third party. + type: bool + type: dict + username: + description: User name string for onboarding SSID. type: str - type: dict + validFrom: + description: Valid From UTC timestamp. + type: int + validTo: + description: Valid To UTC timestamp. + type: int + whiteList: + description: Indication of being on allowed list. + type: bool + wlanId: + description: WLAN ID. + type: int + wlc: + description: WLC IP addres. + type: str + type: list + startTime: + description: Start time. + type: int + status: + description: Status of the test (RUNNING, NOTRUNNING). + type: str templateName: - description: Template Name. + description: The test template name that is to be edited. + type: str + testScheduleMode: + description: Test schedule mode (ONDEMAND, DEDICATED, SCHEDULED, CONTINUOUS, RUNNOW). type: str + version: + description: The sensor test template version (must be 2). + type: int + wlans: + description: WLANs list. + elements: str + type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sensors EditSensorTestTemplate description: Complete reference of the EditSensorTestTemplate API. @@ -108,28 +692,218 @@ dnac_port: "{{dnac_port}}" dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" + _id: string + actionInProgress: string + apCoverage: + - bands: string + numberOfApsToTest: 0 + rssiThreshold: 0 + connection: string + encryptionMode: string + frequency: + unit: string + value: 0 + lastModifiedTime: 0 + location: string locationInfoList: - allSensors: true + customManagementVlan: true locationId: string locationType: string + macAddressList: + - string + managementVlan: string siteHierarchy: string - schedule: - frequency: - unit: string - value: 0 - scheduleRange: - - day: string - timeRange: - - frequency: - unit: string - value: 0 - from: string - to: string - testScheduleMode: string + modelVersion: 0 + name: string + numAssociatedSensor: 0 + numNeighborAPThreshold: 0 + profiles: + - authProtocol: string + authType: string + certdownloadurl: string + certfilename: string + certpassphrase: string + certstatus: string + certxferprotocol: string + deviceType: string + eapMethod: string + extWebAuth: true + extWebAuthAccessUrl: string + extWebAuthHtmlTag: + - label: string + tag: string + value: string + extWebAuthPortal: string + extWebAuthVirtualIp: string + locationVlanList: + - locationId: string + vlans: + - string + password: string + passwordType: string + profileName: string + psk: string + qosPolicy: string + scep: true + tests: + - config: + - direction: string + domains: + - string + downlinkTest: true + endPort: 0 + exitCommand: string + finalPrompt: string + ndtServer: string + ndtServerPath: string + ndtServerPort: string + numPackets: 0 + password: string + passwordPrompt: string + pathToDownload: string + port: 0 + probeType: string + protocol: string + proxyPassword: string + proxyPort: string + proxyServer: string + proxyUserName: string + server: string + servers: + - string + sharedSecret: string + startPort: 0 + transferType: string + udpBandwidth: 0 + uplinkTest: true + url: string + userName: string + userNamePrompt: string + name: string + username: string + vlan: string + whiteList: true + radioAsSensorRemoved: true + rssiThreshold: 0 + runNow: string + scheduleInDays: 0 + sensors: + - allSensorAddition: true + assigned: true + configUpdated: string + hostName: string + iPerfInfo: {} + id: string + ipAddress: string + locationId: string + macAddress: string + markedForUninstall: true + name: string + runNow: string + sensorType: string + servicePolicy: string + status: string + switchMac: string + switchSerialNumber: string + switchUuid: string + targetAPs: + - string + testMacAddresses: {} + wiredApplicationMessage: string + wiredApplicationStatus: string + xorSensor: true + showWlcUpgradeBanner: true + siteHierarchy: string + ssids: + - authProtocol: string + authType: string + bands: string + certdownloadurl: string + certfilename: string + certpassphrase: string + certstatus: string + certxferprotocol: string + eapMethod: string + extWebAuth: true + extWebAuthAccessUrl: string + extWebAuthHtmlTag: + - label: string + tag: string + value: string + extWebAuthPortal: string + extWebAuthVirtualIp: string + id: 0 + layer3webAuthEmailAddress: string + layer3webAuthpassword: string + layer3webAuthsecurity: string + layer3webAuthuserName: string + numAps: 0 + numSensors: 0 + password: string + passwordType: string + profileName: string + proxyPassword: string + proxyPort: string + proxyServer: string + proxyUserName: string + psk: string + qosPolicy: string + scep: true + ssid: string + status: string + tests: + - config: + - direction: string + domains: + - string + downlinkTest: true + endPort: 0 + exitCommand: string + finalPrompt: string + ndtServer: string + ndtServerPath: string + ndtServerPort: string + numPackets: 0 + password: string + passwordPrompt: string + pathToDownload: string + port: 0 + probeType: string + protocol: string + proxyPassword: string + proxyPort: string + proxyServer: string + proxyUserName: string + server: string + servers: + - string + sharedSecret: string + startPort: 0 + transferType: string + udpBandwidth: 0 + uplinkTest: true + url: string + userName: string + userNamePrompt: string + name: string + thirdParty: + selected: true + username: string + validFrom: 0 + validTo: 0 + whiteList: true + wlanId: 0 + wlc: string + startTime: 0 + status: string templateName: string + testScheduleMode: string + version: 0 + wlans: + - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -139,71 +913,202 @@ { "version": "string", "response": { - "_id": "string", "name": "string", + "_id": "string", "version": 0, "modelVersion": 0, "startTime": 0, "lastModifiedTime": 0, "numAssociatedSensor": 0, - "location": {}, - "siteHierarchy": {}, + "location": "string", + "siteHierarchy": "string", "status": "string", "connection": "string", - "frequency": {}, + "actionInProgress": "string", + "frequency": { + "value": 0, + "unit": "string" + }, "rssiThreshold": 0, "numNeighborAPThreshold": 0, "scheduleInDays": 0, "wlans": [ - {} + "string" ], "ssids": [ { - "bands": {}, + "bands": "string", "ssid": "string", "profileName": "string", - "authType": "string", - "authTypeRcvd": {}, - "psk": "string", - "username": {}, - "password": {}, - "eapMethod": {}, - "scep": true, - "authProtocol": {}, - "certfilename": {}, - "certxferprotocol": "string", - "certstatus": "string", - "certpassphrase": {}, - "certdownloadurl": {}, "numAps": 0, "numSensors": 0, - "layer3webAuthsecurity": {}, - "layer3webAuthuserName": {}, - "layer3webAuthpassword": {}, - "extWebAuthVirtualIp": {}, - "layer3webAuthEmailAddress": {}, - "qosPolicy": "string", - "extWebAuth": true, - "whiteList": true, - "extWebAuthPortal": {}, - "extWebAuthAccessUrl": {}, - "extWebAuthHtmlTag": [ - {} - ], + "layer3webAuthsecurity": "string", + "layer3webAuthuserName": "string", + "layer3webAuthpassword": "string", + "layer3webAuthEmailAddress": "string", "thirdParty": { "selected": true }, "id": 0, "wlanId": 0, - "wlc": {}, + "wlc": "string", "validFrom": 0, "validTo": 0, "status": "string", + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "authType": "string", + "psk": "string", + "username": "string", + "password": "string", + "passwordType": "string", + "eapMethod": "string", + "scep": true, + "authProtocol": "string", + "certfilename": "string", + "certxferprotocol": "string", + "certstatus": "string", + "certpassphrase": "string", + "certdownloadurl": "string", + "extWebAuthVirtualIp": "string", + "extWebAuth": true, + "whiteList": true, + "extWebAuthPortal": "string", + "extWebAuthAccessUrl": "string", + "extWebAuthHtmlTag": [ + { + "label": "string", + "tag": "string", + "value": "string" + } + ], + "qosPolicy": "string", + "tests": [ + { + "name": "string", + "config": [ + { + "domains": [ + "string" + ], + "server": "string", + "userName": "string", + "password": "string", + "url": "string", + "port": 0, + "protocol": "string", + "servers": [ + "string" + ], + "direction": "string", + "startPort": 0, + "endPort": 0, + "udpBandwidth": 0, + "probeType": "string", + "numPackets": 0, + "pathToDownload": "string", + "transferType": "string", + "sharedSecret": "string", + "ndtServer": "string", + "ndtServerPort": "string", + "ndtServerPath": "string", + "uplinkTest": true, + "downlinkTest": true, + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "userNamePrompt": "string", + "passwordPrompt": "string", + "exitCommand": "string", + "finalPrompt": "string" + } + ] + } + ] + } + ], + "profiles": [ + { + "authType": "string", + "psk": "string", + "username": "string", + "password": "string", + "passwordType": "string", + "eapMethod": "string", + "scep": true, + "authProtocol": "string", + "certfilename": "string", + "certxferprotocol": "string", + "certstatus": "string", + "certpassphrase": "string", + "certdownloadurl": "string", + "extWebAuthVirtualIp": "string", + "extWebAuth": true, + "whiteList": true, + "extWebAuthPortal": "string", + "extWebAuthAccessUrl": "string", + "extWebAuthHtmlTag": [ + { + "label": "string", + "tag": "string", + "value": "string" + } + ], + "qosPolicy": "string", "tests": [ { "name": "string", "config": [ - {} + { + "domains": [ + "string" + ], + "server": "string", + "userName": "string", + "password": "string", + "url": "string", + "port": 0, + "protocol": "string", + "servers": [ + "string" + ], + "direction": "string", + "startPort": 0, + "endPort": 0, + "udpBandwidth": 0, + "probeType": "string", + "numPackets": 0, + "pathToDownload": "string", + "transferType": "string", + "sharedSecret": "string", + "ndtServer": "string", + "ndtServerPort": "string", + "ndtServerPath": "string", + "uplinkTest": true, + "downlinkTest": true, + "proxyServer": "string", + "proxyPort": "string", + "proxyUserName": "string", + "proxyPassword": "string", + "userNamePrompt": "string", + "passwordPrompt": "string", + "exitCommand": "string", + "finalPrompt": "string" + } + ] + } + ], + "profileName": "string", + "deviceType": "string", + "vlan": "string", + "locationVlanList": [ + { + "locationId": "string", + "vlans": [ + "string" ] } ] @@ -221,36 +1126,40 @@ "allSensors": true, "siteHierarchy": "string", "macAddressList": [ - {} - ] + "string" + ], + "managementVlan": "string", + "customManagementVlan": true } ], - "schedule": { - "testScheduleMode": "string", - "scheduleRange": [ - { - "timeRange": [ - { - "from": "string", - "to": "string", - "frequency": { - "value": 0, - "unit": "string" - } - } - ], - "day": "string" - } - ], - "startTime": 0, - "frequency": { - "value": 0, - "unit": "string" - } - }, - "tests": {}, "sensors": [ - {} + { + "name": "string", + "macAddress": "string", + "switchMac": "string", + "switchUuid": "string", + "switchSerialNumber": "string", + "markedForUninstall": true, + "ipAddress": "string", + "hostName": "string", + "wiredApplicationStatus": "string", + "wiredApplicationMessage": "string", + "assigned": true, + "status": "string", + "xorSensor": true, + "targetAPs": [ + "string" + ], + "runNow": "string", + "locationId": "string", + "allSensorAddition": true, + "configUpdated": "string", + "sensorType": "string", + "testMacAddresses": {}, + "id": "string", + "servicePolicy": "string", + "iPerfInfo": {} + } ], "apCoverage": [ { @@ -258,11 +1167,7 @@ "numberOfApsToTest": 0, "rssiThreshold": 0 } - ], - "testDurationEstimate": 0, - "testTemplate": true, - "legacyTestSuite": true, - "tenantId": "string" + ] } } """ diff --git a/plugins/modules/service_provider_create.py b/plugins/modules/service_provider_create.py index 2ce62b6649..1947468f97 100644 --- a/plugins/modules/service_provider_create.py +++ b/plugins/modules/service_provider_create.py @@ -35,8 +35,8 @@ type: list type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings CreateSPProfile description: Complete reference of the CreateSPProfile API. @@ -67,7 +67,6 @@ wanProvider: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/service_provider_info.py b/plugins/modules/service_provider_info.py index d2bc282f39..2bd9156ed0 100644 --- a/plugins/modules/service_provider_info.py +++ b/plugins/modules/service_provider_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings GetServiceProviderDetails description: Complete reference of the GetServiceProviderDetails API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -64,7 +63,7 @@ "namespace": "string", "type": "string", "key": "string", - "version": "string", + "version": 0, "value": [ { "wanProvider": "string", @@ -77,6 +76,6 @@ "inheritedGroupName": "string" } ], - "version": 0 + "version": "string" } """ diff --git a/plugins/modules/service_provider_profile_delete.py b/plugins/modules/service_provider_profile_delete.py index 0d076885ea..9c37800af5 100644 --- a/plugins/modules/service_provider_profile_delete.py +++ b/plugins/modules/service_provider_profile_delete.py @@ -20,8 +20,8 @@ description: SpProfileName path parameter. Sp profile name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings DeleteSPProfile description: Complete reference of the DeleteSPProfile API. @@ -48,7 +48,6 @@ spProfileName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/service_provider_update.py b/plugins/modules/service_provider_update.py index 3ec3fcde9b..470f50d101 100644 --- a/plugins/modules/service_provider_update.py +++ b/plugins/modules/service_provider_update.py @@ -38,8 +38,8 @@ type: list type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings UpdateSPProfile description: Complete reference of the UpdateSPProfile API. @@ -71,7 +71,6 @@ wanProvider: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/service_provider_v2.py b/plugins/modules/service_provider_v2.py index 5dcf4f3676..d9286b506f 100644 --- a/plugins/modules/service_provider_v2.py +++ b/plugins/modules/service_provider_v2.py @@ -12,7 +12,7 @@ - Manage operations create and update of the resource Service Provider V2. - API to create Service Provider Profile QOS . - API to update Service Provider Profile QoS . -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -36,8 +36,8 @@ type: list type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings CreateSPProfileV2 description: Complete reference of the CreateSPProfileV2 API. @@ -91,7 +91,6 @@ wanProvider: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/service_provider_v2_info.py b/plugins/modules/service_provider_v2_info.py index 2641b9bdb1..ebeeac9999 100644 --- a/plugins/modules/service_provider_v2_info.py +++ b/plugins/modules/service_provider_v2_info.py @@ -11,7 +11,7 @@ description: - Get all Service Provider V2. - API to get Service Provider details QoS . -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings GetServiceProviderDetailsV2 description: Complete reference of the GetServiceProviderDetailsV2 API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/site_assign_credential.py b/plugins/modules/site_assign_credential.py index b21a5ca776..c5b68dc397 100644 --- a/plugins/modules/site_assign_credential.py +++ b/plugins/modules/site_assign_credential.py @@ -41,8 +41,8 @@ description: Snmp V3 Id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings AssignDeviceCredentialToSite description: Complete reference of the AssignDeviceCredentialToSite API. @@ -76,7 +76,6 @@ snmpV3Id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/site_assign_device.py b/plugins/modules/site_assign_device.py index 1c080cba4d..3b7bb354e3 100644 --- a/plugins/modules/site_assign_device.py +++ b/plugins/modules/site_assign_device.py @@ -28,7 +28,7 @@ description: SiteId path parameter. Site id to which site the device to assign. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/site_count_info.py b/plugins/modules/site_count_info.py index c4a5dbd961..44908d5752 100644 --- a/plugins/modules/site_count_info.py +++ b/plugins/modules/site_count_info.py @@ -10,7 +10,7 @@ short_description: Information module for Site Count description: - Get all Site Count. -- API to get site count. +- Get the site count of the specified site's sub-hierarchy inclusive of the provided site . version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -21,11 +21,11 @@ type: dict siteId: description: - - SiteId query parameter. Site id to retrieve site count. + - SiteId query parameter. Site instance UUID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sites GetSiteCount description: Complete reference of the GetSiteCount API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/site_count_v2_info.py b/plugins/modules/site_count_v2_info.py new file mode 100644 index 0000000000..0318cbbdc8 --- /dev/null +++ b/plugins/modules/site_count_v2_info.py @@ -0,0 +1,67 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: site_count_v2_info +short_description: Information module for Site Count V2 +description: +- Get all Site Count V2. +- Get the site count of the specified site's sub-hierarchy inclusive of the provided site . +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + id: + description: + - Id query parameter. Site instance UUID. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites GetSiteCountV2 + description: Complete reference of the GetSiteCountV2 API. + link: https://developer.cisco.com/docs/dna-center/#!get-site-count-v-2 +notes: + - SDK Method used are + sites.Sites.get_site_count_v2, + + - Paths used are + get /dna/intent/api/v2/site/count, + +""" + +EXAMPLES = r""" +- name: Get all Site Count V2 + cisco.dnac.site_count_v2_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + id: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": 0, + "version": "string" + } +""" diff --git a/plugins/modules/site_create.py b/plugins/modules/site_create.py index 6b690ac25d..730a0c2182 100644 --- a/plugins/modules/site_create.py +++ b/plugins/modules/site_create.py @@ -43,10 +43,10 @@ type: str latitude: description: Latitude coordinate of the building (eg 37.338). - type: int + type: float longitude: description: Longitude coordinate of the building (eg -121.832). - type: int + type: float name: description: Name of the building (eg building1). type: str @@ -59,13 +59,13 @@ suboptions: floorNumber: description: Floor number. (eg 5). - type: int + type: float height: description: Height of the floor. Unit of measure is ft. (eg 15). - type: int + type: float length: description: Length of the floor. Unit of measure is ft. (eg 100). - type: int + type: float name: description: Name of the floor (eg floor-1). type: str @@ -77,15 +77,15 @@ type: str width: description: Width of the floor. Unit of measure is ft. (eg 100). - type: int + type: float type: dict type: dict type: description: Type of site to create (eg area, building, floor). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sites CreateSite description: Complete reference of the CreateSite API. @@ -132,7 +132,6 @@ type: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/site_delete.py b/plugins/modules/site_delete.py index 6c52cc343a..8d7a8173bc 100644 --- a/plugins/modules/site_delete.py +++ b/plugins/modules/site_delete.py @@ -20,8 +20,8 @@ description: SiteId path parameter. Site id to which site details to be deleted. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sites DeleteSite description: Complete reference of the DeleteSite API. @@ -48,7 +48,6 @@ siteId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -57,7 +56,7 @@ sample: > { "executionId": "string", - "executionStatusURL": "string", + "executionStatusUrl": "string", "message": "string" } """ diff --git a/plugins/modules/site_design_floormap.py b/plugins/modules/site_design_floormap.py index 0948930f3a..3405dfe6e5 100644 --- a/plugins/modules/site_design_floormap.py +++ b/plugins/modules/site_design_floormap.py @@ -24,7 +24,7 @@ description: Site Design Floormap's payload type: dict requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/site_design_floormap_info.py b/plugins/modules/site_design_floormap_info.py index c427e42bb0..5606039021 100644 --- a/plugins/modules/site_design_floormap_info.py +++ b/plugins/modules/site_design_floormap_info.py @@ -26,7 +26,7 @@ - FloorId path parameter. Group Id of the specified floormap. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/site_health_info.py b/plugins/modules/site_health_info.py index cbb91dcd64..0ea75e2720 100644 --- a/plugins/modules/site_health_info.py +++ b/plugins/modules/site_health_info.py @@ -19,25 +19,25 @@ headers: description: Additional headers. type: dict - timestamp: - description: - - Timestamp query parameter. Epoch time(in milliseconds) when the Site Hierarchy data is required. - type: str siteType: description: - - SiteType query parameter. Type of the site to return. AREA or BUILDING. Default to AREA. + - SiteType query parameter. Site type AREA or BUILDING (case insensitive). type: str offset: description: - - Offset query parameter. The offset value, starting from 1, of the first returned site entry. Default is 1. - type: int + - Offset query parameter. Offset of the first returned data set entry (Multiple of 'limit' + 1). + type: float limit: description: - - Limit query parameter. The max number of sites in the returned data set. Default is 25, and max at 50. - type: int + - Limit query parameter. Max number of data entries in the returned data set 1,50. Default is 25. + type: float + timestamp: + description: + - Timestamp query parameter. Epoch time(in milliseconds) when the Site Hierarchy data is required. + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sites GetSiteHealth description: Complete reference of the GetSiteHealth API. @@ -62,14 +62,13 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" - timestamp: string siteType: string offset: 0 limit: 0 + timestamp: 0 register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -86,41 +85,62 @@ "siteType": "string", "latitude": 0, "longitude": 0, - "healthyNetworkDevicePercentage": {}, - "healthyClientsPercentage": {}, - "clientHealthWired": {}, - "clientHealthWireless": {}, - "numberOfClients": {}, - "numberOfNetworkDevice": {}, - "networkHealthAverage": {}, - "networkHealthAccess": {}, - "networkHealthCore": {}, - "networkHealthDistribution": {}, - "networkHealthRouter": {}, - "networkHealthWireless": {}, - "networkHealthOthers": {}, - "numberOfWiredClients": {}, - "numberOfWirelessClients": {}, - "totalNumberOfConnectedWiredClients": {}, - "totalNumberOfActiveWirelessClients": {}, - "wiredGoodClients": {}, - "wirelessGoodClients": {}, - "overallGoodDevices": {}, - "accessGoodCount": {}, - "accessTotalCount": {}, - "coreGoodCount": {}, - "coreTotalCount": {}, - "distributionGoodCount": {}, - "distributionTotalCount": {}, - "routerGoodCount": {}, - "routerTotalCount": {}, - "wirelessDeviceGoodCount": {}, - "wirelessDeviceTotalCount": {}, - "applicationHealth": {}, - "applicationGoodCount": {}, - "applicationTotalCount": {}, - "applicationBytesTotalCount": {}, - "dnacInfo": {}, + "healthyNetworkDevicePercentage": 0, + "healthyClientsPercentage": 0, + "clientHealthWired": 0, + "clientHealthWireless": 0, + "numberOfClients": 0, + "numberOfNetworkDevice": 0, + "networkHealthAverage": 0, + "networkHealthAccess": 0, + "networkHealthCore": 0, + "networkHealthDistribution": 0, + "networkHealthRouter": 0, + "networkHealthWireless": 0, + "networkHealthAP": 0, + "networkHealthWLC": 0, + "networkHealthSwitch": 0, + "networkHealthOthers": 0, + "numberOfWiredClients": 0, + "numberOfWirelessClients": 0, + "totalNumberOfConnectedWiredClients": 0, + "totalNumberOfActiveWirelessClients": 0, + "wiredGoodClients": 0, + "wirelessGoodClients": 0, + "overallGoodDevices": 0, + "accessGoodCount": 0, + "accessTotalCount": 0, + "coreGoodCount": 0, + "coreTotalCount": 0, + "distributionGoodCount": 0, + "distributionTotalCount": 0, + "routerGoodCount": 0, + "routerTotalCount": 0, + "wirelessDeviceGoodCount": 0, + "wirelessDeviceTotalCount": 0, + "apDeviceGoodCount": 0, + "apDeviceTotalCount": 0, + "wlcDeviceGoodCount": 0, + "wlcDeviceTotalCount": 0, + "switchDeviceGoodCount": 0, + "switchDeviceTotalCount": 0, + "applicationHealth": 0, + "applicationHealthInfo": [ + { + "trafficClass": "string", + "bytesCount": 0, + "healthScore": 0 + } + ], + "applicationGoodCount": 0, + "applicationTotalCount": 0, + "applicationBytesTotalCount": 0, + "dnacInfo": { + "uuid": "string", + "ip": "string", + "status": "string" + }, + "usage": 0, "applicationHealthStats": { "appTotalCount": 0, "businessRelevantAppCount": { diff --git a/plugins/modules/site_info.py b/plugins/modules/site_info.py index be914d2e2c..e728b8b123 100644 --- a/plugins/modules/site_info.py +++ b/plugins/modules/site_info.py @@ -10,7 +10,7 @@ short_description: Information module for Site description: - Get all Site. -- Get site using siteNameHierarchy/siteId/type ,return all sites if these parameters are not given as input. +- Get sites by site-name-hierarchy or siteId or type. List all sites if these parameters are not given as an input. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -21,27 +21,27 @@ type: dict name: description: - - Name query parameter. SiteNameHierarchy (ex global/groupName). + - Name query parameter. Site name hierarchy (E.g Global/USA/CA). type: str siteId: description: - - SiteId query parameter. Site id to which site details to retrieve. + - SiteId query parameter. Site Id. type: str type: description: - - Type query parameter. Type (ex area, building, floor). + - Type query parameter. Site type (Ex area, building, floor). type: str offset: description: - - Offset query parameter. Offset/starting row. The default value is 1. + - Offset query parameter. Offset/starting index for pagination. Indexed from 1. type: int limit: description: - - Limit query parameter. Number of sites to be retrieved. The default value is 500. + - Limit query parameter. Number of sites to be listed. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sites GetSite description: Complete reference of the GetSite API. @@ -74,7 +74,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/site_intent.py b/plugins/modules/site_intent.py index 39d708730d..63af3d1920 100644 --- a/plugins/modules/site_intent.py +++ b/plugins/modules/site_intent.py @@ -342,6 +342,8 @@ class DnacSite(DnacBase): def __init__(self, module): super().__init__(module) self.supported_states = ["merged", "deleted"] + self.created_site_list, self.updated_site_list, self.update_not_neeeded_sites = [], [], [] + self.deleted_site_list, self.site_absent_list = [], [] def validate_input(self): """ @@ -449,7 +451,7 @@ def get_current_site(self, site): width=map_geometry.get("attributes").get("width"), length=map_geometry.get("attributes").get("length"), height=map_geometry.get("attributes").get("height"), - floorNumber=map_geometry.get("attributes").get("floor_number", "") + floorNumber=map_summary.get('attributes').get('floorIndex') ) ) @@ -666,7 +668,7 @@ def is_floor_updated(self, updated_site, requested_site): """ keys_to_compare = ['length', 'width', 'height'] - if updated_site['name'] != requested_site['name'] or updated_site['rf_model'] != requested_site['rfModel']: + if updated_site['name'] != requested_site['name'] or updated_site.get('rf_model') != requested_site.get('rfModel'): return False for key in keys_to_compare: @@ -781,6 +783,7 @@ def get_diff_merged(self, config): site_updated = False site_created = False + site_name = self.want.get("site_name") # check if the given site exists and/or needs to be updated/created. if self.have.get("site_exists"): @@ -795,14 +798,13 @@ def get_diff_merged(self, config): op_modifies=True, params=site_params, ) + self.log("Received API response from 'update_site': {0}".format(str(response)), "DEBUG") site_updated = True else: # Site does not neet update - self.result['response'] = self.have.get("current_site") - self.msg = "Site - {0} does not need any update".format(self.have.get("current_site")) - self.log(self.msg, "INFO") - self.result['msg'] = self.msg + self.update_not_neeeded_sites.append(site_name) + self.log("Site - {0} does not need any update".format(site_name), "INFO") return self else: @@ -817,9 +819,9 @@ def get_diff_merged(self, config): site_params['site']['building'] = building_details except Exception as e: site_type = site_params['type'] - site_name = site_params['site'][site_type]['name'] + name = site_params['site'][site_type]['name'] self.log("""The site '{0}' is not categorized as a building; hence, there is no need to filter out 'None' - values from the 'site_params' dictionary.""".format(site_name), "INFO") + values from the 'site_params' dictionary.""".format(name), "INFO") response = self.dnac._exec( family="sites", @@ -837,7 +839,6 @@ def get_diff_merged(self, config): execution_details = self.get_execution_details(executionid) if execution_details.get("status") == "SUCCESS": self.result['changed'] = True - self.result['response'] = execution_details break elif execution_details.get("bapiError"): @@ -846,21 +847,15 @@ def get_diff_merged(self, config): break if site_updated: - self.msg = "Site - {0} Updated Successfully".format(self.want.get("site_name")) - self.log(self.msg, "INFO") - self.result['msg'] = self.msg - self.result['response'].update({"siteId": self.have.get("site_id")}) - + self.updated_site_list.append(site_name) + self.log("Site - {0} Updated Successfully".format(site_name), "INFO") else: # Get the site id of the newly created site. (site_exists, current_site) = self.site_exists() if site_exists: - self.msg = "Site '{0}' created successfully".format(self.want.get("site_name")) - self.log(self.msg, "INFO") - self.log("Current site (have): {0}".format(str(current_site)), "DEBUG") - self.result['msg'] = self.msg - self.result['response'].update({"siteId": current_site.get('site_id')}) + self.created_site_list.append(site_name) + self.log("Site '{0}' created successfully".format(site_name), "INFO") return self @@ -895,11 +890,9 @@ def delete_single_site(self, site_id, site_name): while True: execution_details = self.get_execution_details(executionid) if execution_details.get("status") == "SUCCESS": - self.msg = "Site '{0}' deleted successfully".format(site_name) - self.result['changed'] = True - self.result['response'] = self.msg self.status = "success" - self.log(self.msg, "INFO") + self.deleted_site_list.append(site_name) + self.log("Site '{0}' deleted successfully".format(site_name), "INFO") break elif execution_details.get("bapiError"): self.log("Error response for 'delete_site' execution: {0}".format(execution_details.get("bapiError")), "ERROR") @@ -935,12 +928,8 @@ def get_diff_deleted(self, config): site_name = self.want.get("site_name") if not site_exists: self.status = "success" - self.msg = "Unable to delete site '{0}' as it's not found in Cisco Catalyst Center".format(site_name) - self.result.update({'changed': False, - 'response': self.msg, - 'msg': self.msg}) - self.log(self.msg, "INFO") - + self.site_absent_list.append(site_name) + self.log("Unable to delete site '{0}' as it's not found in Cisco Catalyst Center".format(site_name), "INFO") return self # Check here if the site have the childs then fetch it using get membership API and then sort it @@ -952,6 +941,7 @@ def get_diff_deleted(self, config): op_modifies=True, params={"site_id": site_id}, ) + self.log("Received API response from 'get_membership': {0}".format(str(mem_response)), "DEBUG") site_response = mem_response.get("site").get("response") self.log("Site {0} response along with it's child sites: {1}".format(site_name, str(site_response)), "DEBUG") @@ -968,9 +958,7 @@ def get_diff_deleted(self, config): # Delete the final parent site self.delete_single_site(site_id, site_name) - self.msg = "The site '{0}' and its child sites have been deleted successfully".format(site_name) - self.result['response'] = self.msg - self.log(self.msg, "INFO") + self.log("The site '{0}' and its child sites have been deleted successfully".format(site_name), "INFO") return self @@ -1044,6 +1032,63 @@ def verify_diff_deleted(self, config): return self + def update_site_messages(self): + """ + Update site messages based on the status of created, updated, and deleted sites. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + self (object): An instance of a class representing the status of the operation, including whether it was + successful or failed, any error messages encountered during operation. + Description: + This method updates the messages related to site creation, updating, and deletion in the Cisco Catalyst Center. + It evaluates the status of created sites, updated sites, and sites that are no longer needed for update to + determine the appropriate message to be set. The messages are then stored in the 'msg' attribute of the object. + """ + + if self.created_site_list and self.updated_site_list: + self.result['changed'] = True + if self.update_not_neeeded_sites: + msg = """Site(s) '{0}' created successfully as well as Site(s) '{1}' updated successully and the some site(s) + '{2}' needs no update in Cisco Catalyst Center""" + self.msg = msg.format(str(self.created_site_list), str(self.updated_site_list), str(self.update_not_neeeded_sites)) + else: + self.msg = """Site(s) '{0}' created successfully in Cisco Catalyst Center as well as Site(s) '{1}' updated successully in + Cisco Catalyst Center""".format(str(self.created_site_list), str(self.updated_site_list)) + elif self.created_site_list: + self.result['changed'] = True + if self.update_not_neeeded_sites: + self.msg = """Site(s) '{0}' created successfully and some site(s) '{1}' not needs any update in Cisco Catalyst + Center.""".format(str(self.created_site_list), str(self.update_not_neeeded_sites)) + else: + self.msg = "Site(s) '{0}' created successfully in Cisco Catalyst Center.".format(str(self.created_site_list)) + elif self.updated_site_list: + self.result['changed'] = True + if self.update_not_neeeded_sites: + self.msg = """Site(s) '{0}' updated successfully and some site(s) '{1}' not needs any update in Cisco Catalyst + Center.""".format(str(self.updated_site_list), str(self.update_not_neeeded_sites)) + else: + self.msg = "Site(s) '{0}' updated successfully in Cisco Catalyst Center.".format(str(self.updated_site_list)) + elif self.update_not_neeeded_sites: + self.result['changed'] = False + self.msg = "Site(s) '{0}' not needs any update in Cisco Catalyst Center.".format(str(self.update_not_neeeded_sites)) + elif self.deleted_site_list and self.site_absent_list: + self.result['changed'] = True + self.msg = """Given site(s) '{0}' deleted successfully from Cisco Catalyst Center and unable to deleted some site(s) '{1}' as they + are not found in Cisco Catalyst Center.""".format(str(self.deleted_site_list), str(self.site_absent_list)) + elif self.deleted_site_list: + self.result['changed'] = True + self.msg = "Given site(s) '{0}' deleted successfully from Cisco Catalyst Center".format(str(self.deleted_site_list)) + else: + self.result['changed'] = False + self.msg = "Unable to delete site(s) '{0}' as it's not found in Cisco Catalyst Center.".format(str(self.site_absent_list)) + + self.status = "success" + self.result['response'] = self.msg + self.result['msg'] = self.msg + + return self + def main(): """ main entry point for module execution @@ -1090,6 +1135,9 @@ def main(): if config_verify: dnac_site.verify_diff_state_apply[state](config).check_return_status() + # Invoke the API to check the status and log the output of each site on the console + dnac_site.update_site_messages().check_return_status() + module.exit_json(**dnac_site.result) diff --git a/plugins/modules/site_membership_info.py b/plugins/modules/site_membership_info.py index bc28ba3f3b..70452cfd93 100644 --- a/plugins/modules/site_membership_info.py +++ b/plugins/modules/site_membership_info.py @@ -26,11 +26,11 @@ offset: description: - Offset query parameter. Offset/starting row. - type: int + type: float limit: description: - Limit query parameter. Number of sites to be retrieved. - type: int + type: float deviceFamily: description: - DeviceFamily query parameter. Device family name. @@ -40,8 +40,8 @@ - SerialNumber query parameter. Device serial number. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sites GetMembership description: Complete reference of the GetMembership API. @@ -74,7 +74,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/site_update.py b/plugins/modules/site_update.py index 86c54a60b8..a94359ef60 100644 --- a/plugins/modules/site_update.py +++ b/plugins/modules/site_update.py @@ -26,60 +26,68 @@ description: Site Update's area. suboptions: name: - description: Name. + description: Area name. type: str parentName: - description: Parent Name. + description: Parent hierarchical name (Example Global/USA/CA). type: str type: dict building: description: Site Update's building. suboptions: address: - description: Address. + description: Building address (Example 4900 Marie P. Debartolo Way, Santa + Clara, California 95054, United States). + type: str + country: + description: Country name. This field is mandatory for air-gapped networks + (Example United States). type: str latitude: - description: Latitude. - type: int + description: Building latitude (Example 37.403712). + type: float longitude: - description: Longitude. - type: int + description: Building longitude (Example -121.971063). + type: float name: - description: Name. + description: Building name. type: str parentName: - description: Parent Name. + description: Parent hierarchical name (Example Global/USA/CA/SantaClara). type: str type: dict floor: description: Site Update's floor. suboptions: + floorNumber: + description: Floor Number (Example 3). + type: float height: - description: Height. - type: int + description: Floor height in feet (Example 10). + type: float length: - description: Length. - type: int + description: Floor length in feet (Example 100). + type: float name: - description: Name. + description: Floor name. type: str rfModel: - description: Rf Model. + description: RF model (Example Cubes And Walled Offices). type: str width: - description: Width. - type: int + description: Floor width in feet (Example 200). + type: float type: dict type: dict siteId: description: SiteId path parameter. Site id to which site details to be updated. type: str type: - description: Type. + description: Site type. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Sites UpdateSite description: Complete reference of the UpdateSite API. @@ -110,11 +118,13 @@ parentName: string building: address: string + country: string latitude: 0 longitude: 0 name: string parentName: string floor: + floorNumber: 0 height: 0 length: 0 name: string @@ -124,7 +134,6 @@ type: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/site_v2_info.py b/plugins/modules/site_v2_info.py new file mode 100644 index 0000000000..267234579a --- /dev/null +++ b/plugins/modules/site_v2_info.py @@ -0,0 +1,112 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: site_v2_info +short_description: Information module for Site V2 +description: +- Get all Site V2. +- > + API to get sites by site-name-hierarchy or siteId or type. List all sites if these parameters are not given as an + input. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict + groupNameHierarchy: + description: + - GroupNameHierarchy query parameter. Site name hierarchy (E.g. Global/USA/CA). + type: str + id: + description: + - Id query parameter. Site Id. + type: str + type: + description: + - Type query parameter. Site type (Acceptable values area, building, floor). + type: str + offset: + description: + - Offset query parameter. Offset/starting index for pagination. + type: str + limit: + description: + - Limit query parameter. Number of sites to be listed. Default and max supported value is 500. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Sites GetSiteV2 + description: Complete reference of the GetSiteV2 API. + link: https://developer.cisco.com/docs/dna-center/#!get-site-v-2 +notes: + - SDK Method used are + sites.Sites.get_site_v2, + + - Paths used are + get /dna/intent/api/v2/site, + +""" + +EXAMPLES = r""" +- name: Get all Site V2 + cisco.dnac.site_v2_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + groupNameHierarchy: string + id: string + type: string + offset: string + limit: string + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: list + elements: dict + sample: > + [ + { + "parentId": "string", + "groupTypeList": [ + "string" + ], + "groupHierarchy": "string", + "additionalInfo": [ + { + "nameSpace": "string", + "attributes": { + "addressInheritedFrom": "string", + "type": "string", + "country": "string", + "address": "string", + "latitude": "string", + "longitude": "string" + } + } + ], + "groupNameHierarchy": "string", + "name": "string", + "instanceTenantId": "string", + "id": "string" + } + ] +""" diff --git a/plugins/modules/site_workflow_manager.py b/plugins/modules/site_workflow_manager.py index 81c6a974ec..1f17115b7a 100644 --- a/plugins/modules/site_workflow_manager.py +++ b/plugins/modules/site_workflow_manager.py @@ -342,6 +342,8 @@ class Site(DnacBase): def __init__(self, module): super().__init__(module) self.supported_states = ["merged", "deleted"] + self.created_site_list, self.updated_site_list, self.update_not_neeeded_sites = [], [], [] + self.deleted_site_list, self.site_absent_list = [], [] def validate_input(self): """ @@ -448,7 +450,7 @@ def get_current_site(self, site): width=map_geometry.get("attributes").get("width"), length=map_geometry.get("attributes").get("length"), height=map_geometry.get("attributes").get("height"), - floorNumber=map_geometry.get("attributes").get("floor_number", "") + floorNumber=map_summary.get('attributes').get('floorIndex') ) ) @@ -665,7 +667,9 @@ def is_floor_updated(self, updated_site, requested_site): """ keys_to_compare = ['length', 'width', 'height'] - if updated_site['name'] != requested_site['name'] or updated_site['rf_model'] != requested_site['rfModel']: + if updated_site['name'] != requested_site['name'] or updated_site.get('rf_model') != requested_site.get('rfModel'): + return False + if requested_site.get('floorNumber') and int(requested_site.get('floorNumber')) != int(updated_site.get('floorNumber')): return False for key in keys_to_compare: @@ -780,6 +784,7 @@ def get_diff_merged(self, config): site_updated = False site_created = False + site_name = self.want.get("site_name") # check if the given site exists and/or needs to be updated/created. if self.have.get("site_exists"): @@ -794,14 +799,12 @@ def get_diff_merged(self, config): op_modifies=True, params=site_params, ) + self.log("Received API response from 'update_site': {0}".format(str(response)), "DEBUG") site_updated = True - else: # Site does not neet update - self.result['response'] = self.have.get("current_site") - self.msg = "Site - {0} does not need any update".format(self.have.get("current_site")) - self.log(self.msg, "INFO") - self.result['msg'] = self.msg + self.update_not_neeeded_sites.append(site_name) + self.log("Site - {0} does not need any update".format(site_name), "INFO") return self else: @@ -816,9 +819,9 @@ def get_diff_merged(self, config): site_params['site']['building'] = building_details except Exception as e: site_type = site_params['type'] - site_name = site_params['site'][site_type]['name'] + name = site_params['site'][site_type]['name'] self.log("""The site '{0}' is not categorized as a building; hence, there is no need to filter out 'None' - values from the 'site_params' dictionary.""".format(site_name), "INFO") + values from the 'site_params' dictionary.""".format(name), "INFO") response = self.dnac._exec( family="sites", @@ -836,7 +839,6 @@ def get_diff_merged(self, config): execution_details = self.get_execution_details(executionid) if execution_details.get("status") == "SUCCESS": self.result['changed'] = True - self.result['response'] = execution_details break elif execution_details.get("bapiError"): @@ -845,21 +847,15 @@ def get_diff_merged(self, config): break if site_updated: - self.msg = "Site - {0} Updated Successfully".format(self.want.get("site_name")) - self.log(self.msg, "INFO") - self.result['msg'] = self.msg - self.result['response'].update({"siteId": self.have.get("site_id")}) - + self.updated_site_list.append(site_name) + self.log("Site - {0} Updated Successfully".format(site_name), "INFO") else: # Get the site id of the newly created site. (site_exists, current_site) = self.site_exists() if site_exists: - self.msg = "Site '{0}' created successfully".format(self.want.get("site_name")) - self.log(self.msg, "INFO") - self.log("Current site (have): {0}".format(str(current_site)), "DEBUG") - self.result['msg'] = self.msg - self.result['response'].update({"siteId": current_site.get('site_id')}) + self.created_site_list.append(site_name) + self.log("Site '{0}' created successfully".format(site_name), "INFO") return self @@ -894,11 +890,9 @@ def delete_single_site(self, site_id, site_name): while True: execution_details = self.get_execution_details(executionid) if execution_details.get("status") == "SUCCESS": - self.msg = "Site '{0}' deleted successfully".format(site_name) - self.result['changed'] = True - self.result['response'] = self.msg self.status = "success" - self.log(self.msg, "INFO") + self.deleted_site_list.append(site_name) + self.log("Site '{0}' deleted successfully".format(site_name), "INFO") break elif execution_details.get("bapiError"): self.log("Error response for 'delete_site' execution: {0}".format(execution_details.get("bapiError")), "ERROR") @@ -934,12 +928,8 @@ def get_diff_deleted(self, config): site_name = self.want.get("site_name") if not site_exists: self.status = "success" - self.msg = "Unable to delete site '{0}' as it's not found in Cisco Catalyst Center".format(site_name) - self.result.update({'changed': False, - 'response': self.msg, - 'msg': self.msg}) - self.log(self.msg, "INFO") - + self.site_absent_list.append(site_name) + self.log("Unable to delete site '{0}' as it's not found in Cisco Catalyst Center".format(site_name), "INFO") return self # Check here if the site have the childs then fetch it using get membership API and then sort it @@ -951,6 +941,7 @@ def get_diff_deleted(self, config): op_modifies=True, params={"site_id": site_id}, ) + self.log("Received API response from 'get_membership': {0}".format(str(mem_response)), "DEBUG") site_response = mem_response.get("site").get("response") self.log("Site {0} response along with it's child sites: {1}".format(site_name, str(site_response)), "DEBUG") @@ -967,9 +958,7 @@ def get_diff_deleted(self, config): # Delete the final parent site self.delete_single_site(site_id, site_name) - self.msg = "The site '{0}' and its child sites have been deleted successfully".format(site_name) - self.result['response'] = self.msg - self.log(self.msg, "INFO") + self.log("The site '{0}' and its child sites have been deleted successfully".format(site_name), "INFO") return self @@ -1043,6 +1032,63 @@ def verify_diff_deleted(self, config): return self + def update_site_messages(self): + """ + Update site messages based on the status of created, updated, and deleted sites. + Args: + self (object): An instance of a class used for interacting with Cisco Catalyst Center. + Returns: + self (object): An instance of a class representing the status of the operation, including whether it was + successful or failed, any error messages encountered during operation. + Description: + This method updates the messages related to site creation, updating, and deletion in the Cisco Catalyst Center. + It evaluates the status of created sites, updated sites, and sites that are no longer needed for update to + determine the appropriate message to be set. The messages are then stored in the 'msg' attribute of the object. + """ + + if self.created_site_list and self.updated_site_list: + self.result['changed'] = True + if self.update_not_neeeded_sites: + msg = """Site(s) '{0}' created successfully as well as Site(s) '{1}' updated successully and the some site(s) + '{2}' needs no update in Cisco Catalyst Center""" + self.msg = msg.format(str(self.created_site_list), str(self.updated_site_list), str(self.update_not_neeeded_sites)) + else: + self.msg = """Site(s) '{0}' created successfully in Cisco Catalyst Center as well as Site(s) '{1}' updated successully in + Cisco Catalyst Center""".format(str(self.created_site_list), str(self.updated_site_list)) + elif self.created_site_list: + self.result['changed'] = True + if self.update_not_neeeded_sites: + self.msg = """Site(s) '{0}' created successfully and some site(s) '{1}' not needs any update in Cisco Catalyst + Center.""".format(str(self.created_site_list), str(self.update_not_neeeded_sites)) + else: + self.msg = "Site(s) '{0}' created successfully in Cisco Catalyst Center.".format(str(self.created_site_list)) + elif self.updated_site_list: + self.result['changed'] = True + if self.update_not_neeeded_sites: + self.msg = """Site(s) '{0}' updated successfully and some site(s) '{1}' not needs any update in Cisco Catalyst + Center.""".format(str(self.updated_site_list), str(self.update_not_neeeded_sites)) + else: + self.msg = "Site(s) '{0}' updated successfully in Cisco Catalyst Center.".format(str(self.updated_site_list)) + elif self.update_not_neeeded_sites: + self.result['changed'] = False + self.msg = "Site(s) '{0}' not needs any update in Cisco Catalyst Center.".format(str(self.update_not_neeeded_sites)) + elif self.deleted_site_list and self.site_absent_list: + self.result['changed'] = True + self.msg = """Given site(s) '{0}' deleted successfully from Cisco Catalyst Center and unable to deleted some site(s) '{1}' as they + are not found in Cisco Catalyst Center.""".format(str(self.deleted_site_list), str(self.site_absent_list)) + elif self.deleted_site_list: + self.result['changed'] = True + self.msg = "Given site(s) '{0}' deleted successfully from Cisco Catalyst Center".format(str(self.deleted_site_list)) + else: + self.result['changed'] = False + self.msg = "Unable to delete site(s) '{0}' as it's not found in Cisco Catalyst Center.".format(str(self.site_absent_list)) + + self.status = "success" + self.result['response'] = self.msg + self.result['msg'] = self.msg + + return self + def main(): """ main entry point for module execution @@ -1089,6 +1135,9 @@ def main(): if config_verify: ccc_site.verify_diff_state_apply[state](config).check_return_status() + # Invoke the API to check the status and log the output of each site on the console + ccc_site.update_site_messages().check_return_status() + module.exit_json(**ccc_site.result) diff --git a/plugins/modules/snmp_properties.py b/plugins/modules/snmp_properties.py index 9cbcae16c1..0fce9c0aec 100644 --- a/plugins/modules/snmp_properties.py +++ b/plugins/modules/snmp_properties.py @@ -37,8 +37,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateUpdateSNMPProperties description: Complete reference of the CreateUpdateSNMPProperties API. @@ -71,7 +71,6 @@ systemPropertyName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/snmp_properties_info.py b/plugins/modules/snmp_properties_info.py index 4f32fd28d6..933cbc9299 100644 --- a/plugins/modules/snmp_properties_info.py +++ b/plugins/modules/snmp_properties_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery GetSNMPProperties description: Complete reference of the GetSNMPProperties API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/snmpv2_read_community_credential.py b/plugins/modules/snmpv2_read_community_credential.py index 0fd5ce8cb1..b3067d9e83 100644 --- a/plugins/modules/snmpv2_read_community_credential.py +++ b/plugins/modules/snmpv2_read_community_credential.py @@ -27,14 +27,14 @@ description: Name/Description of the credential. type: str instanceUuid: - description: Snmpv2 Read Community Credential's instanceUuid. + description: Credential UUID. type: str readCommunity: description: SNMP read community. NO!$DATA!$ for no value change. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateSNMPReadCommunity description: Complete reference of the CreateSNMPReadCommunity API. @@ -86,7 +86,6 @@ readCommunity: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/snmpv2_write_community_credential.py b/plugins/modules/snmpv2_write_community_credential.py index 00caf3e5bc..cef5534619 100644 --- a/plugins/modules/snmpv2_write_community_credential.py +++ b/plugins/modules/snmpv2_write_community_credential.py @@ -27,14 +27,14 @@ description: Name/Description of the credential. type: str instanceUuid: - description: Snmpv2 Write Community Credential's instanceUuid. + description: Credential UUID. type: str writeCommunity: description: SNMP write community. NO!$DATA!$ for no value change. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateSNMPWriteCommunity description: Complete reference of the CreateSNMPWriteCommunity API. @@ -86,7 +86,6 @@ writeCommunity: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/snmpv3_credential.py b/plugins/modules/snmpv3_credential.py index 705d9e507d..dd43a29d00 100644 --- a/plugins/modules/snmpv3_credential.py +++ b/plugins/modules/snmpv3_credential.py @@ -18,44 +18,44 @@ author: Rafael Campos (@racampos) options: authPassword: - description: Snmpv3 Credential's authPassword. + description: Auth Password for SNMP. type: str authType: - description: Snmpv3 Credential's authType. + description: SNMP auth protocol. 'SHA' or 'MD5'. type: str comments: - description: Snmpv3 Credential's comments. + description: Comments to identify the SNMPv3 credential. type: str credentialType: - description: Snmpv3 Credential's credentialType. + description: Credential type to identify the application that uses the SNMPv3 credential. type: str description: - description: Snmpv3 Credential's description. + description: Description for Snmp V3 Credential. type: str id: - description: Snmpv3 Credential's id. + description: Id of the SNMP V3 Credential in UUID format. type: str instanceTenantId: - description: Snmpv3 Credential's instanceTenantId. + description: Deprecated. type: str instanceUuid: - description: Snmpv3 Credential's instanceUuid. + description: Deprecated. type: str privacyPassword: - description: Snmpv3 Credential's privacyPassword. + description: Privacy Password for SNMP privacy. type: str privacyType: - description: Snmpv3 Credential's privacyType. + description: SNMP privacy protocol. type: str snmpMode: - description: Snmpv3 Credential's snmpMode. + description: Mode of SNMP. 'AUTHPRIV' or 'AUTHNOPRIV' or 'NOAUTHNOPRIV'. type: str username: - description: Snmpv3 Credential's username. + description: SNMP V3 Username. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Discovery CreateSNMPv3Credentials description: Complete reference of the CreateSNMPv3Credentials API. @@ -122,7 +122,6 @@ username: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/sp_profile_delete_v2.py b/plugins/modules/sp_profile_delete_v2.py index 236a0ba49a..df31ed1f94 100644 --- a/plugins/modules/sp_profile_delete_v2.py +++ b/plugins/modules/sp_profile_delete_v2.py @@ -11,17 +11,17 @@ description: - Manage operation delete of the resource Sp Profile Delete V2. - API to delete Service Provider Profile QoS . -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) options: spProfileName: - description: SpProfileName path parameter. Sp profile name. + description: SpProfileName path parameter. SP profile name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Network Settings DeleteSPProfileV2 description: Complete reference of the DeleteSPProfileV2 API. @@ -48,7 +48,6 @@ spProfileName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/swim_image_details_info.py b/plugins/modules/swim_image_details_info.py index d41519382c..1138286705 100644 --- a/plugins/modules/swim_image_details_info.py +++ b/plugins/modules/swim_image_details_info.py @@ -92,8 +92,8 @@ - Offset query parameter. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) GetSoftwareImageDetails description: Complete reference of the GetSoftwareImageDetails API. @@ -139,7 +139,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/swim_import_local.py b/plugins/modules/swim_import_local.py index 27966b4cdd..a8c0ba28aa 100644 --- a/plugins/modules/swim_import_local.py +++ b/plugins/modules/swim_import_local.py @@ -35,8 +35,8 @@ description: ThirdPartyVendor query parameter. Third Party Vendor. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) ImportLocalSoftwareImage description: Complete reference of the ImportLocalSoftwareImage API. @@ -67,7 +67,6 @@ thirdPartyVendor: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/swim_import_via_url.py b/plugins/modules/swim_import_via_url.py index df217a30c1..fdeb49ddaf 100644 --- a/plugins/modules/swim_import_via_url.py +++ b/plugins/modules/swim_import_via_url.py @@ -49,8 +49,8 @@ description: ScheduleOrigin query parameter. Originator of this call (Optional). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) ImportSoftwareImageViaURL description: Complete reference of the ImportSoftwareImageViaURL API. @@ -85,7 +85,6 @@ scheduleOrigin: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/swim_trigger_activation.py b/plugins/modules/swim_trigger_activation.py index 5d7cae2b54..41694e5d45 100644 --- a/plugins/modules/swim_trigger_activation.py +++ b/plugins/modules/swim_trigger_activation.py @@ -49,8 +49,8 @@ before schedule (Optional). type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) TriggerSoftwareImageActivation description: Complete reference of the TriggerSoftwareImageActivation API. @@ -87,7 +87,6 @@ scheduleValidate: true """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/swim_trigger_distribution.py b/plugins/modules/swim_trigger_distribution.py index ce1b5e1fc7..72ebad1622 100644 --- a/plugins/modules/swim_trigger_distribution.py +++ b/plugins/modules/swim_trigger_distribution.py @@ -30,8 +30,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Software Image Management (SWIM) TriggerSoftwareImageDistribution description: Complete reference of the TriggerSoftwareImageDistribution API. @@ -60,7 +60,6 @@ imageUuid: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/syslog_config_create.py b/plugins/modules/syslog_config_create.py index c4804a3b31..57c525fd60 100644 --- a/plugins/modules/syslog_config_create.py +++ b/plugins/modules/syslog_config_create.py @@ -35,7 +35,7 @@ description: Protocol. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management CreateSyslogDestination diff --git a/plugins/modules/syslog_config_update.py b/plugins/modules/syslog_config_update.py index 653555ac9f..6eeae91a0e 100644 --- a/plugins/modules/syslog_config_update.py +++ b/plugins/modules/syslog_config_update.py @@ -35,7 +35,7 @@ description: Protocol. type: str requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 seealso: - name: Cisco DNA Center documentation for Event Management UpdateSyslogDestination diff --git a/plugins/modules/system_health_count_info.py b/plugins/modules/system_health_count_info.py index bf9b723611..75eb45fdaa 100644 --- a/plugins/modules/system_health_count_info.py +++ b/plugins/modules/system_health_count_info.py @@ -32,8 +32,8 @@ here /dna/platform/app/consumer-portal/developer-toolkit/events. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemHealthCountAPI description: Complete reference of the SystemHealthCountAPI API. @@ -63,7 +63,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/system_health_info.py b/plugins/modules/system_health_info.py index 01a23ee641..eeab1aa40c 100644 --- a/plugins/modules/system_health_info.py +++ b/plugins/modules/system_health_info.py @@ -38,14 +38,14 @@ limit: description: - Limit query parameter. - type: int + type: float offset: description: - Offset query parameter. - type: int + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemHealthAPI description: Complete reference of the SystemHealthAPI API. @@ -78,7 +78,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/system_performance_historical_info.py b/plugins/modules/system_performance_historical_info.py index 11476ed6f0..68c365ef88 100644 --- a/plugins/modules/system_performance_historical_info.py +++ b/plugins/modules/system_performance_historical_info.py @@ -10,7 +10,10 @@ short_description: Information module for System Performance Historical description: - Get all System Performance Historical. -- This API retrieves the historical performance indicators. The data can be retrieved for the last 3 months. +- > + Retrieves the average values of cluster key performance indicators KPIs , like CPU utilization, memory utilization + or network rates grouped by time intervals within a specified time range. The data will be available from the past + 24 hours. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -28,16 +31,16 @@ - > StartTime query parameter. This is the epoch start time in milliseconds from which performance indicator need to be fetched. - type: int + type: float endTime: description: - > EndTime query parameter. This is the epoch end time in milliseconds upto which performance indicator need to be fetched. - type: int + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemPerformanceHistoricalAPI description: Complete reference of the SystemPerformanceHistoricalAPI API. @@ -68,7 +71,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -97,7 +99,9 @@ "t1": [ "string" ] - } + }, + "cpuAvg": "string", + "memoryAvg": "string" } } """ diff --git a/plugins/modules/system_performance_info.py b/plugins/modules/system_performance_info.py index 41b14ccdde..0be1b89d80 100644 --- a/plugins/modules/system_performance_info.py +++ b/plugins/modules/system_performance_info.py @@ -10,7 +10,10 @@ short_description: Information module for System Performance description: - Get all System Performance. -- This API gives the aggregated performance indicators. The data can be retrieved for the last 3 months. +- > + Retrieves the aggregated metrics total, average or maximum of cluster key performance indicators KPIs , such as + CPU utilization, memory utilization or network rates recorded within a specified time period. The data will be + available from the past 24 hours. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -32,16 +35,16 @@ - > StartTime query parameter. This is the epoch start time in milliseconds from which performance indicator need to be fetched. - type: int + type: float endTime: description: - > EndTime query parameter. This is the epoch end time in milliseconds upto which performance indicator need to be fetched. - type: int + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Health and Performance SystemPerformanceAPI description: Complete reference of the SystemPerformanceAPI API. @@ -73,7 +76,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/tag.py b/plugins/modules/tag.py index 0b26448c03..71589a303a 100644 --- a/plugins/modules/tag.py +++ b/plugins/modules/tag.py @@ -19,52 +19,59 @@ author: Rafael Campos (@racampos) options: description: - description: Tag's description. + description: Description of the tag. type: str dynamicRules: description: Tag's dynamicRules. elements: dict suboptions: memberType: - description: Tag's memberType. + description: MemberType of the tag (e.g. Networkdevice, interface). type: str rules: description: Tag's rules. suboptions: items: - description: Tag's items. - elements: str + description: Items details,multiple rules can be defined by items(e.g. "items" + {"operation" "ILIKE", "name" "managementIpAddress", "value" "%10%"}, {"operation" + "ILIKE", "name" "hostname", "value" "%NA%"} ). + elements: dict type: list name: - description: Tag's name. + description: Name of the parameter (e.g. For interface portName,adminStatus,speed,status,description. + For networkdevice family,series,hostname,managementIpAddress,groupNameHierarchy,softwareVersion). type: str operation: - description: Tag's operation. + description: Opeartion used in the rules (e.g. OR,IN,EQ,LIKE,ILIKE,AND). type: str value: - description: Tag's value. + description: Value of the parameter (e.g. For portName 1/0/1,for adminStatus,status + up/down, for speed any integer value, for description any valid string, + for family switches, for series C3650, for managementIpAddress 10.197.124.90, + groupNameHierarchy Global, softwareVersion 16.9.1). type: str values: - description: Tag's values. + description: Values of the parameter,Only one of the value or values can + be used for the given parameter. (for managementIpAddress e.g. "10.197.124.90","10.197.124.91"). elements: str type: list type: dict type: list id: - description: Tag's id. + description: Mandatory instanceUuid of the tag that needs to be updated. type: str instanceTenantId: - description: Tag's instanceTenantId. + description: InstanceTenantId generated for the tag. type: str name: - description: Tag's name. + description: Name of the tag. type: str systemTag: - description: SystemTag flag. + description: True for system created tags, false for user defined tags. type: bool requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Tag CreateTag description: Complete reference of the CreateTag API. @@ -104,7 +111,7 @@ - memberType: string rules: items: - - string + - {} name: string operation: string value: string @@ -129,7 +136,8 @@ dynamicRules: - memberType: string rules: - items: string + items: + - {} name: string operation: string value: string @@ -153,7 +161,6 @@ id: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/tag_count_info.py b/plugins/modules/tag_count_info.py index 7562f71fc6..9d5bfee5ba 100644 --- a/plugins/modules/tag_count_info.py +++ b/plugins/modules/tag_count_info.py @@ -31,10 +31,6 @@ description: - AttributeName query parameter. type: str - level: - description: - - Level query parameter. - type: str size: description: - Size query parameter. Size in kilobytes(KB). @@ -44,8 +40,8 @@ - SystemTag query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Tag GetTagCount description: Complete reference of the GetTagCount API. @@ -73,13 +69,11 @@ name: string nameSpace: string attributeName: string - level: string size: string systemTag: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/tag_info.py b/plugins/modules/tag_info.py index c7c32e7d56..bbc0372142 100644 --- a/plugins/modules/tag_info.py +++ b/plugins/modules/tag_info.py @@ -40,11 +40,11 @@ offset: description: - Offset query parameter. - type: int + type: float limit: description: - Limit query parameter. - type: int + type: float size: description: - Size query parameter. Size in kilobytes(KB). @@ -72,8 +72,8 @@ - Id path parameter. Tag ID. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Tag GetTag description: Complete reference of the GetTag API. @@ -130,7 +130,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -149,7 +148,9 @@ "values": [ "string" ], - "items": "string", + "items": [ + {} + ], "operation": "string", "name": "string", "value": "string" diff --git a/plugins/modules/tag_member.py b/plugins/modules/tag_member.py index 2ffe6ce106..b102c1d96e 100644 --- a/plugins/modules/tag_member.py +++ b/plugins/modules/tag_member.py @@ -23,15 +23,16 @@ memberId: description: MemberId path parameter. TagMember id to be removed from tag. type: str - object: - description: Object. - type: str + memberType: + description: Tag Member's memberType. + elements: str + type: list payload: description: Map of member type and member ids. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Tag AddMembersToTheTag description: Complete reference of the AddMembersToTheTag API. @@ -62,7 +63,8 @@ dnac_debug: "{{dnac_debug}}" state: present id: string - object: string + memberType: + - string payload: networkinterface: - string @@ -79,10 +81,8 @@ state: absent id: string memberId: string - memberType: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/tag_member_count_info.py b/plugins/modules/tag_member_count_info.py index 82dbf33d0c..192c359ff5 100644 --- a/plugins/modules/tag_member_count_info.py +++ b/plugins/modules/tag_member_count_info.py @@ -31,13 +31,9 @@ description: - MemberAssociationType query parameter. type: str - level: - description: - - Level query parameter. - type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Tag GetTagMemberCount description: Complete reference of the GetTagMemberCount API. @@ -64,12 +60,10 @@ headers: "{{my_headers | from_json}}" memberType: string memberAssociationType: string - level: string id: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/tag_member_info.py b/plugins/modules/tag_member_info.py index 57401f1529..d700a5c774 100644 --- a/plugins/modules/tag_member_info.py +++ b/plugins/modules/tag_member_info.py @@ -32,11 +32,11 @@ offset: description: - Offset query parameter. Used for pagination. It indicates the starting row number out of available member records. - type: str + type: float limit: description: - Limit query parameter. Used to Number of maximum members to return in the result. - type: str + type: float memberAssociationType: description: - > @@ -50,8 +50,8 @@ - Level query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Tag GetTagMembersById description: Complete reference of the GetTagMembersById API. @@ -77,15 +77,14 @@ dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" memberType: string - offset: string - limit: string + offset: 0 + limit: 0 memberAssociationType: string level: string id: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/tag_member_type_info.py b/plugins/modules/tag_member_type_info.py index a7e4cd1c93..c8a0f10652 100644 --- a/plugins/modules/tag_member_type_info.py +++ b/plugins/modules/tag_member_type_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Tag GetTagResourceTypes description: Complete reference of the GetTagResourceTypes API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/tag_membership.py b/plugins/modules/tag_membership.py index 9366e9ed2e..5c6e729c42 100644 --- a/plugins/modules/tag_membership.py +++ b/plugins/modules/tag_membership.py @@ -11,7 +11,7 @@ description: - Manage operation update of the resource Tag Membership. - > - Updates tag membership. As part of the request payload through this API, only the specified members are added / + Update tag membership. As part of the request payload through this API, only the specified members are added / retained to the given input tags. Possible values of memberType attribute in the request payload can be queried by using the /tag/member/type API. version_added: '3.1.0' @@ -21,26 +21,25 @@ options: memberToTags: description: Tag Membership's memberToTags. - elements: dict suboptions: key: description: Tag Membership's key. elements: str type: list - type: list + type: dict memberType: description: Tag Membership's memberType. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Tag UpdatesTagMembership - description: Complete reference of the UpdatesTagMembership API. - link: https://developer.cisco.com/docs/dna-center/#!updates-tag-membership +- name: Cisco DNA Center documentation for Tag UpdateTagMembership + description: Complete reference of the UpdateTagMembership API. + link: https://developer.cisco.com/docs/dna-center/#!update-tag-membership notes: - SDK Method used are - tag.Tag.updates_tag_membership, + tag.Tag.update_tag_membership, - Paths used are put /dna/intent/api/v1/tag/member, @@ -58,12 +57,11 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" memberToTags: - - key: + key: - string memberType: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/task_count_info.py b/plugins/modules/task_count_info.py index a1eedd4459..ca2aa0eb08 100644 --- a/plugins/modules/task_count_info.py +++ b/plugins/modules/task_count_info.py @@ -60,8 +60,8 @@ - ParentId query parameter. Fetch tasks that have this parent Id. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Task GetTaskCount description: Complete reference of the GetTaskCount API. @@ -99,7 +99,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/task_info.py b/plugins/modules/task_info.py index 9adaf195a4..3b76977687 100644 --- a/plugins/modules/task_info.py +++ b/plugins/modules/task_info.py @@ -82,8 +82,8 @@ - TaskId path parameter. UUID of the Task. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Task GetTaskById description: Complete reference of the GetTaskById API. @@ -143,7 +143,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/task_operation_info.py b/plugins/modules/task_operation_info.py index ea08f3306b..30c80cbc48 100644 --- a/plugins/modules/task_operation_info.py +++ b/plugins/modules/task_operation_info.py @@ -34,8 +34,8 @@ value is 1. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Task GetTaskByOperationId description: Complete reference of the GetTaskByOperationId API. @@ -66,7 +66,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -78,20 +77,20 @@ { "additionalStatusURL": "string", "data": "string", - "endTime": "string", + "endTime": 0, "errorCode": "string", "errorKey": "string", "failureReason": "string", "id": "string", "instanceTenantId": "string", "isError": true, - "lastUpdate": "string", + "lastUpdate": 0, "operationIdList": {}, "parentId": "string", "progress": "string", "rootId": "string", "serviceType": "string", - "startTime": "string", + "startTime": 0, "username": "string", "version": 0 } diff --git a/plugins/modules/task_tree_info.py b/plugins/modules/task_tree_info.py index 9e80665b34..334aa5b1eb 100644 --- a/plugins/modules/task_tree_info.py +++ b/plugins/modules/task_tree_info.py @@ -24,8 +24,8 @@ - TaskId path parameter. UUID of the Task. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Task GetTaskTree description: Complete reference of the GetTaskTree API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -66,20 +65,20 @@ { "additionalStatusURL": "string", "data": "string", - "endTime": "string", + "endTime": 0, "errorCode": "string", "errorKey": "string", "failureReason": "string", "id": "string", "instanceTenantId": "string", "isError": true, - "lastUpdate": "string", + "lastUpdate": 0, "operationIdList": {}, "parentId": "string", "progress": "string", "rootId": "string", "serviceType": "string", - "startTime": "string", + "startTime": 0, "username": "string", "version": 0 } diff --git a/plugins/modules/template_preview.py b/plugins/modules/template_preview.py index cb1657cccd..679f355842 100644 --- a/plugins/modules/template_preview.py +++ b/plugins/modules/template_preview.py @@ -29,8 +29,8 @@ description: UUID of template to get template preview. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates PreviewTemplate description: Complete reference of the PreviewTemplate API. @@ -60,7 +60,6 @@ templateId: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/template_workflow_manager.py b/plugins/modules/template_workflow_manager.py index fbd91685ea..4a123ed2b3 100644 --- a/plugins/modules/template_workflow_manager.py +++ b/plugins/modules/template_workflow_manager.py @@ -100,90 +100,6 @@ project_description: description: Narrative that elaborates on the purpose and scope of the project. type: str - rollback_template_params: - description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. - type: list - elements: dict - suboptions: - binding: - description: Associates the parameter with its source. - type: str - custom_order: - description: Specifies a user-defined ordering for the parameter. - type: int - data_type: - description: Identifies the data type of the parameter (e.g., string, integer, boolean). - type: str - default_value: - description: Establishes a default value for the parameter, used if no other value is provided. - type: str - description: - description: Provides a descriptive explanation of the parameter's purpose. - type: str - display_name: - description: The name of the parameter as displayed to users. - type: str - group: - description: Categorizes the parameter into a named group for organizational purposes. - type: str - id: - description: A unique identifier for the parameter, formatted as a UUID. - type: str - instruction_text: - description: Gives guidance or instructions regarding the parameter's use. - type: str - key: - description: A unique key that identifies the parameter within the template. - type: str - not_param: - description: Indicates whether the entry is not to be treated as a parameter. - type: bool - order: - description: Determines the sequence in which the parameter appears relative to others. - type: int - param_array: - description: Specifies if the parameter should be treated as an array. - type: bool - parameter_name: - description: The name of the parameter. - type: str - provider: - description: Denotes the provider associated with the parameter. - type: str - range: - description: Defines the permissible range for the parameter's value. - type: list - elements: dict - suboptions: - id: - description: Unique identifier for the range, represented as a UUID. - type: str - max_value: - description: Specifies the maximum allowable value for the parameter. - type: int - min_value: - description: Specifies the minimum allowable value for the parameter. - type: int - required: - description: Dictates whether the parameter is mandatory for template operations. - type: bool - selection: - description: Contains options for parameter selection when a choice is available. - suboptions: - default_selected_values: - description: Lists the default values that are preselected. - elements: str - type: list - id: - description: A unique identifier for the selection entity, represented as a UUID. - type: str - selection_type: - description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. - type: str - selection_values: - description: A dictionary of available values for selection. - type: dict - type: dict tags: description: A list of dictionaries representing tags associated with the Configuration Template during creation. suboptions: @@ -287,9 +203,6 @@ type: str type: list elements: dict - create_time: - description: The creation time of the template refers to the initial development. - type: int custom_params_order: description: Specifies the sequence in which custom parameters or variables should be arranged within the template. type: bool @@ -310,9 +223,6 @@ product_type: description: Describes the exact type of the device. type: str - failure_policy: - description: Define failure policy if template provisioning fails. - type: str id: description: A unique identifier, represented as a UUID. type: str @@ -322,114 +232,15 @@ - JINJA - VELOCITY type: str - last_update_time: - description: Indicates the most recent timestamp when the template was modified or revised. - type: int - latest_version_time: - description: Indicates when the most recent version of a template was released or updated. - type: int template_name: description: Name of template. This field is mandatory to create a new template. type: str - parent_template_id: - description: Refers to the unique identifier of a template from which another template derives. - type: str - project_id: - description: A unique identifier for the project, formatted as a UUID. - type: str project_name: description: Title of the project within which the template is categorized and managed. type: str project_description: description: Narrative that elaborates on the purpose and scope of the project. type: str - rollback_template_content: - description: Refers to the process of reverting the content of a template back to a previous version or state. - type: str - rollback_template_params: - description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. - suboptions: - binding: - description: Associates the parameter with its source. - type: str - custom_order: - description: Specifies a user-defined ordering for the parameter. - type: int - data_type: - description: Identifies the data type of the parameter (e.g., string, integer, boolean). - type: str - default_value: - description: Establishes a default value for the parameter, used if no other value is provided. - type: str - description: - description: Provides a descriptive explanation of the parameter's purpose. - type: str - display_name: - description: The name of the parameter as displayed to users. - type: str - group: - description: Categorizes the parameter into a named group for organizational purposes. - type: str - id: - description: A unique identifier for the parameter, formatted as a UUID. - type: str - instruction_text: - description: Gives guidance or instructions regarding the parameter's use. - type: str - key: - description: A unique key that identifies the parameter within the template. - type: str - not_param: - description: Indicates whether the entry is not to be treated as a parameter. - type: bool - order: - description: Determines the sequence in which the parameter appears relative to others. - type: int - param_array: - description: Specifies if the parameter should be treated as an array. - type: bool - parameter_name: - description: The name of the parameter. - type: str - provider: - description: Denotes the provider associated with the parameter. - type: str - range: - description: Defines the permissible range for the parameter's value. - suboptions: - id: - description: Unique identifier for the range, represented as a UUID. - type: str - max_value: - description: Specifies the maximum allowable value for the parameter. - type: int - min_value: - description: Specifies the minimum allowable value for the parameter. - type: int - type: list - elements: dict - required: - description: Dictates whether the parameter is mandatory for template operations. - type: bool - selection: - description: Contains options for parameter selection when a choice is available. - suboptions: - default_selected_values: - description: Lists the default values that are preselected. - elements: str - type: list - id: - description: A unique identifier for the selection entity, represented as a UUID. - type: str - selection_type: - description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. - type: str - selection_values: - description: A dictionary of available values for selection. - type: dict - type: dict - type: list - elements: dict software_type: description: Applicable device software type. This field is mandatory to create a new template. type: str @@ -537,24 +348,6 @@ type: dict type: list elements: dict - validation_errors: - description: Refer to issues or discrepancies identified during the validation process. - suboptions: - rollback_template_errors: - description: Validation or design conflicts errors of rollback template. - elements: dict - type: list - template_errors: - description: Refer to issues or discrepancies encountered during the processing of a template within a software application. - elements: dict - type: list - template_id: - description: A unique identifier for the template, represented as a UUID. - type: str - template_version: - description: The current version of validation process in the template. - type: str - type: dict version: description: The current version of template. type: str @@ -664,90 +457,6 @@ project_name: description: Title of the project within which the template is categorized and managed. type: str - rollback_template_params: - description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. - type: list - elements: dict - suboptions: - binding: - description: Associates the parameter with its source. - type: str - custom_order: - description: Specifies a user-defined ordering for the parameter. - type: int - data_type: - description: Identifies the data type of the parameter (e.g., string, integer, boolean). - type: str - default_value: - description: Establishes a default value for the parameter, used if no other value is provided. - type: str - description: - description: Provides a descriptive explanation of the parameter's purpose. - type: str - display_name: - description: The name of the parameter as displayed to users. - type: str - group: - description: Categorizes the parameter into a named group for organizational purposes. - type: str - id: - description: A unique identifier for the parameter, formatted as a UUID. - type: str - instruction_text: - description: Gives guidance or instructions regarding the parameter's use. - type: str - key: - description: A unique key that identifies the parameter within the template. - type: str - not_param: - description: Indicates whether the entry is not to be treated as a parameter. - type: bool - order: - description: Determines the sequence in which the parameter appears relative to others. - type: int - param_array: - description: Specifies if the parameter should be treated as an array. - type: bool - parameter_name: - description: The name of the parameter. - type: str - provider: - description: Denotes the provider associated with the parameter. - type: str - range: - description: Defines the permissible range for the parameter's value. - type: list - elements: dict - suboptions: - id: - description: Unique identifier for the range, represented as a UUID. - type: str - max_value: - description: Specifies the maximum allowable value for the parameter. - type: int - min_value: - description: Specifies the minimum allowable value for the parameter. - type: int - required: - description: Dictates whether the parameter is mandatory for template operations. - type: bool - selection: - description: Contains options for parameter selection when a choice is available. - suboptions: - default_selected_values: - description: Lists the default values that are preselected. - elements: str - type: list - id: - description: A unique identifier for the selection entity, represented as a UUID. - type: str - selection_type: - description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. - type: str - selection_values: - description: A dictionary of available values for selection. - type: dict - type: dict tags: description: A list of dictionaries representing tags associated with the Configuration Template during creation. suboptions: @@ -851,9 +560,6 @@ type: str type: list elements: dict - create_time: - description: The creation time of the template refers to the initial development. - type: int custom_params_order: description: Specifies the sequence in which custom parameters or variables should be arranged within the template. type: bool @@ -874,9 +580,6 @@ product_type: description: Describes the exact type of the device. type: str - failure_policy: - description: Define failure policy if template provisioning fails. - type: str id: description: A unique identifier, represented as a UUID. type: str @@ -886,114 +589,15 @@ - JINJA - VELOCITY type: str - last_update_time: - description: Indicates the most recent timestamp when the template was modified or revised. - type: int - latest_version_time: - description: Indicates when the most recent version of a template was released or updated. - type: int template_name: description: Name of template. This field is mandatory to create a new template. type: str - parent_template_id: - description: Refers to the unique identifier of a template from which another template derives. - type: str - project_id: - description: A unique identifier for the project, formatted as a UUID. - type: str project_name: description: Title of the project within which the template is categorized and managed. type: str project_description: description: Narrative that elaborates on the purpose and scope of the project. type: str - rollback_template_content: - description: Refers to the process of reverting the content of a template back to a previous version or state. - type: str - rollback_template_params: - description: A list of dictionaries defining parameters necessary for the rollback functionality of a template. - suboptions: - binding: - description: Associates the parameter with its source. - type: str - custom_order: - description: Specifies a user-defined ordering for the parameter. - type: int - data_type: - description: Identifies the data type of the parameter (e.g., string, integer, boolean). - type: str - default_value: - description: Establishes a default value for the parameter, used if no other value is provided. - type: str - description: - description: Provides a descriptive explanation of the parameter's purpose. - type: str - display_name: - description: The name of the parameter as displayed to users. - type: str - group: - description: Categorizes the parameter into a named group for organizational purposes. - type: str - id: - description: A unique identifier for the parameter, formatted as a UUID. - type: str - instruction_text: - description: Gives guidance or instructions regarding the parameter's use. - type: str - key: - description: A unique key that identifies the parameter within the template. - type: str - not_param: - description: Indicates whether the entry is not to be treated as a parameter. - type: bool - order: - description: Determines the sequence in which the parameter appears relative to others. - type: int - param_array: - description: Specifies if the parameter should be treated as an array. - type: bool - parameter_name: - description: The name of the parameter. - type: str - provider: - description: Denotes the provider associated with the parameter. - type: str - range: - description: Defines the permissible range for the parameter's value. - suboptions: - id: - description: Unique identifier for the range, represented as a UUID. - type: str - max_value: - description: Specifies the maximum allowable value for the parameter. - type: int - min_value: - description: Specifies the minimum allowable value for the parameter. - type: int - type: list - elements: dict - required: - description: Dictates whether the parameter is mandatory for template operations. - type: bool - selection: - description: Contains options for parameter selection when a choice is available. - suboptions: - default_selected_values: - description: Lists the default values that are preselected. - elements: str - type: list - id: - description: A unique identifier for the selection entity, represented as a UUID. - type: str - selection_type: - description: Specifies the type of selection, such as 'SINGLE_SELECT' or 'MULTI_SELECT'. - type: str - selection_values: - description: A dictionary of available values for selection. - type: dict - type: dict - type: list - elements: dict software_type: description: Applicable device software type. This field is mandatory to create a new template. type: str @@ -1101,24 +705,6 @@ type: dict type: list elements: dict - validation_errors: - description: Refer to issues or discrepancies identified during the validation process. - suboptions: - rollback_template_errors: - description: Refer to errors or issues encountered during the process of reverting a template to a previous version or state. - elements: dict - type: list - template_errors: - description: Refer to issues or discrepancies encountered during the processing of a template within a software application. - elements: dict - type: list - template_id: - description: A unique identifier for the template, represented as a UUID. - type: str - template_version: - description: The current version of validation process in the template. - type: str - type: dict version: description: The current version of template. type: str @@ -1128,7 +714,7 @@ type: str requirements: -- dnacentersdk == 2.4.5 +- dnacentersdk >= 2.4.5 - python >= 3.9 notes: - SDK Method used are @@ -1169,24 +755,17 @@ - configuration_templates: author: string composite: true - create_time: 0 custom_params_order: true description: string device_types: - product_family: string product_series: string product_type: string - failure_policy: string id: string language: string - last_update_time: 0 - latest_version_time: 0 name: string - parent_template_id: string - project_id: string project_name: string project_description: string - rollback_template_content: string software_type: string software_variant: string software_version: string @@ -1194,13 +773,6 @@ - id: string name: string template_content: string - validation_errors: - rollback_template_errors: - - {} - template_errors: - - {} - template_id: string - template_version: string version: string - name: Export the projects. @@ -1415,7 +987,6 @@ def validate_input(self): 'author': {'type': 'str'}, 'composite': {'type': 'bool'}, 'containing_templates': {'type': 'list'}, - 'create_time': {'type': 'int'}, 'custom_params_order': {'type': 'bool'}, 'template_description': {'type': 'str'}, 'device_types': { @@ -1425,25 +996,17 @@ def validate_input(self): 'product_series': {'type': 'str'}, 'product_type': {'type': 'str'}, }, - 'failure_policy': {'type': 'str'}, 'id': {'type': 'str'}, 'language': {'type': 'str'}, - 'last_update_time': {'type': 'int'}, - 'latest_version_time': {'type': 'int'}, 'name': {'type': 'str'}, - 'parent_template_id': {'type': 'str'}, - 'project_id': {'type': 'str'}, 'project_name': {'type': 'str'}, 'project_description': {'type': 'str'}, - 'rollback_template_content': {'type': 'str'}, - 'rollback_template_params': {'type': 'list'}, 'software_type': {'type': 'str'}, 'software_variant': {'type': 'str'}, 'software_version': {'type': 'str'}, 'template_content': {'type': 'str'}, 'template_params': {'type': 'list'}, 'template_name': {'type': 'str'}, - 'validation_errors': {'type': 'dict'}, 'version': {'type': 'str'} }, 'export': { @@ -1472,7 +1035,6 @@ def validate_input(self): 'author': {'type': 'str'}, 'composite': {'type': 'bool'}, 'containing_templates': {'type': 'list'}, - 'create_time': {'type': 'int'}, 'custom_params_order': {'type': 'bool'}, 'template_description': {'type': 'str'}, 'device_types': { @@ -1482,25 +1044,17 @@ def validate_input(self): 'product_series': {'type': 'str'}, 'product_type': {'type': 'str'}, }, - 'failure_policy': {'type': 'str'}, 'id': {'type': 'str'}, 'language': {'type': 'str'}, - 'last_update_time': {'type': 'int'}, - 'latest_version_time': {'type': 'int'}, 'name': {'type': 'str'}, - 'parent_template_id': {'type': 'str'}, - 'project_id': {'type': 'str'}, 'project_name': {'type': 'str'}, 'project_description': {'type': 'str'}, - 'rollback_template_content': {'type': 'str'}, - 'rollback_template_params': {'type': 'list'}, 'software_type': {'type': 'str'}, 'software_variant': {'type': 'str'}, 'software_version': {'type': 'str'}, 'template_content': {'type': 'str'}, 'template_params': {'type': 'list'}, 'template_name': {'type': 'str'}, - 'validation_errors': {'type': 'dict'}, 'version': {'type': 'str'} } } @@ -1611,47 +1165,6 @@ def get_device_types(self, device_types): return deviceTypes - def get_validation_errors(self, validation_errors): - """ - Store template parameters from the playbook for template processing in Cisco Catalyst Center. - - Parameters: - validation_errors (dict) - Playbook details containing validation errors information. - - Returns: - validationErrors (dict) - Organized validation errors parameters. - """ - - if validation_errors is None: - return None - - validationErrors = {} - rollback_template_errors = validation_errors.get("rollback_template_errors") - if rollback_template_errors is not None: - validationErrors.update({ - "rollbackTemplateErrors": rollback_template_errors - }) - - template_errors = validation_errors.get("template_errors") - if template_errors is not None: - validationErrors.update({ - "templateErrors": template_errors - }) - - template_id = validation_errors.get("template_id") - if template_id is not None: - validationErrors.update({ - "templateId": template_id - }) - - template_version = validation_errors.get("template_version") - if template_version is not None: - validationErrors.update({ - "templateVersion": template_version - }) - - return validationErrors - def get_template_info(self, template_params): """ Store template params from the playbook for template processing in Cisco Catalyst Center. @@ -1771,7 +1284,7 @@ def get_template_info(self, template_params): return self.check_return_status() min_value = value.get("min_value") if min_value is not None: - _range[j].update({"maxValue": min_value}) + _range[j].update({"minValue": min_value}) else: self.msg = "min_value is mandatory for range under template_params" self.status = "failed" @@ -1800,13 +1313,37 @@ def get_template_info(self, template_params): return templateParams + def get_templates_details(self, name): + """ + Get the template details from the template name provided in the playbook. + + Parameters: + name (str) - Name of the template provided in the playbook. + + Returns: + result (dict) - Template details for the given template name. + """ + + result = None + items = self.dnac_apply['exec']( + family="configuration_templates", + function="get_templates_details", + op_modifies=True, + params={"name": name} + ) + if items: + result = items + + self.log("Received API response from 'get_templates_details': {0}".format(items), "DEBUG") + return result + def get_containing_templates(self, containing_templates): """ Store tags from the playbook for template processing in Cisco Catalyst Center. Check using check_return_status() Parameters: - containing_templates (dict) - Containing tempaltes details + containing_templates (dict) - Containing templates details containing Template information. Returns: @@ -1838,10 +1375,6 @@ def get_containing_templates(self, containing_templates): "deviceTypes": self.get_device_types(device_types) }) - id = item.get("id") - if id is not None: - containingTemplates[i].update({"id": id}) - name = item.get("name") if name is None: self.msg = "name is mandatory under containing templates" @@ -1850,6 +1383,16 @@ def get_containing_templates(self, containing_templates): containingTemplates[i].update({"name": name}) + template_details = self.get_templates_details(name).get("response") + if not template_details: + self.msg = "No template with the template name '{0}' or it is not versioned".format(name) + self.status = "failed" + return self.check_return_status() + + id = template_details[0].get("id") + if id is not None: + containingTemplates[i].update({"id": id}) + language = item.get("language") if language is None: self.msg = "language is mandatory under containing templates" @@ -1865,19 +1408,12 @@ def get_containing_templates(self, containing_templates): containingTemplates[i].update({"language": language}) project_name = item.get("project_name") - if project_name is not None: - containingTemplates[i].update({"projectName": project_name}) - else: + if project_name is None: self.msg = "project_name is mandatory under containing templates" self.status = "failed" return self.check_return_status() - rollback_template_params = item.get("rollback_template_params") - if rollback_template_params is not None: - containingTemplates[i].update({ - "rollbackTemplateParams": self.get_template_info(rollback_template_params) - }) - + containingTemplates[i].update({"projectName": project_name}) template_content = item.get("template_content") if template_content is not None: containingTemplates[i].update({"templateContent": template_content}) @@ -1892,6 +1428,8 @@ def get_containing_templates(self, containing_templates): if version is not None: containingTemplates[i].update({"version": version}) + i += 1 + return containingTemplates def get_template_params(self, params): @@ -1912,29 +1450,17 @@ def get_template_params(self, params): "composite": params.get("composite"), "containingTemplates": self.get_containing_templates(params.get("containing_templates")), - "createTime": params.get("create_time"), "customParamsOrder": params.get("custom_params_order"), "description": params.get("template_description"), "deviceTypes": self.get_device_types(params.get("device_types")), - "failurePolicy": params.get("failure_policy"), "id": params.get("id"), - "lastUpdateTime": params.get("last_update_time"), - "latestVersionTime": params.get("latest_version_time"), - "parentTemplateId": params.get("parent_template_id"), - "projectId": params.get("project_id"), - "rollbackTemplateContent": params.get("rollback_template_content"), - "rollbackTemplateParams": - self.get_template_info(params.get("rollback_template_params")), "softwareVariant": params.get("software_variant"), "softwareVersion": params.get("software_version"), "templateContent": params.get("template_content"), "templateParams": self.get_template_info(params.get("template_params")), - "validationErrors": - self.get_validation_errors(params.get("validation_errors")), "version": params.get("version"), - "project_id": params.get("project_id") } language = params.get("language") if not language: @@ -2243,7 +1769,7 @@ def create_project_or_template(self, is_create_project=False): if task_details.get("isError"): self.log("Error occurred for '{0}' with taskid: {1}" .format(creation_value, task_id), "ERROR") - return creation_id, created + return task_id, created if validation_string not in task_details.get("progress"): self.log("'{0}' progress set to {1} for taskid: {2}" @@ -2298,27 +1824,18 @@ def requires_update(self): ("author", "author", ""), ("composite", "composite", False), ("containingTemplates", "containingTemplates", []), - ("createTime", "createTime", ""), ("customParamsOrder", "customParamsOrder", False), ("description", "description", ""), ("deviceTypes", "deviceTypes", []), - ("failurePolicy", "failurePolicy", ""), ("id", "id", ""), ("language", "language", "VELOCITY"), - ("lastUpdateTime", "lastUpdateTime", ""), - ("latestVersionTime", "latestVersionTime", ""), ("name", "name", ""), - ("parentTemplateId", "parentTemplateId", ""), - ("projectId", "projectId", ""), ("projectName", "projectName", ""), - ("rollbackTemplateContent", "rollbackTemplateContent", ""), - ("rollbackTemplateParams", "rollbackTemplateParams", []), ("softwareType", "softwareType", ""), ("softwareVariant", "softwareVariant", ""), ("softwareVersion", "softwareVersion", ""), ("templateContent", "templateContent", ""), ("templateParams", "templateParams", []), - ("validationErrors", "validationErrors", {}), ("version", "version", ""), ] @@ -2522,6 +2039,15 @@ def update_configuration_templates(self, configuration_templates): self.msg = "Error while versioning the template" self.status = "failed" return self + else: + task_details = self.get_task_details(template_id) + self.log('Getting task details from task ID {0}: {1}'.format(template_id, task_details), "DEBUG") + if task_details.get("failureReason"): + self.msg = str(task_details.get("failureReason")) + else: + self.msg = str(task_details.get("progress")) + self.status = "failed" + return self def handle_export(self, export): """ @@ -2683,6 +2209,17 @@ def handle_import(self, _import): } self.log("Import template details from the playbook: {0}" .format(import_template), "DEBUG") + global_project_name = import_template.get("project_name") + for item in import_template.get("payload"): + template_project_name = item.get("projectName") + if template_project_name is not None and \ + global_project_name != template_project_name: + self.msg = "Template '{0}' under the the 'Import Template' should have project_name as {1}" \ + .format(item.get("name"), global_project_name) + self.log(str(self.msg), "ERROR") + self.status = "failed" + return self + if _import_template: response = self.dnac._exec( family="configuration_templates", @@ -2807,8 +2344,11 @@ def get_diff_deleted(self, config): if is_template_found: self.delete_project_or_template(config) else: + self.result['response'][0].get("configurationTemplate").update({ + "msg": "Template with template_name '{0}' already deleted".format(templateName) + }) self.msg = "Invalid template {0} under project".format(templateName) - self.status = "failed" + self.status = "success" return self else: self.log("Template name is empty, deleting the project '{0}' and " @@ -2848,15 +2388,40 @@ def verify_diff_merged(self, config): return self self.get_have_template(config, is_template_available) - self.log("Current State (have): {0}".format(self.want.get("template_params")), "INFO") - self.log("Desired State (want): {0}".format(self.have_template.get("template")), "INFO") + self.log("Desired State (have): {0}".format(self.want.get("template_params")), "INFO") + self.log("Current State (want): {0}".format(self.have_template.get("template")), "INFO") + if not self.have_template.get("template"): + self.msg = "No template created with the name '{0}'".format(self.want.get("template_params").get("name")) + self.status = "failed" + return self + template_params = ["language", "name", "projectName", "softwareType", "softwareVariant", "templateContent"] + have_template = self.have_template.get("template") + want_template = self.want.get("template_params") for item in template_params: - if self.have_template.get("template").get(item) != self.want.get("template_params").get(item): - self.msg = "Configuration Template config is not applied to the Cisco Catalyst Center." + if have_template.get(item) != want_template.get(item): + self.msg = "Configuration Template config with template_name {0}'s '{1}' is not applied to the Cisco Catalyst Center." \ + .format(want_template.get("name"), item) + self.status = "failed" + return self + + want_template_containing_template = want_template.get("containingTemplates") + for item in want_template_containing_template: + name = item.get("name") + response = get_dict_result(have_template.get("containingTemplates"), "name", name) + if response is None: + self.msg = "Configuration Template config with template_name '{0}' under ".format(name) + \ + "'containing_templates' is not available in the Cisco Catalyst Center." self.status = "failed" return self + for value in item: + if item.get(value) != response.get(value): + self.msg = "Configuration Template config with template_name " + \ + "{0}'s '{1}' is not applied to the Cisco Catalyst Center.".format(name, value) + self.status = "failed" + return self + self.log("Successfully validated the Template in the Catalyst Center.", "INFO") self.result['response'][0].get("configurationTemplate").get("response").update({"Validation": "Success"}) diff --git a/plugins/modules/templates_details_info.py b/plugins/modules/templates_details_info.py index f2f45271cb..af205545c9 100644 --- a/plugins/modules/templates_details_info.py +++ b/plugins/modules/templates_details_info.py @@ -89,8 +89,8 @@ - Limit query parameter. Limits number of results. type: int requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Configuration Templates GetTemplatesDetails description: Complete reference of the GetTemplatesDetails API. @@ -135,7 +135,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/threat_detail.py b/plugins/modules/threat_detail.py index 0bcfac62c2..a7cd309ce2 100644 --- a/plugins/modules/threat_detail.py +++ b/plugins/modules/threat_detail.py @@ -44,7 +44,7 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/threat_detail_count.py b/plugins/modules/threat_detail_count.py index 7a21cd1ade..4b63e29b73 100644 --- a/plugins/modules/threat_detail_count.py +++ b/plugins/modules/threat_detail_count.py @@ -44,7 +44,7 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/threat_summary.py b/plugins/modules/threat_summary.py index 635b0c43c0..a8c1d7a4b0 100644 --- a/plugins/modules/threat_summary.py +++ b/plugins/modules/threat_summary.py @@ -35,7 +35,7 @@ elements: str type: list requirements: -- dnacentersdk >= 2.6.0 +- dnacentersdk >= 2.7.1 - python >= 3.9 notes: - SDK Method used are diff --git a/plugins/modules/topology_layer_2_info.py b/plugins/modules/topology_layer_2_info.py index 2ba3667e27..227062be57 100644 --- a/plugins/modules/topology_layer_2_info.py +++ b/plugins/modules/topology_layer_2_info.py @@ -24,8 +24,8 @@ - VlanID path parameter. Vlan Name for e.g Vlan1, Vlan23 etc. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Topology GetTopologyDetails description: Complete reference of the GetTopologyDetails API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/topology_layer_3_info.py b/plugins/modules/topology_layer_3_info.py index 008b5d1ac7..f7134cd678 100644 --- a/plugins/modules/topology_layer_3_info.py +++ b/plugins/modules/topology_layer_3_info.py @@ -24,8 +24,8 @@ - TopologyType path parameter. Type of topology(OSPF,ISIS,etc). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Topology GetL3TopologyDetails description: Complete reference of the GetL3TopologyDetails API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/topology_network_health_info.py b/plugins/modules/topology_network_health_info.py index b9c856316e..7faecb1e84 100644 --- a/plugins/modules/topology_network_health_info.py +++ b/plugins/modules/topology_network_health_info.py @@ -23,11 +23,11 @@ type: dict timestamp: description: - - Timestamp query parameter. Epoch time(in milliseconds) when the Network health data is required. - type: str + - Timestamp query parameter. UTC timestamp of network health data in milliseconds. + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Topology GetOverallNetworkHealth description: Complete reference of the GetOverallNetworkHealth API. @@ -52,11 +52,10 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" - timestamp: string + timestamp: 0 register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -71,20 +70,27 @@ "healthScore": 0, "totalCount": 0, "goodCount": 0, + "noHealthCount": 0, "unmonCount": 0, "fairCount": 0, "badCount": 0, - "entity": {}, + "maintenanceModeCount": 0, + "entity": "string", "timeinMillis": 0 } ], "measuredBy": "string", - "latestMeasuredByEntity": {}, + "latestMeasuredByEntity": "string", "latestHealthScore": 0, "monitoredDevices": 0, "monitoredHealthyDevices": 0, "monitoredUnHealthyDevices": 0, "unMonitoredDevices": 0, + "noHealthDevices": 0, + "totalDevices": 0, + "monitoredPoorHealthDevices": 0, + "monitoredFairHealthDevices": 0, + "healthContributingDevices": 0, "healthDistirubution": [ { "category": "string", @@ -93,13 +99,19 @@ "goodPercentage": 0, "badPercentage": 0, "fairPercentage": 0, + "noHealthPercentage": 0, "unmonPercentage": 0, "goodCount": 0, "badCount": 0, "fairCount": 0, + "noHealthCount": 0, "unmonCount": 0, + "thirdPartyDeviceCount": 0, "kpiMetrics": [ - {} + { + "key": "string", + "value": "string" + } ] } ] diff --git a/plugins/modules/topology_physical_info.py b/plugins/modules/topology_physical_info.py index 6a9573d577..4db9461e85 100644 --- a/plugins/modules/topology_physical_info.py +++ b/plugins/modules/topology_physical_info.py @@ -24,8 +24,8 @@ - NodeType query parameter. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Topology GetPhysicalTopology description: Complete reference of the GetPhysicalTopology API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/topology_site_info.py b/plugins/modules/topology_site_info.py index d63661b43b..d2b797a773 100644 --- a/plugins/modules/topology_site_info.py +++ b/plugins/modules/topology_site_info.py @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Topology GetSiteTopology description: Complete reference of the GetSiteTopology API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/topology_vlan_details_info.py b/plugins/modules/topology_vlan_details_info.py index 555b5b9d8c..0b14eeda28 100644 --- a/plugins/modules/topology_vlan_details_info.py +++ b/plugins/modules/topology_vlan_details_info.py @@ -10,7 +10,7 @@ short_description: Information module for Topology Vlan Details description: - Get all Topology Vlan Details. -- Returns the list of VLAN names. +- Returns the list of VLAN names that are involved in a loop as identified by the Spanning Tree Protocol. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info @@ -20,8 +20,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Topology GetVLANDetails description: Complete reference of the GetVLANDetails API. @@ -49,7 +49,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/transit_peer_network.py b/plugins/modules/transit_peer_network.py index 38125e4d35..42e9f7598d 100644 --- a/plugins/modules/transit_peer_network.py +++ b/plugins/modules/transit_peer_network.py @@ -12,7 +12,7 @@ - Manage operations create and delete of the resource Transit Peer Network. - Add Transit Peer Network in SD-Access. - Delete Transit Peer Network from SD-Access. -version_added: '6.5.0' +version_added: '6.0.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -21,7 +21,7 @@ description: Transit Peer Network's ipTransitSettings. suboptions: autonomousSystemNumber: - description: Autonomous System Number (e.g.,1-65535). + description: Autonomous System Number. type: str routingProtocolName: description: Routing Protocol Name. @@ -49,19 +49,19 @@ description: Transit Peer Network Type. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for AddTransitPeerNetwork +- name: Cisco DNA Center documentation for SDA AddTransitPeerNetwork description: Complete reference of the AddTransitPeerNetwork API. link: https://developer.cisco.com/docs/dna-center/#!add-transit-peer-network -- name: Cisco DNA Center documentation for DeleteTransitPeerNetwork +- name: Cisco DNA Center documentation for SDA DeleteTransitPeerNetwork description: Complete reference of the DeleteTransitPeerNetwork API. link: https://developer.cisco.com/docs/dna-center/#!delete-transit-peer-network notes: - SDK Method used are - ..add_transit_peer_network, - ..delete_transit_peer_network, + sda.Sda.add_transit_peer_network, + sda.Sda.delete_transit_peer_network, - Paths used are post /dna/intent/api/v1/business/sda/transit-peer-network, @@ -103,7 +103,6 @@ transitPeerNetworkType: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/transit_peer_network_info.py b/plugins/modules/transit_peer_network_info.py index 75ca07d7a7..e98d2288fe 100644 --- a/plugins/modules/transit_peer_network_info.py +++ b/plugins/modules/transit_peer_network_info.py @@ -11,7 +11,7 @@ description: - Get all Transit Peer Network. - Get Transit Peer Network Info from SD-Access. -version_added: '6.5.0' +version_added: '6.0.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -24,15 +24,15 @@ - TransitPeerNetworkName query parameter. Transit or Peer Network Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for GetTransitPeerNetworkInfo +- name: Cisco DNA Center documentation for SDA GetTransitPeerNetworkInfo description: Complete reference of the GetTransitPeerNetworkInfo API. link: https://developer.cisco.com/docs/dna-center/#!get-transit-peer-network-info notes: - SDK Method used are - ..get_transit_peer_network_info, + sda.Sda.get_transit_peer_network_info, - Paths used are get /dna/intent/api/v1/business/sda/transit-peer-network, @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/user.py b/plugins/modules/user.py index 4567de33dd..32809c4f9e 100644 --- a/plugins/modules/user.py +++ b/plugins/modules/user.py @@ -9,10 +9,11 @@ module: user short_description: Resource module for User description: -- Manage operations create and update of the resource User. -- Add a new user for Cisco DNA Center system. -- Update a user for Cisco DNA Center system. -version_added: '6.7.0' +- Manage operations create, update and delete of the resource User. +- Add a new user for Cisco DNA Center System. +- Delete a user from Cisco DNA Center System. +- Update a user for Cisco DNA Center System. +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -40,22 +41,27 @@ description: Username. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for User and Roles AddUserAPI description: Complete reference of the AddUserAPI API. link: https://developer.cisco.com/docs/dna-center/#!add-user-api +- name: Cisco DNA Center documentation for User and Roles DeleteUserAPI + description: Complete reference of the DeleteUserAPI API. + link: https://developer.cisco.com/docs/dna-center/#!delete-user-api - name: Cisco DNA Center documentation for User and Roles UpdateUserAPI description: Complete reference of the UpdateUserAPI API. link: https://developer.cisco.com/docs/dna-center/#!update-user-api notes: - SDK Method used are - user_and_roles.UserandRoles.add_user_ap_i, - user_and_roles.UserandRoles.update_user_ap_i, + userand_roles.UserandRoles.add_user_api, + userand_roles.UserandRoles.delete_user_api, + userand_roles.UserandRoles.update_user_api, - Paths used are post /dna/system/api/v1/user, + delete /dna/system/api/v1/user/{userId}, put /dna/system/api/v1/user, """ @@ -97,8 +103,19 @@ userId: string username: string -""" +- name: Delete by id + cisco.dnac.user: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + userId: string +""" RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/user_enrichment_details_info.py b/plugins/modules/user_enrichment_details_info.py index bcffca7466..84271957b1 100644 --- a/plugins/modules/user_enrichment_details_info.py +++ b/plugins/modules/user_enrichment_details_info.py @@ -22,8 +22,8 @@ description: Additional headers. type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Users GetUserEnrichmentDetails description: Complete reference of the GetUserEnrichmentDetails API. @@ -51,7 +51,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/user_info.py b/plugins/modules/user_info.py index d4c20af69a..94b3205d88 100644 --- a/plugins/modules/user_info.py +++ b/plugins/modules/user_info.py @@ -10,8 +10,8 @@ short_description: Information module for User description: - Get all User. -- Get all users for the Cisco DNA Center system. -version_added: '6.7.0' +- Get all users for the Cisco DNA Center System. +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -21,18 +21,26 @@ type: dict invokeSource: description: - - InvokeSource query parameter. The source that invokes this API. + - > + InvokeSource query parameter. The source that invokes this API. The value of this query parameter must be + set to "external". + type: str + authSource: + description: + - > + AuthSource query parameter. The source that authenticates the user. The value of this query parameter can be + set to "internal" or "external". If not provided, then all users will be returned in the response. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for User and Roles GetUsersAPI description: Complete reference of the GetUsersAPI API. link: https://developer.cisco.com/docs/dna-center/#!get-users-api notes: - SDK Method used are - user_and_roles.UserandRoles.get_users_api, + userand_roles.UserandRoles.get_users_api, - Paths used are get /dna/system/api/v1/user, @@ -51,10 +59,10 @@ dnac_debug: "{{dnac_debug}}" headers: "{{my_headers | from_json}}" invokeSource: string + authSource: string register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/users_external_authentication.py b/plugins/modules/users_external_authentication.py new file mode 100644 index 0000000000..f7cc5f3cf7 --- /dev/null +++ b/plugins/modules/users_external_authentication.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: users_external_authentication +short_description: Resource module for Users External Authentication +description: +- Manage operation create of the resource Users External Authentication. +- Enable or disable external authentication on Cisco DNA Center System. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + enable: + description: Enable/disable External Authentication. + type: bool +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for User and Roles ManageExternalAuthenticationSettingAPI + description: Complete reference of the ManageExternalAuthenticationSettingAPI API. + link: https://developer.cisco.com/docs/dna-center/#!manage-external-authentication-setting-api +notes: + - SDK Method used are + userand_roles.UserandRoles.manage_external_authentication_setting_api, + + - Paths used are + post /dna/system/api/v1/users/external-authentication, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.users_external_authentication: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + enable: true + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "message": "string" + } +""" diff --git a/plugins/modules/users_external_authentication_info.py b/plugins/modules/users_external_authentication_info.py new file mode 100644 index 0000000000..b4b93bb26b --- /dev/null +++ b/plugins/modules/users_external_authentication_info.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: users_external_authentication_info +short_description: Information module for Users External Authentication +description: +- Get all Users External Authentication. +- Get the External Authentication setting. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for User and Roles GetExternalAuthenticationSettingAPI + description: Complete reference of the GetExternalAuthenticationSettingAPI API. + link: https://developer.cisco.com/docs/dna-center/#!get-external-authentication-setting-api +notes: + - SDK Method used are + userand_roles.UserandRoles.get_external_authentication_setting_api, + + - Paths used are + get /dna/system/api/v1/users/external-authentication, + +""" + +EXAMPLES = r""" +- name: Get all Users External Authentication + cisco.dnac.users_external_authentication_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "external-authentication-flag": [ + { + "enabled": true + } + ] + } +""" diff --git a/plugins/modules/users_external_servers_aaa_attribute.py b/plugins/modules/users_external_servers_aaa_attribute.py new file mode 100644 index 0000000000..3dba589605 --- /dev/null +++ b/plugins/modules/users_external_servers_aaa_attribute.py @@ -0,0 +1,84 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: users_external_servers_aaa_attribute +short_description: Resource module for Users External Servers Aaa Attribute +description: +- Manage operations create and delete of the resource Users External Servers Aaa Attribute. +- > + Add or update the custom AAA attribute for external authentication. Note that if you decide not to set the custom + AAA attribute, a default AAA attribute will be used for authentication based on the protocol supported by your + server. For TACACS servers it will be "cisco-av-pair" and for RADIUS servers it will be "Cisco-AVPair". +- > + Delete the custom AAA attribute that was added. Note that by deleting the AAA attribute, a default AAA attribute + will be used for authentication based on the protocol supported by your server. For TACACS servers it will be + "cisco-av-pair" and for RADIUS servers it will be "Cisco-AVPair". +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + attributeName: + description: Name of the custom AAA attribute. + type: str +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for User and Roles AddAndUpdateAAAAttributeAPI + description: Complete reference of the AddAndUpdateAAAAttributeAPI API. + link: https://developer.cisco.com/docs/dna-center/#!add-and-update-aaa-attribute-api +- name: Cisco DNA Center documentation for User and Roles DeleteAAAAttributeAPI + description: Complete reference of the DeleteAAAAttributeAPI API. + link: https://developer.cisco.com/docs/dna-center/#!delete-aaa-attribute-api +notes: + - SDK Method used are + userand_roles.UserandRoles.add_and_update_a_a_a_attribute_api, + userand_roles.UserandRoles.delete_a_a_a_attribute_api, + + - Paths used are + post /dna/system/api/v1/users/external-servers/aaa-attribute, + delete /dna/system/api/v1/users/external-servers/aaa-attribute, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.users_external_servers_aaa_attribute: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: present + attributeName: string + +- name: Delete all + cisco.dnac.users_external_servers_aaa_attribute: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + state: absent + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "message": "string" + } +""" diff --git a/plugins/modules/users_external_servers_aaa_attribute_info.py b/plugins/modules/users_external_servers_aaa_attribute_info.py new file mode 100644 index 0000000000..e47e055c91 --- /dev/null +++ b/plugins/modules/users_external_servers_aaa_attribute_info.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: users_external_servers_aaa_attribute_info +short_description: Information module for Users External Servers Aaa Attribute +description: +- Get all Users External Servers Aaa Attribute. +- Get the current value of the custom AAA attribute. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module_info +author: Rafael Campos (@racampos) +options: + headers: + description: Additional headers. + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for User and Roles GetAAAAttributeAPI + description: Complete reference of the GetAAAAttributeAPI API. + link: https://developer.cisco.com/docs/dna-center/#!get-aaa-attribute-api +notes: + - SDK Method used are + userand_roles.UserandRoles.get_a_a_a_attribute_api, + + - Paths used are + get /dna/system/api/v1/users/external-servers/aaa-attribute, + +""" + +EXAMPLES = r""" +- name: Get all Users External Servers Aaa Attribute + cisco.dnac.users_external_servers_aaa_attribute_info: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + headers: "{{my_headers | from_json}}" + register: result + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "aaa-attributes": [ + { + "attributeName": "string" + } + ] + } +""" diff --git a/plugins/modules/users_external_servers_info.py b/plugins/modules/users_external_servers_info.py index 0373d2c859..4af30bcfdc 100644 --- a/plugins/modules/users_external_servers_info.py +++ b/plugins/modules/users_external_servers_info.py @@ -11,7 +11,7 @@ description: - Get all Users External Servers. - Get external users authentication servers. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -21,18 +21,20 @@ type: dict invokeSource: description: - - InvokeSource query parameter. The source that invokes this API. + - > + InvokeSource query parameter. The source that invokes this API. The value of this query parameter must be + set to "external". type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for User and Roles GetExternalAuthenticationServersAPI description: Complete reference of the GetExternalAuthenticationServersAPI API. link: https://developer.cisco.com/docs/dna-center/#!get-external-authentication-servers-api notes: - SDK Method used are - user_and_roles.UserandRoles.get_external_authentication_servers_ap_i, + userand_roles.UserandRoles.get_external_authentication_servers_api, - Paths used are get /dna/system/api/v1/users/external-servers, @@ -54,7 +56,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_accespoint_configuration.py b/plugins/modules/wireless_accespoint_configuration.py index 6a1cf29463..f3341b010c 100644 --- a/plugins/modules/wireless_accespoint_configuration.py +++ b/plugins/modules/wireless_accespoint_configuration.py @@ -10,8 +10,10 @@ short_description: Resource module for Wireless Accespoint Configuration description: - Manage operation create of the resource Wireless Accespoint Configuration. -- User can configure multiple access points with required options using this intent API. -version_added: '6.7.0' +- > + User can configure multiple access points with required options using this intent API. This API does not support + configuration of CleanAir or SI for IOS-XE devices with version greater than or equal to 17.9. +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module author: Rafael Campos (@racampos) @@ -20,10 +22,6 @@ description: Configure the access point's admin status. Set this parameter's value to "true" to enable it and "false" to disable it. type: bool - apHeight: - description: Configure the height of the access point by setting a value between - 3 and height of the floor. - type: int apList: description: Wireless Accespoint Configuration's apList. elements: dict @@ -47,10 +45,6 @@ description: To change the access point's admin status, set this parameter's value to "true". type: bool - configureApHeight: - description: To change the access point's height, set this parameter's value to - "true". - type: bool configureApMode: description: To change the access point's mode, set this parameter's value to "true". type: bool @@ -78,6 +72,10 @@ description: Configure the acess point's failover priority for low, set "1"; for medium, set "2"; for high, set "3"; and for critical, set "4". type: int + isAssignedSiteAsLocation: + description: If AP is assigned to a site, then to assign AP location as the site + name, set this parameter's value to "true". + type: bool ledBrightnessLevel: description: Configure the access point's LED brightness level by setting a value between 1 and 8. @@ -113,31 +111,19 @@ access point. If cable loss needs to be configured, set this parameter's value to "other". type: str - antennaDegree: - description: Configure the antenna degree on the specified radio for an access - point. - type: int - antennaElevAngleDegree: - description: Configure the antenna elevation angle on the specified radio for - an access point. - type: int - antennaElevAngleSign: - description: Configure the antenna elevation angle direction on the specified - radio for an access point for up, set "1"; for down, set "-1". - type: int antennaGain: description: Configure the antenna gain on the specified radio for an access - point by setting a decimal value (in dBi). + point by setting a decimal value (in dBi). To configure "antennaGain", set + "antennaPatternName" value to "other". type: int antennaPatternName: - description: Configure the antenna pattern name on the specified radio for an - access point. If antenna gain needs to be configured, set this parameter's - value to "other". + description: Specify the antenna name on the specified radio for an access point. + The antenna name is used to calculate the gain on the radio slot. type: str cableLoss: description: Configure the cable loss on the specified radio for an access point by setting a decimal value (in dBi). - type: int + type: float channelAssignmentMode: description: Configure the channel assignment mode on the specified radio for an access point for global mode, set "1"; and for custom mode, set "2". @@ -164,13 +150,9 @@ description: To change the antenna cable name on the specified radio for an access point, set this parameter's value to "true". type: bool - configureAntennaDegree: - description: To change the antenna degree on the specified radio for an access - point, set this parameter's value to "true". - type: bool configureAntennaPatternName: - description: To change the antenna pattern name on the specified radio for an - access point, set the value for this parameter to "true". + description: To change the antenna gain on the specified radio for an access + point, set the value for this parameter to "true". type: bool configureChannel: description: To change the channel on the specified radio for an access point, @@ -184,10 +166,6 @@ description: To enable or disable either CleanAir or Spectrum Intelligence on the specified radio for an access point, set this parameter's value to "true". type: bool - configureElevAngleDegree: - description: To change the elevation angle degree on the specified radio for - an access point, set this parameter's value to "true". - type: bool configurePower: description: To change the power assignment mode on the specified radio for an access point, set this parameter's value to "true". @@ -206,11 +184,13 @@ type: int radioBand: description: Configure the band on the specified radio for an access point for - 2.4 GHz, set "RADIO24"; for 5 GHz, set "RADIO5". + 2.4 GHz, set "RADIO24"; for 5 GHz, set "RADIO5". Any other string is invalid, + including empty string. type: str radioRoleAssignment: - description: Configure one of the following roles on the specified radio for - an access point "auto", "serving", or "monitor". + description: Configure only one of the following roles on the specified radio + for an access point as "AUTO", "SERVING", or "MONITOR". Any other string is + invalid, including empty string. type: str radioType: description: Configure an access point's radio band for 2.4 GHz, set "1"; for @@ -238,15 +218,15 @@ type: str type: dict requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: -- name: Cisco DNA Center documentation for Wireless ConfigureAccessPoints - description: Complete reference of the ConfigureAccessPoints API. - link: https://developer.cisco.com/docs/dna-center/#!configure-access-points +- name: Cisco DNA Center documentation for Wireless ConfigureAccessPointsV1 + description: Complete reference of the ConfigureAccessPointsV1 API. + link: https://developer.cisco.com/docs/dna-center/#!configure-access-points-v-1 notes: - SDK Method used are - wireless.Wireless.configure_access_points, + wireless.Wireless.configure_access_points_v1, - Paths used are post /dna/intent/api/v1/wireless/accesspoint-configuration, @@ -264,14 +244,12 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" adminStatus: true - apHeight: 0 apList: - apName: string apNameNew: string macAddress: string apMode: 0 configureAdminStatus: true - configureApHeight: true configureApMode: true configureFailoverPriority: true configureHAController: true @@ -279,6 +257,7 @@ configureLedStatus: true configureLocation: true failoverPriority: 0 + isAssignedSiteAsLocation: true ledBrightnessLevel: 0 ledStatus: true location: string @@ -288,9 +267,6 @@ radioConfigurations: - adminStatus: true antennaCableName: string - antennaDegree: 0 - antennaElevAngleDegree: 0 - antennaElevAngleSign: 0 antennaGain: 0 antennaPatternName: string cableLoss: 0 @@ -300,12 +276,10 @@ cleanAirSI: 0 configureAdminStatus: true configureAntennaCable: true - configureAntennaDegree: true configureAntennaPatternName: true configureChannel: true configureChannelWidth: true configureCleanAirSI: true - configureElevAngleDegree: true configurePower: true configureRadioRoleAssignment: true powerAssignmentMode: 0 @@ -321,7 +295,6 @@ address: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_accesspoint_configuration_create.py b/plugins/modules/wireless_accesspoint_configuration_create.py new file mode 100644 index 0000000000..dca07464a6 --- /dev/null +++ b/plugins/modules/wireless_accesspoint_configuration_create.py @@ -0,0 +1,328 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright (c) 2021, Cisco Systems +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +DOCUMENTATION = r""" +--- +module: wireless_accesspoint_configuration_create +short_description: Resource module for Wireless Accesspoint Configuration Create +description: +- Manage operation create of the resource Wireless Accesspoint Configuration Create. +- User can configure multiple access points with required options using this intent API. +version_added: '6.14.0' +extends_documentation_fragment: + - cisco.dnac.module +author: Rafael Campos (@racampos) +options: + adminStatus: + description: Configure the access point's admin status. Set this parameter's value + to "true" to enable it and "false" to disable it. + type: bool + apList: + description: Wireless Accesspoint Configuration Create's apList. + elements: dict + suboptions: + apName: + description: The current host name of the access point. + type: str + apNameNew: + description: The modified hostname of the access point. + type: str + macAddress: + description: The ethernet MAC address of the access point. + type: str + type: list + apMode: + description: Configure the access point's mode for local/flexconnect mode, set "0"; + for monitor mode, set "1"; for sniffer mode, set "4"; and for bridge/flex+bridge + mode, set "5". + type: int + cleanAirSI24: + description: Configure clean air status for radios that are in 2.4 Ghz band. Set + this parameter's value to "true" to enable it and "false" to disable it. + type: bool + cleanAirSI5: + description: Configure clean air status for radios that are in 5 Ghz band. Set this + parameter's value to "true" to enable it and "false" to disable it. + type: bool + cleanAirSI6: + description: Configure clean air status for radios that are in 6 Ghz band. Set this + parameter's value to "true" to enable it and "false" to disable it. + type: bool + configureAdminStatus: + description: To change the access point's admin status, set this parameter's value + to "true". + type: bool + configureApMode: + description: To change the access point's mode, set this parameter's value to "true". + type: bool + configureCleanAirSI24Ghz: + description: To change the clean air status for radios that are in 2.4 Ghz band, + set this parameter's value to "true". + type: bool + configureCleanAirSI5Ghz: + description: To change the clean air status for radios that are in 5 Ghz band, set + this parameter's value to "true". + type: bool + configureCleanAirSI6Ghz: + description: To change the clean air status for radios that are in 6 Ghz band, set + this parameter's value to "true". + type: bool + configureFailoverPriority: + description: To change the access point's failover priority, set this parameter's + value to "true". + type: bool + configureHAController: + description: To change the access point's HA controller, set this parameter's value + to "true". + type: bool + configureLedBrightnessLevel: + description: To change the access point's LED brightness level, set this parameter's + value to "true". + type: bool + configureLedStatus: + description: To change the access point's LED status, set this parameter's value + to "true". + type: bool + configureLocation: + description: To change the access point's location, set this parameter's value to + "true". + type: bool + failoverPriority: + description: Configure the acess point's failover priority for low, set "1"; for + medium, set "2"; for high, set "3"; and for critical, set "4". + type: int + isAssignedSiteAsLocation: + description: To configure the access point's location as the site assigned to the + access point, set this parameter's value to "true". + type: bool + ledBrightnessLevel: + description: Configure the access point's LED brightness level by setting a value + between 1 and 8. + type: int + ledStatus: + description: Configure the access point's LED status. Set "true" to enable its status + and "false" to disable it. + type: bool + location: + description: Configure the access point's location. + type: str + primaryControllerName: + description: Configure the hostname for an access point's primary controller. + type: str + primaryIpAddress: + description: Wireless Accesspoint Configuration Create's primaryIpAddress. + suboptions: + address: + description: Configure the IP address for an access point's primary controller. + type: str + type: dict + radioConfigurations: + description: Wireless Accesspoint Configuration Create's radioConfigurations. + elements: dict + suboptions: + adminStatus: + description: Configure the admin status on the specified radio for an access + point. Set this parameter's value to "true" to enable it and "false" to disable + it. + type: bool + antennaCableName: + description: Configure the antenna cable name on the specified radio for an + access point. If cable loss needs to be configured, set this parameter's value + to "other". + type: str + antennaGain: + description: Configure the antenna gain on the specified radio for an access + point by setting a decimal value (in dBi). To configure "antennaGain", set + "antennaPatternName" value to "other". + type: int + antennaPatternName: + description: Specify the antenna name on the specified radio for an access point. + The antenna name is used to calculate the gain on the radio slot. + type: str + cableLoss: + description: Configure the cable loss on the specified radio for an access point + by setting a decimal value (in dBi). + type: float + channelAssignmentMode: + description: Configure the channel assignment mode on the specified radio for + an access point for global mode, set "1"; and for custom mode, set "2". + type: int + channelNumber: + description: Configure the channel number on the specified radio for an access + point. + type: int + channelWidth: + description: Configure the channel width on the specified radio for an access + point for 20 MHz, set "3"; for 40 MHz, set "4"; for 80 MHz, set "5"; and for + 160 MHz, set "6". + type: int + configureAdminStatus: + description: To change the admin status on the specified radio for an access + point, set this parameter's value to "true". + type: bool + configureAntennaCable: + description: To change the antenna cable name on the specified radio for an + access point, set this parameter's value to "true". + type: bool + configureAntennaPatternName: + description: To change the antenna gain on the specified radio for an access + point, set the value for this parameter to "true". + type: bool + configureChannel: + description: To change the channel on the specified radio for an access point, + set this parameter's value to "true". + type: bool + configureChannelWidth: + description: To change the channel width on the specified radio for an access + point, set this parameter's value to "true". + type: bool + configurePower: + description: To change the power assignment mode on the specified radio for + an access point, set this parameter's value to "true". + type: bool + configureRadioRoleAssignment: + description: To change the radio role on the specified radio for an access point, + set this parameter's value to "true". + type: bool + powerAssignmentMode: + description: Configure the power assignment mode on the specified radio for + an access point for global mode, set "1"; and for custom mode, set "2". + type: int + powerlevel: + description: Configure the power level on the specified radio for an access + point by setting a value between 1 and 8. + type: int + radioBand: + description: Configure the band on the specified radio for an access point for + 2.4 GHz, set "RADIO24"; for 5 GHz, set "RADIO5". Any other string is invalid, + including empty string. + type: str + radioRoleAssignment: + description: Configure only one of the following roles on the specified radio + for an access point as "AUTO", "SERVING", or "MONITOR". Any other string is + invalid, including empty string. + type: str + radioType: + description: Configure an access point's radio band for 2.4 GHz, set "1"; for + 5 GHz, set "2"; for XOR, set "3"; and for 6 GHz, set "6". + type: int + type: list + secondaryControllerName: + description: Configure the hostname for an access point's secondary controller. + type: str + secondaryIpAddress: + description: Wireless Accesspoint Configuration Create's secondaryIpAddress. + suboptions: + address: + description: Configure the IP address for an access point's secondary controller. + type: str + type: dict + tertiaryControllerName: + description: Configure the hostname for an access point's tertiary controller. + type: str + tertiaryIpAddress: + description: Wireless Accesspoint Configuration Create's tertiaryIpAddress. + suboptions: + address: + description: Configure the IP address for an access point's tertiary controller. + type: str + type: dict +requirements: +- dnacentersdk >= 2.4.9 +- python >= 3.5 +seealso: +- name: Cisco DNA Center documentation for Wireless ConfigureAccessPointsV2 + description: Complete reference of the ConfigureAccessPointsV2 API. + link: https://developer.cisco.com/docs/dna-center/#!configure-access-points-v-2 +notes: + - SDK Method used are + wireless.Wireless.configure_access_points_v2, + + - Paths used are + post /dna/intent/api/v2/wireless/accesspoint-configuration, + +""" + +EXAMPLES = r""" +- name: Create + cisco.dnac.wireless_accesspoint_configuration_create: + dnac_host: "{{dnac_host}}" + dnac_username: "{{dnac_username}}" + dnac_password: "{{dnac_password}}" + dnac_verify: "{{dnac_verify}}" + dnac_port: "{{dnac_port}}" + dnac_version: "{{dnac_version}}" + dnac_debug: "{{dnac_debug}}" + adminStatus: true + apList: + - apName: string + apNameNew: string + macAddress: string + apMode: 0 + cleanAirSI24: true + cleanAirSI5: true + cleanAirSI6: true + configureAdminStatus: true + configureApMode: true + configureCleanAirSI24Ghz: true + configureCleanAirSI5Ghz: true + configureCleanAirSI6Ghz: true + configureFailoverPriority: true + configureHAController: true + configureLedBrightnessLevel: true + configureLedStatus: true + configureLocation: true + failoverPriority: 0 + isAssignedSiteAsLocation: true + ledBrightnessLevel: 0 + ledStatus: true + location: string + primaryControllerName: string + primaryIpAddress: + address: string + radioConfigurations: + - adminStatus: true + antennaCableName: string + antennaGain: 0 + antennaPatternName: string + cableLoss: 0 + channelAssignmentMode: 0 + channelNumber: 0 + channelWidth: 0 + configureAdminStatus: true + configureAntennaCable: true + configureAntennaPatternName: true + configureChannel: true + configureChannelWidth: true + configurePower: true + configureRadioRoleAssignment: true + powerAssignmentMode: 0 + powerlevel: 0 + radioBand: string + radioRoleAssignment: string + radioType: 0 + secondaryControllerName: string + secondaryIpAddress: + address: string + tertiaryControllerName: string + tertiaryIpAddress: + address: string + +""" +RETURN = r""" +dnac_response: + description: A dictionary or list with the response returned by the Cisco DNAC Python SDK + returned: always + type: dict + sample: > + { + "response": { + "taskId": "string", + "url": "string" + }, + "version": "string" + } +""" diff --git a/plugins/modules/wireless_accesspoint_configuration_summary_info.py b/plugins/modules/wireless_accesspoint_configuration_summary_info.py index ba43fe0526..931c663638 100644 --- a/plugins/modules/wireless_accesspoint_configuration_summary_info.py +++ b/plugins/modules/wireless_accesspoint_configuration_summary_info.py @@ -11,7 +11,7 @@ description: - Get all Wireless Accesspoint Configuration Summary. - Users can query the access point configuration information per device using the ethernet MAC address. -version_added: '6.7.0' +version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module_info author: Rafael Campos (@racampos) @@ -24,8 +24,8 @@ - Key query parameter. The ethernet MAC address of Access point. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless GetAccessPointConfiguration description: Complete reference of the GetAccessPointConfiguration API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_dynamic_interface.py b/plugins/modules/wireless_dynamic_interface.py index ed933a268b..133d26326e 100644 --- a/plugins/modules/wireless_dynamic_interface.py +++ b/plugins/modules/wireless_dynamic_interface.py @@ -21,14 +21,14 @@ description: Additional headers. type: dict interfaceName: - description: Dynamic-interface name. + description: InterfaceName query parameter. Valid interface-name to be deleted. type: str vlanId: description: Vlan Id. - type: int + type: float requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless CreateUpdateDynamicInterface description: Complete reference of the CreateUpdateDynamicInterface API. @@ -43,12 +43,12 @@ - Paths used are post /dna/intent/api/v1/wireless/dynamic-interface, - delete /dna/intent/api/v1/wireless/dynamic-interface/{interfaceName}, + delete /dna/intent/api/v1/wireless/dynamic-interface, """ EXAMPLES = r""" -- name: Create +- name: Delete all cisco.dnac.wireless_dynamic_interface: dnac_host: "{{dnac_host}}" dnac_username: "{{dnac_username}}" @@ -57,12 +57,11 @@ dnac_port: "{{dnac_port}}" dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" - state: present + state: absent headers: '{{my_headers | from_json}}' interfaceName: string - vlanId: 0 -- name: Delete by name +- name: Create cisco.dnac.wireless_dynamic_interface: dnac_host: "{{dnac_host}}" dnac_username: "{{dnac_username}}" @@ -71,23 +70,20 @@ dnac_port: "{{dnac_port}}" dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" - state: absent - headers: '{{my_headers | from_json}}' + state: present interfaceName: string + vlanId: 0 """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: list + type: dict sample: > - [ - { - "executionId": "string", - "executionUrl": "string", - "message": "string" - } - ] + { + "executionId": "string", + "executionStatusUrl": "string", + "message": "string" + } """ diff --git a/plugins/modules/wireless_dynamic_interface_info.py b/plugins/modules/wireless_dynamic_interface_info.py index 152b1c339e..d3191e1418 100644 --- a/plugins/modules/wireless_dynamic_interface_info.py +++ b/plugins/modules/wireless_dynamic_interface_info.py @@ -26,8 +26,8 @@ will be retrieved. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless GetDynamicInterface description: Complete reference of the GetDynamicInterface API. @@ -56,7 +56,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_enterprise_ssid.py b/plugins/modules/wireless_enterprise_ssid.py index f288aaada9..094de30842 100644 --- a/plugins/modules/wireless_enterprise_ssid.py +++ b/plugins/modules/wireless_enterprise_ssid.py @@ -18,20 +18,36 @@ - cisco.dnac.module author: Rafael Campos (@racampos) options: + aaaOverride: + description: Aaa Override. + type: bool + authKeyMgmt: + description: Takes string inputs for the AKMs that should be set true. Possible + AKM values dot1x,dot1x_ft, dot1x_sha, psk, psk_ft, psk_sha, owe, sae, sae_ft. + elements: str + type: list basicServiceSetClientIdleTimeout: - description: Basic Service Set Client Idle Timeout. + description: Basic Service Set Client Idle Timeout (Default 300 if enableBasicServiceSetMaxIdle + is true, 0 otherwise). type: int clientExclusionTimeout: - description: Client Exclusion Timeout. + description: Client Exclusion Timeout(Default 180 if enableClientExclusion is true, + 0 otherwise). type: int + clientRateLimit: + description: Client Rate Limit (in bits per second). + type: float + coverageHoleDetectionEnable: + description: Coverage Hole Detection Enable. + type: bool enableBasicServiceSetMaxIdle: - description: Enable Basic Service Set Max Idle. + description: Enable Basic Service Set Max Idle (Default true). type: bool enableBroadcastSSID: description: Enable Broadcase SSID. type: bool enableClientExclusion: - description: Enable Client Exclusion. + description: Enable Client Exclusion(Default true). type: bool enableDirectedMulticastService: description: Enable Directed Multicast Service. @@ -46,14 +62,34 @@ description: Enable Neighbor List. type: bool enableSessionTimeOut: - description: Enable Session Timeout. + description: Enable Session Timeout(Default true). type: bool fastTransition: description: Fast Transition. type: str + ghz24Policy: + description: Ghz24 Policy. + type: str + ghz6PolicyClientSteering: + description: Ghz6 Policy Client Steering. + type: bool mfpClientProtection: description: Management Frame Protection Client. type: str + multiPSKSettings: + description: Wireless Enterprise Ssid's multiPSKSettings. + elements: dict + suboptions: + passphrase: + description: Passphrase. + type: str + passphraseType: + description: Passphrase Type. + type: str + priority: + description: Priority. + type: int + type: list name: description: SSID NAME. type: str @@ -64,15 +100,34 @@ passphrase: description: Passphrase. type: str + policyProfileName: + description: Policy Profile Name. + type: str + profileName: + description: Profile Name. + type: str + protectedManagementFrame: + description: (Required applicable for Security Type WPA3_PERSONAL, WPA3_ENTERPRISE, + OPEN_SECURED) and (Optional, Required Applicable for Security Type WPA2_WPA3_PERSONAL + and WPA2_WPA3_ENTERPRISE). + type: str radioPolicy: - description: Radio Policy Enum (enum Triple band operation (2.4GHz, 5GHz and 6GHz), - Triple band operation with band select, 5GHz only, 2.4GHz only, 6GHz only). + description: Radio Policy Enum. type: str + rsnCipherSuiteCcmp256: + description: Rsn Cipher Suite Ccmp256. + type: bool + rsnCipherSuiteGcmp128: + description: Rsn Cipher Suite Gcmp 128. + type: bool + rsnCipherSuiteGcmp256: + description: Rsn Cipher Suite Gcmp256. + type: bool securityLevel: description: Security Level. type: str sessionTimeOut: - description: Session Time Out. + description: Session Time Out (Default 1800 if enableSessionTimeOut is true, 0 otherwise). type: int ssidName: description: SsidName path parameter. Enter the SSID name to be deleted. @@ -81,8 +136,8 @@ description: Traffic Type Enum (voicedata or data ). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless CreateEnterpriseSSID description: Complete reference of the CreateEnterpriseSSID API. @@ -117,8 +172,13 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" state: present + aaaOverride: true + authKeyMgmt: + - string basicServiceSetClientIdleTimeout: 0 clientExclusionTimeout: 0 + clientRateLimit: 0 + coverageHoleDetectionEnable: true enableBasicServiceSetMaxIdle: true enableBroadcastSSID: true enableClientExclusion: true @@ -128,12 +188,24 @@ enableNeighborList: true enableSessionTimeOut: true fastTransition: string + ghz24Policy: string + ghz6PolicyClientSteering: true mfpClientProtection: string + multiPSKSettings: + - passphrase: string + passphraseType: string + priority: 0 name: string nasOptions: - string passphrase: string + policyProfileName: string + profileName: string + protectedManagementFrame: string radioPolicy: string + rsnCipherSuiteCcmp256: true + rsnCipherSuiteGcmp128: true + rsnCipherSuiteGcmp256: true securityLevel: string sessionTimeOut: 0 trafficType: string @@ -148,8 +220,13 @@ dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" state: present + aaaOverride: true + authKeyMgmt: + - string basicServiceSetClientIdleTimeout: 0 clientExclusionTimeout: 0 + clientRateLimit: 0 + coverageHoleDetectionEnable: true enableBasicServiceSetMaxIdle: true enableBroadcastSSID: true enableClientExclusion: true @@ -159,12 +236,24 @@ enableNeighborList: true enableSessionTimeOut: true fastTransition: string + ghz24Policy: string + ghz6PolicyClientSteering: true mfpClientProtection: string + multiPSKSettings: + - passphrase: string + passphraseType: string + priority: 0 name: string nasOptions: - string passphrase: string + policyProfileName: string + profileName: string + protectedManagementFrame: string radioPolicy: string + rsnCipherSuiteCcmp256: true + rsnCipherSuiteGcmp128: true + rsnCipherSuiteGcmp256: true securityLevel: string sessionTimeOut: 0 trafficType: string @@ -182,7 +271,6 @@ ssidName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_enterprise_ssid_info.py b/plugins/modules/wireless_enterprise_ssid_info.py index b277d03bd2..158d9bdb92 100644 --- a/plugins/modules/wireless_enterprise_ssid_info.py +++ b/plugins/modules/wireless_enterprise_ssid_info.py @@ -26,8 +26,8 @@ enterprise SSIDs will be retrieved. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless GetEnterpriseSSID description: Complete reference of the GetEnterpriseSSID API. @@ -56,7 +56,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -96,7 +95,16 @@ "passphrase": "string" } ], - "clientRateLimit": 0 + "clientRateLimit": 0, + "enableSessionTimeOut": true, + "sessionTimeOut": 0, + "enableClientExclusion": true, + "clientExclusionTimeout": 0, + "enableBasicServiceSetMaxIdle": true, + "basicServiceSetClientIdleTimeout": 0, + "enableDirectedMulticastService": true, + "enableNeighborList": true, + "mfpClientProtection": "string" } ], "groupUuid": "string", diff --git a/plugins/modules/wireless_profile.py b/plugins/modules/wireless_profile.py index 7c837cca75..0a611b9c01 100644 --- a/plugins/modules/wireless_profile.py +++ b/plugins/modules/wireless_profile.py @@ -14,7 +14,8 @@ - Delete the Wireless Profile from Cisco DNA Center whose name is provided. - > Updates the wireless Network Profile with updated details provided. All sites to be present in the network profile - should be provided. + should be provided. This API has been deprecated. Please use the new endpoint URL + /dna/intent/api/v2/wireless/profile. version_added: '3.1.0' extends_documentation_fragment: - cisco.dnac.module @@ -51,14 +52,12 @@ description: Interface Name. type: str name: - description: Ssid Name. + description: Ssid Name is required if ssidDetails is passed in PayLoad for + mapping to the Network Profile. type: str policyProfileName: description: Policy Profile Name. type: str - type: - description: Ssid Type(enum Enterprise/Guest). - type: str wlanProfileName: description: WLAN Profile Name. type: str @@ -68,8 +67,8 @@ description: WirelessProfileName path parameter. Wireless Profile Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless CreateWirelessProfile description: Complete reference of the CreateWirelessProfile API. @@ -128,7 +127,6 @@ interfaceName: string name: string policyProfileName: string - type: string wlanProfileName: string - name: Create @@ -153,11 +151,9 @@ interfaceName: string name: string policyProfileName: string - type: string wlanProfileName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_profile_info.py b/plugins/modules/wireless_profile_info.py index fb175dedf6..7dcd2196f2 100644 --- a/plugins/modules/wireless_profile_info.py +++ b/plugins/modules/wireless_profile_info.py @@ -24,8 +24,8 @@ - ProfileName query parameter. Wireless Network Profile Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless GetWirelessProfile description: Complete reference of the GetWirelessProfile API. @@ -54,7 +54,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_provision_access_point.py b/plugins/modules/wireless_provision_access_point.py index d4651745fb..8bf6d4b63d 100644 --- a/plugins/modules/wireless_provision_access_point.py +++ b/plugins/modules/wireless_provision_access_point.py @@ -36,9 +36,6 @@ rfProfile: description: Radio frequency profile name. type: str - siteId: - description: Site name hierarchy(ex Global/...). - type: str siteNameHierarchy: description: Site name hierarchy(ex Global/...). type: str @@ -47,8 +44,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless APProvision description: Complete reference of the APProvision API. @@ -79,7 +76,6 @@ - string deviceName: string rfProfile: string - siteId: string siteNameHierarchy: string type: string @@ -92,7 +88,7 @@ sample: > { "executionId": "string", - "executionUrl": "string", + "executionStatusUrl": "string", "message": "string" } """ diff --git a/plugins/modules/wireless_provision_device_create.py b/plugins/modules/wireless_provision_device_create.py index 84622d9906..79dd393bc8 100644 --- a/plugins/modules/wireless_provision_device_create.py +++ b/plugins/modules/wireless_provision_device_create.py @@ -28,22 +28,22 @@ elements: dict suboptions: interfaceGateway: - description: Interface Gateway. + description: Interface Gateway. Required for AireOS. type: str interfaceIPAddress: - description: Interface IP Address. + description: Interface IP Address. Required for AireOS. type: str interfaceName: - description: Interface Name. + description: Interface Name. Required for both AireOS and EWLC. type: str interfaceNetmaskInCIDR: - description: Interface Netmask In CIDR. + description: Interface Netmask In CIDR. Required for AireOS. type: int lagOrPortNumber: - description: Lag Or Port Number. + description: Lag Or Port Number. Required for AireOS. type: int vlanId: - description: VLAN ID. + description: VLAN ID. Required for both AireOS and EWLC. type: int type: list managedAPLocations: @@ -55,8 +55,8 @@ type: str type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless Provision description: Complete reference of the Provision API. @@ -94,7 +94,6 @@ site: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -103,14 +102,7 @@ sample: > { "executionId": "string", - "executionUrl": "string", - "provisioningTasks": { - "success": [ - "string" - ], - "failed": [ - "string" - ] - } + "executionStatusUrl": "string", + "message": "string" } """ diff --git a/plugins/modules/wireless_provision_device_update.py b/plugins/modules/wireless_provision_device_update.py index c76487739e..e0b5580cb3 100644 --- a/plugins/modules/wireless_provision_device_update.py +++ b/plugins/modules/wireless_provision_device_update.py @@ -24,39 +24,39 @@ elements: dict suboptions: deviceName: - description: Device Name. + description: Controller Name. type: str dynamicInterfaces: description: Wireless Provision Device Update's dynamicInterfaces. elements: dict suboptions: interfaceGateway: - description: Interface Gateway. + description: Interface Gateway. Required for AireOS. type: str interfaceIPAddress: - description: Interface IPAddress. + description: Interface IP Address. Required for AireOS. type: str interfaceName: - description: Interface Name. + description: Interface Name. Required for AireOS and EWLC. type: str interfaceNetmaskInCIDR: - description: Interface Netmask In CIDR. + description: Interface Netmask In CIDR. Required for AireOS. type: int lagOrPortNumber: - description: Lag Or Port Number. + description: Lag Or Port Number. Required for AireOS. type: int vlanId: - description: Vlan Id. + description: VLAN ID. Required for AireOS and EWLC. type: int type: list managedAPLocations: - description: Managed APLocations. + description: List of managed AP locations (Site Hierarchies). elements: str type: list type: list requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless ProvisionUpdate description: Complete reference of the ProvisionUpdate API. @@ -94,7 +94,6 @@ - string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -103,14 +102,7 @@ sample: > { "executionId": "string", - "executionUrl": "string", - "provisioningTasks": { - "success": [ - "string" - ], - "failed": [ - "string" - ] - } + "executionStatusUrl": "string", + "message": "string" } """ diff --git a/plugins/modules/wireless_provision_ssid_create_provision.py b/plugins/modules/wireless_provision_ssid_create_provision.py index a0627c125e..e9297e90e8 100644 --- a/plugins/modules/wireless_provision_ssid_create_provision.py +++ b/plugins/modules/wireless_provision_ssid_create_provision.py @@ -41,6 +41,11 @@ ssidDetails: description: Wireless Provision Ssid Create Provision's ssidDetails. suboptions: + authKeyMgmt: + description: Takes string inputs for the AKMs that should be set true. Possible + AKM values dot1x,dot1x_ft, dot1x_sha, psk, psk_ft, psk_sha, owe, sae, sae_ft. + elements: str + type: list enableBroadcastSSID: description: Enable Broadcast SSID. type: bool @@ -53,6 +58,12 @@ fastTransition: description: Fast Transition. type: str + ghz24Policy: + description: 2.4 GHz Policy. + type: str + ghz6PolicyClientSteering: + description: 6 Ghz Client Steering. + type: bool name: description: SSID Name. type: str @@ -63,6 +74,15 @@ radioPolicy: description: Radio Policy. type: str + rsnCipherSuiteCcmp256: + description: Rsn Cipher Suite Ccmp256. + type: bool + rsnCipherSuiteGcmp128: + description: Rsn Cipher Suite Gcmp128. + type: bool + rsnCipherSuiteGcmp256: + description: Rsn Cipher Suite Gcmp256. + type: bool securityLevel: description: Security Level(For guest SSID OPEN/WEB_AUTH, For Enterprise SSID ENTERPRISE/PERSONAL/OPEN). @@ -78,8 +98,8 @@ description: SSID Type. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless CreateAndProvisionSSID description: Complete reference of the CreateAndProvisionSSID API. @@ -111,20 +131,26 @@ managedAPLocations: - string ssidDetails: + authKeyMgmt: + - string enableBroadcastSSID: true enableFastLane: true enableMACFiltering: true fastTransition: string + ghz24Policy: string + ghz6PolicyClientSteering: true name: string passphrase: string radioPolicy: string + rsnCipherSuiteCcmp256: true + rsnCipherSuiteGcmp128: true + rsnCipherSuiteGcmp256: true securityLevel: string trafficType: string webAuthURL: string ssidType: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_provision_ssid_delete_reprovision.py b/plugins/modules/wireless_provision_ssid_delete_reprovision.py index 8d713ce13f..2fb01aeb4f 100644 --- a/plugins/modules/wireless_provision_ssid_delete_reprovision.py +++ b/plugins/modules/wireless_provision_ssid_delete_reprovision.py @@ -20,14 +20,16 @@ description: Additional headers. type: dict managedAPLocations: - description: ManagedAPLocations path parameter. + description: ManagedAPLocations path parameter. List of managed AP locations (Site + Hierarchies). This parameter needs to be encoded as per UTF-8 encoding. type: str ssidName: - description: SsidName path parameter. + description: SsidName path parameter. SSID Name. This parameter needs to be encoded + as per UTF-8 encoding. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless DeleteSSIDAndProvisionItToDevices description: Complete reference of the DeleteSSIDAndProvisionItToDevices API. @@ -56,7 +58,6 @@ ssidName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_psk_override.py b/plugins/modules/wireless_psk_override.py index 163ea45b5a..1e6c060c46 100644 --- a/plugins/modules/wireless_psk_override.py +++ b/plugins/modules/wireless_psk_override.py @@ -16,26 +16,21 @@ - cisco.dnac.module author: Rafael Campos (@racampos) options: - payload: - description: Wireless Psk Override's payload. - elements: dict - suboptions: - passPhrase: - description: Pass phrase (create/update). - type: str - site: - description: Site name hierarchy (ex Global/aaa/zzz/...). - type: str - ssid: - description: Enterprise ssid name(already created/present). - type: str - wlanProfileName: - description: WLAN Profile Name. - type: str - type: list + passPhrase: + description: Pass phrase (create/update). + type: str + site: + description: Site name hierarchy (ex Global/aaa/zzz/...). + type: str + ssidName: + description: Enterprise SSID Name(already created/present). + type: str + wlanProfileName: + description: WLAN Profile Name. + type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless PSKOverride description: Complete reference of the PSKOverride API. @@ -59,14 +54,12 @@ dnac_port: "{{dnac_port}}" dnac_version: "{{dnac_version}}" dnac_debug: "{{dnac_debug}}" - payload: - - passPhrase: string - site: string - ssid: string - wlanProfileName: string + passPhrase: string + site: string + ssidName: string + wlanProfileName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK diff --git a/plugins/modules/wireless_rf_profile.py b/plugins/modules/wireless_rf_profile.py index 86c7ad953d..b6c4062c8c 100644 --- a/plugins/modules/wireless_rf_profile.py +++ b/plugins/modules/wireless_rf_profile.py @@ -21,7 +21,7 @@ description: Channel Width. type: str defaultRfProfile: - description: Is Default Rf Profile. + description: Default Rf Profile. type: bool enableBrownField: description: Enable Brown Field. @@ -52,16 +52,16 @@ type: str maxPowerLevel: description: Max Power Level. - type: int + type: float minPowerLevel: description: Rx Sop Threshold. - type: int + type: float parentProfile: description: Parent Profile. type: str powerThresholdV1: description: Power Threshold V1. - type: int + type: float radioChannels: description: Radio Channels. type: str @@ -80,16 +80,16 @@ type: str maxPowerLevel: description: Max Power Level. - type: int + type: float minPowerLevel: description: Min Power Level. - type: int + type: float parentProfile: description: Parent Profile. type: str powerThresholdV1: description: Power Threshold V1. - type: int + type: float radioChannels: description: Radio Channels. type: str @@ -108,16 +108,16 @@ type: str maxPowerLevel: description: Max Power Level. - type: int + type: float minPowerLevel: description: Min Power Level. - type: int + type: float parentProfile: description: Parent Profile. type: str powerThresholdV1: description: Power Threshold V1. - type: int + type: float radioChannels: description: Radio Channels. type: str @@ -130,8 +130,8 @@ *non-custom RF profile cannot be deleted. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless CreateOrUpdateRFProfile description: Complete reference of the CreateOrUpdateRFProfile API. @@ -210,7 +210,6 @@ rfProfileName: string """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -219,7 +218,7 @@ sample: > { "executionId": "string", - "executionUrl": "string", + "executionStatusUrl": "string", "message": "string" } """ diff --git a/plugins/modules/wireless_rf_profile_info.py b/plugins/modules/wireless_rf_profile_info.py index 281f87b6dc..21415ca889 100644 --- a/plugins/modules/wireless_rf_profile_info.py +++ b/plugins/modules/wireless_rf_profile_info.py @@ -24,8 +24,8 @@ - Rf-profile-name query parameter. RF Profile Name. type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless RetrieveRFProfiles description: Complete reference of the RetrieveRFProfiles API. @@ -54,46 +54,50 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK returned: always - type: list - elements: dict + type: dict sample: > - [ - { - "name": "string", - "parentProfileA": "string", - "parentProfileB": "string", - "enableARadioType": true, - "enableBRadioType": true, - "enableCRadioType": true, - "channelWidth": "string", - "aRadioChannels": "string", - "bRadioChannels": "string", - "cRadioChannels": "string", - "dataRatesA": "string", - "dataRatesB": "string", - "dataRatesC": "string", - "mandatoryDataRatesA": "string", - "mandatoryDataRatesB": "string", - "mandatoryDataRatesC": "string", - "enableCustom": true, - "minPowerLevelA": "string", - "minPowerLevelB": "string", - "minPowerLevelC": "string", - "maxPowerLevelA": "string", - "maxPowerLevelB": "string", - "powerThresholdV1A": 0, - "powerThresholdV1B": 0, - "powerThresholdV1C": 0, - "rxSopThresholdA": "string", - "rxSopThresholdB": "string", - "rxSopThresholdC": "string", - "defaultRfProfile": true, - "enableBrownField": true - } - ] + { + "name": "string", + "defaultRfProfile": true, + "enableRadioTypeA": true, + "enableRadioTypeB": true, + "channelWidth": "string", + "enableCustom": true, + "enableBrownField": true, + "radioTypeAProperties": { + "parentProfile": "string", + "radioChannels": "string", + "dataRates": "string", + "mandatoryDataRates": "string", + "powerThresholdV1": 0, + "rxSopThreshold": "string", + "minPowerLevel": 0, + "maxPowerLevel": 0 + }, + "radioTypeBProperties": { + "parentProfile": "string", + "radioChannels": "string", + "dataRates": "string", + "mandatoryDataRates": "string", + "powerThresholdV1": 0, + "rxSopThreshold": "string", + "minPowerLevel": 0, + "maxPowerLevel": 0 + }, + "radioTypeCProperties": { + "parentProfile": "string", + "radioChannels": "string", + "dataRates": "string", + "mandatoryDataRates": "string", + "rxSopThreshold": "string", + "minPowerLevel": 0, + "maxPowerLevel": 0, + "powerThresholdV1": 0 + }, + "enableRadioTypeC": true + } """ diff --git a/plugins/modules/wireless_sensor_test_results_info.py b/plugins/modules/wireless_sensor_test_results_info.py index f316a4602c..e4de58e12d 100644 --- a/plugins/modules/wireless_sensor_test_results_info.py +++ b/plugins/modules/wireless_sensor_test_results_info.py @@ -26,18 +26,20 @@ startTime: description: - StartTime query parameter. The epoch time in milliseconds. - type: int + type: float endTime: description: - EndTime query parameter. The epoch time in milliseconds. - type: int + type: float testFailureBy: description: - - TestFailureBy query parameter. Obtain failure statistics group by "area", "building", or "floor". + - > + TestFailureBy query parameter. Obtain failure statistics group by "area", "building", or "floor" (case + insensitive). type: str requirements: -- dnacentersdk >= 2.6.0 -- python >= 3.9 +- dnacentersdk >= 2.4.9 +- python >= 3.5 seealso: - name: Cisco DNA Center documentation for Wireless SensorTestResults description: Complete reference of the SensorTestResults API. @@ -69,7 +71,6 @@ register: result """ - RETURN = r""" dnac_response: description: A dictionary or list with the response returned by the Cisco DNAC Python SDK @@ -77,72 +78,75 @@ type: dict sample: > { - "summary": { - "totalTestCount": 0, - "ONBOARDING": { - "AUTH": { - "passCount": 0, - "failCount": 0 + "version": "string", + "response": { + "summary": { + "totalTestCount": 0, + "ONBOARDING": { + "AUTH": { + "passCount": 0, + "failCount": 0 + }, + "DHCP": { + "passCount": 0, + "failCount": 0 + }, + "ASSOC": { + "passCount": 0, + "failCount": 0 + } }, - "DHCP": { - "passCount": 0, - "failCount": 0 + "PERFORMANCE": { + "IPSLASENDER": { + "passCount": 0, + "failCount": 0 + } }, - "ASSOC": { - "passCount": 0, - "failCount": 0 - } - }, - "PERFORMANCE": { - "IPSLASENDER": { - "passCount": 0, - "failCount": 0 - } - }, - "NETWORK_SERVICES": { - "DNS": { - "passCount": 0, - "failCount": 0 - } - }, - "APP_CONNECTIVITY": { - "HOST_REACHABILITY": { - "passCount": 0, - "failCount": 0 + "NETWORK_SERVICES": { + "DNS": { + "passCount": 0, + "failCount": 0 + } }, - "WEBSERVER": { - "passCount": 0, - "failCount": 0 + "APP_CONNECTIVITY": { + "HOST_REACHABILITY": { + "passCount": 0, + "failCount": 0 + }, + "WEBSERVER": { + "passCount": 0, + "failCount": 0 + }, + "FILETRANSFER": { + "passCount": 0, + "failCount": 0 + } }, - "FILETRANSFER": { - "passCount": 0, - "failCount": 0 - } - }, - "RF_ASSESSMENT": { - "DATA_RATE": { - "passCount": 0, - "failCount": 0 + "RF_ASSESSMENT": { + "DATA_RATE": { + "passCount": 0, + "failCount": 0 + }, + "SNR": { + "passCount": 0, + "failCount": 0 + } }, - "SNR": { - "passCount": 0, - "failCount": 0 + "EMAIL": { + "MAILSERVER": { + "passCount": 0, + "failCount": 0 + } } }, - "EMAIL": { - "MAILSERVER": { - "passCount": 0, - "failCount": 0 + "failureStats": [ + { + "errorCode": 0, + "errorTitle": "string", + "testType": "string", + "testCategory": "string" } - } - }, - "failureStats": [ - { - "errorCode": 0, - "errorTitle": "string", - "testType": "string", - "testCategory": "string" - } - ] + ] + } } """ diff --git a/plugins/plugin_utils/dnac.py b/plugins/plugin_utils/dnac.py index 7448c4c508..514106e2f1 100644 --- a/plugins/plugin_utils/dnac.py +++ b/plugins/plugin_utils/dnac.py @@ -140,7 +140,7 @@ def dnac_argument_spec(): dnac_username=dict(type="str", fallback=(env_fallback, ['DNAC_USERNAME']), default="admin", aliases=["user"]), dnac_password=dict(type="str", fallback=(env_fallback, ['DNAC_PASSWORD']), no_log=True), dnac_verify=dict(type="bool", fallback=(env_fallback, ['DNAC_VERIFY']), default=True), - dnac_version=dict(type="str", fallback=(env_fallback, ['DNAC_VERSION']), default="2.3.5.3"), + dnac_version=dict(type="str", fallback=(env_fallback, ['DNAC_VERSION']), default="2.3.7.6"), dnac_debug=dict(type="bool", fallback=(env_fallback, ['DNAC_DEBUG']), default=False), validate_response_schema=dict(type="bool", fallback=(env_fallback, ['VALIDATE_RESPONSE_SCHEMA']), default=True), ) diff --git a/requirements.txt b/requirements.txt index fe7a7694cd..cf40b8f59f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -dnacentersdk >= 2.6.0 \ No newline at end of file +dnacentersdk >= 2.7.1 \ No newline at end of file diff --git a/tests/sanity/ignore-2.10.txt b/tests/sanity/ignore-2.10.txt index 199ea4ac42..81bbb929cd 100644 --- a/tests/sanity/ignore-2.10.txt +++ b/tests/sanity/ignore-2.10.txt @@ -740,3 +740,7 @@ plugins/modules/template_workflow_manager.py compile-2.7!skip # Python 2.7 is no plugins/modules/template_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK diff --git a/tests/sanity/ignore-2.11.txt b/tests/sanity/ignore-2.11.txt index 91834bb50a..0b839978b0 100644 --- a/tests/sanity/ignore-2.11.txt +++ b/tests/sanity/ignore-2.11.txt @@ -1091,3 +1091,7 @@ plugins/modules/template_workflow_manager.py compile-2.7!skip # Python 2.7 is no plugins/modules/template_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK diff --git a/tests/sanity/ignore-2.12.txt b/tests/sanity/ignore-2.12.txt index 41aebb287f..36d5eb734e 100644 --- a/tests/sanity/ignore-2.12.txt +++ b/tests/sanity/ignore-2.12.txt @@ -38,3 +38,7 @@ plugins/modules/template_workflow_manager.py compile-2.7!skip # Python 2.7 is no plugins/modules/template_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK diff --git a/tests/sanity/ignore-2.13.txt b/tests/sanity/ignore-2.13.txt index 29449f7cb2..3c31c2c4bc 100644 --- a/tests/sanity/ignore-2.13.txt +++ b/tests/sanity/ignore-2.13.txt @@ -18,3 +18,5 @@ plugins/modules/device_credential_workflow_manager.py compile-2.7!skip # Python plugins/modules/device_credential_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK diff --git a/tests/sanity/ignore-2.14.txt b/tests/sanity/ignore-2.14.txt index 29449f7cb2..3c31c2c4bc 100644 --- a/tests/sanity/ignore-2.14.txt +++ b/tests/sanity/ignore-2.14.txt @@ -18,3 +18,5 @@ plugins/modules/device_credential_workflow_manager.py compile-2.7!skip # Python plugins/modules/device_credential_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK diff --git a/tests/sanity/ignore-2.15.txt b/tests/sanity/ignore-2.15.txt index 29449f7cb2..3c31c2c4bc 100644 --- a/tests/sanity/ignore-2.15.txt +++ b/tests/sanity/ignore-2.15.txt @@ -18,3 +18,5 @@ plugins/modules/device_credential_workflow_manager.py compile-2.7!skip # Python plugins/modules/device_credential_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK diff --git a/tests/sanity/ignore-2.9.txt b/tests/sanity/ignore-2.9.txt index 199ea4ac42..81bbb929cd 100644 --- a/tests/sanity/ignore-2.9.txt +++ b/tests/sanity/ignore-2.9.txt @@ -740,3 +740,7 @@ plugins/modules/template_workflow_manager.py compile-2.7!skip # Python 2.7 is no plugins/modules/template_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK plugins/modules/template_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py compile-2.6!skip # Python 2.6 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.7!skip # Python 2.7 is not supported by the DNA Center SDK +plugins/modules/ise_radius_integration_workflow_manager.py import-2.6!skip # Python 2.6 is not supported by the DNA Center SDK