ciscodevnet / ansible-aci Goto Github PK
View Code? Open in Web Editor NEWCisco ACI Ansible Collection
Home Page: https://galaxy.ansible.com/cisco/aci
License: GNU General Public License v3.0
Cisco ACI Ansible Collection
Home Page: https://galaxy.ansible.com/cisco/aci
License: GNU General Public License v3.0
extra space was added to "epg" when constructed url for api call for fex port
in the following example, epg name is "test". An extra space was added to the end as "test "
"epg": "test ",
The full traceback is:
File "/tmp/ansible_cisco.aci.aci_static_binding_to_epg_payload_z00_4esa/ansible_cisco.aci.aci_static_binding_to_epg_payload.zip/ansible_collections/cisco/aci/plugins/module_utils/aci.py", line 994, in get_existing
self.response_json(info['body'])
failed: [10.1.102.66] (item={'tenant': 'jackyu', 'ap': 'poc', 'epg': 'test', 'vlan': '3100', 'leaf': '1201', 'interface': '1/30', 'extpaths': '181'}) => {
"ansible_loop_var": "item",
"changed": false,
"invocation": {
"module_args": {
"annotation": null,
"ap": "poc",
"certificate_name": null,
"deploy_immediacy": "immediate",
"description": null,
"encap_id": 3100,
"epg": "test ",
"extpaths": 181,
"host": "10.1.102.66",
"interface": "1/30",
"interface_mode": "native",
"interface_type": "fex",
"leafs": [
"1201"
],
"output_level": "normal",
"output_path": null,
"owner_key": null,
"owner_tag": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"pod_id": 1,
"port": null,
"primary_encap_id": null,
"private_key": null,
"protocol": "https",
"state": "present",
"tenant": "jackyu",
"timeout": 30,
"use_proxy": true,
"use_ssl": true,
"username": "admin",
"validate_certs": false
}
},
"item": {
"ap": "poc",
"epg": "test",
"extpaths": "181",
"interface": "1/30",
"leaf": "1201",
"tenant": "jackyu",
"vlan": "3100"
},
"msg": "Connection failed for https://10.1.102.66/api/mo/uni/tn-jackyu/ap-poc/epg-test /rspathAtt-[topology/pod-1/paths-1201/extpaths-181/pathep-[eth1/30]].json?rsp-prop-include=config-only. An unknown error occurred: URL can't contain control characters. '/api/mo/uni/tn-jackyu/ap-poc/epg-test /rspathAtt-[topology/pod-1/paths-1201/extpaths-181/pathep-[eth1/30]].json?rsp-prop-include=config-only' (found at least ' ')"
SUMMARY
There seem to be issue with aci_access_port_block_to_access_port: module. What is the parameter for "leaf_port_blk:" ?
using aci_rest the dn is
dn: "uni/infra/accportprof-{{item.name}}/hports-{{item.intSel}}-typ-range/portblk-block2"
but if i use leaf_port_blk: block2, the dn shown is correct, but i there is error.
ISSUE OPENER ewchuah
ISSUE LINK ansible/ansible#65824
ISSUE TYPE
Bug Report
COMPONENT NAME
aci_access_port_block_to_access_port:
ANSIBLE VERSION
ansible 2.9.2
config file = /home/chuahew/ansible_aci/ansible.cfg
configured module search path = ['/home/chuahew/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/chuahew/environments/venv_toolkit_py36/lib64/python3.6/site-packages/ansible
executable location = /home/chuahew/environments/venv_toolkit_py36/bin/ansible
python version = 3.6.8 (default, Aug 7 2019, 17:28:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
CONFIGURATION
DEFAULT_STDOUT_CALLBACK(/home/chuahew/ansible_aci/ansible.cfg) = skippy
RETRY_FILES_ENABLED(/home/chuahew/ansible_aci/ansible.cfg) = False
OS / ENVIRONMENT
Linux dev-centos.localdomain 3.10.0-1062.1.1.el7.x86_64 #1 SMP Fri Sep 13 22:55:44 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
centos-release-7-7.1908.0.el7.centos.x86_64
STEPS TO REPRODUCE
- name: Create Interface Profile (conntype = acc)
aci_access_port_block_to_access_port:
<<: *aci_login
leaf_interface_profile: "{{item.name}}"
access_port_selector: "{{item.intSel}}"
leaf_port_blk: block2
from_port: 1
to_port: 1
state: present
delegate_to: localhost
with_items:
- "{{IntProf}}"
when: item.conntype == 'acc'
EXPECTED RESULTS
should be able to provision interface profile. Using aci_rest works fine.
ACTUAL RESULTS
failed: [10.68.1.21 -> localhost] (item={'conntype': 'acc', 'name': 'IPF_SS301', 'desc': '', 'intPolGrp': 'IPG_ACC_SVR_Auto', 'intSel': 'IST_E1:01', 'fromPort': '1', 'toPort': '1'}) => {
"ansible_loop_var": "item",
"changed": false,
"error": {
"code": "102",
"text": "configured object ((Dn0)) not found Dn0=uni/infra/accportprof-IPF_SS301/hports-IST_E1:01-typ-range/portblk-block2, "
},
"invocation": {
"module_args": {
"access_port_selector": "IST_E1:01",
"certificate_name": null,
"from_card": null,
"from_port": "1",
"host": "10.68.1.21",
"hostname": "10.68.1.21",
"leaf_interface_profile": "IPF_SS301",
"leaf_port_blk": "block2",
"leaf_port_blk_description": null,
"output_level": "normal",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": null,
"private_key": null,
"protocol": "https",
"state": "present",
"timeout": 30,
"to_card": null,
"to_port": "1",
"use_proxy": true,
"use_ssl": true,
"username": "admin",
"validate_certs": false
}
},
"item": {
"conntype": "acc",
"desc": "",
"fromPort": "1",
"intPolGrp": "IPG_ACC_SVR_Auto",
"intSel": "IST_E1:01",
"name": "IPF_SS301",
"toPort": "1"
},
"msg": "APIC Error 102: configured object ((Dn0)) not found Dn0=uni/infra/accportprof-IPF_SS301/hports-IST_E1:01-typ-range/portblk-block2, "
}
ISSUE TYPE
Bug Report
COMPONENT NAME
aci_firmware_source
ANSIBLE VERSION
v2.5
SUMMARY
The aci_firmware_source module does not correctly report a change as one would expect. However the same aci_rest payload does correctly report a change since it relies on the return output status: created.
The following fails:
- aci_firmware_source:
source: aci-n9000-dk9.11.3.2h.bin
url: foo.bar.cisco.com/01/Software/Cisco/ACI/aci-n9000-dk9.11.3.2h.bin
url_protocol: http
While this works:
- aci_rest:
method: post
path: /api/mo/uni/fazbric/fwrepop.json
content:
firmwareOSource:
name: aci-n9000-dk9.11.3.2h.bin
url: foo.bar.cisco.com/01/Software/Cisco/ACI/aci-n9000-dk9.11.3.2h.bin
proto: http
SUMMARY
ISSUE TYPE
Informational
COMPONENT NAME
aci_contract
ANSIBLE VERSION
Observed in Ansible 2.5.1, 2.5.2 and 2.5.3, with Ansible Tower 3.2.4.
CONFIGURATION
DEFAULT_LOOKUP_PLUGIN_PATH(/etc/ansible/ansible.cfg) = [u'/usr/share/ansible/plu
DEFAULT_MODULE_PATH(/etc/ansible/ansible.cfg) = [u'/usr/share/ansible']
OS / ENVIRONMENT
N/A
STEPS TO REPRODUCE
Following APIC upgrade to Version: 3.1(2o), the ACI playbook demonstrated (https://youtu.be/Fs8STriMqTM?t=8m24s) began to intermittently fail when when adding contracts to the APIC. Running the same playbook against an APIC simulator on 3.0(1k) has not encountered errors, using the same playbook and the same instance of Ansible Tower. Only the target APIC was changed.
Enabling debug level 3 (-vvv) appears to reduce or eliminate the frequency of the problem, suggesting it may be load or timing related. I suspect the fault is with the APIC controller on release 3.1(2o). This is an informational issue only.
- name: Add (or delete) the contract
aci_contract:
hostname: '{{ inventory_hostname }}'
username: '{{ apic.username }}'
password: '{{ apic.password }}'
validate_certs: '{{ validate_certs }}'
state: '{{ desired_state }}'
#
contract: '{{ item.contract_name }}'
description: '{{ item.contract_descr }}'
tenant: '{{ tenant }}'
scope: '{{ scope }}'
with_items: '{{ tpe }}'
tags: contract
EXPECTED RESULTS
The contract would be added to the APIC.
ACTUAL RESULTS
{
"changed": false,
"error": {
"code": -1,
"text": "Unable to parse output as JSON, see 'raw' output. No JSON object could be decoded"
}
}
failed: [aci-demo.sandbox.wwtatc.local] (item={u'contract_name': u'QA_Bling_Enterprise-to-Prod_Qualys', u'dst_port_start': u'4445', u'dst_port_end': u'4445', u'ip_protocol': u'tcp', u'contract_subject_name': u'sub-QA_Bling_Enterprise-to-Prod_Qualys', u'contract_descr': u'WorkOrder6756', u'entry_name': u'tcp-port_4445', u'filter_name': u'tcp-4445', u'contract_subject_descr': u'WorkOrder6756', u'filter_descr': u'WorkOrder6756', u'filter_entry_descr': u'ent_descr', u'ether_type': u'ip'}) => {
"changed": false,
"error": {
"code": -1,
"text": "Unable to parse output as JSON, see 'raw' output. No JSON object could be decoded"
},
"item": {
"contract_descr": "WorkOrder6756",
"contract_name": "QA_Bling_Enterprise-to-Prod_Qualys",
"contract_subject_descr": "WorkOrder6756",
"contract_subject_name": "sub-QA_Bling_Enterprise-to-Prod_Qualys",
"dst_port_end": "4445",
"dst_port_start": "4445",
"entry_name": "tcp-port_4445",
"ether_type": "ip",
"filter_descr": "WorkOrder6756",
"filter_entry_descr": "ent_descr",
-snip-
}
ISSUE TYPE
Feature Idea
COMPONENT NAME
aci_domain
ANSIBLE VERSION
# ansible --version
ansible 2.5.0 (devel b107e397cb) last updated 2018/01/15 16:56:58 (GMT +200)
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /home/nillo/software/ansible/lib/ansible
executable location = /home/nillo/software/ansible/bin/ansible
python version = 2.7.5 (default, Nov 6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
#
CONFIGURATION
# ansible-config dump --only-changed
DEFAULT_ROLES_PATH(/etc/ansible/ansible.cfg) = [u'/etc/ansible/roles', u'/usr/share/ansible/roles']
#
OS / ENVIRONMENT
Ansible running on CentOS 7.3 and ACI running 3.1(1i).
SUMMARY
For VMM domains we need to be able to specify all required parameters. This is dependent on the domain type (vmware, redhat, microsoft). I believe it would be great to add to the module.
For VMware:
domain_name
vswitch_type: [vds, avs, ave]
access_mode: [ro, rw]
vcenter_name
vcenter_ip: [ip or FQDN]
vds_version: [5.1, 5.5, 6.0, 6.5, default]
stats_collection: [disabled, enabled]
datacenter_name
mgmt_epg
credential_name
port_channel_mode: [on, lacp-active,lacp-passive,mac-pining,mac-pinning-plus]
vswitch_policy: [cdp, lldp, none]
For RHV:
domain_name
rhvm_name
rhvm_ip: [ip or FQDN]
datacenter_name
mgmt_epg
credential_name
For Microsoft:
domain_name
scvmm_name
scvmm_ip: [ip or FQDN]
scvmm_cloud_name
port_channel_mode: [on, lacp-active,lacp-passive,mac-pining,mac-pinning-plus]
STEPS TO REPRODUCE
This is an enhancement request/idea.
If the output_path parameter is configured any module should dump the config to file.
However this is not the case for the aci_rest
This config:
aci_rest:
<<: *aci_login
path: /api/node/mo/uni/tn-CICD/ap-3Tier_App.json
method: post
src: 3Tier_App.json
output_path: 'config.json'
Should dump the content of 3Tier_App.json into config.json but this does not happens.
ISSUE TYPE
Bug Report
COMPONENT NAME
aci_aaa_user
ANSIBLE VERSION
v2.5
SUMMARY
Due to an inconsistency in the APIC REST API, a task that sets the password of a locally-authenticated user is not idempotent. The APIC will complain with message Password history check: user dag should not use previous 5 passwords.
aaaUser:
attributes:
name: dag
pwd: S0me!Pwd
{
"aaaUser": {
"attributes": {
"name": "dag",
"pwd": "S0me!Pwd"
}
}
}
This seems to be a bug in the APIC as according to APIC REST API documentation:
Standard REST methods are supported on the API, which includes POST, GET, and DELETE operations through HTTP. The POST and DELETE methods are idempotent, meaning that there is no additional effect if they are called more than once with the same input parameters. The GET method is nullipotent, meaning that it can be called zero or more times without making any changes (or that it is a read-only operation).
The APIC in this case should really be testing whether the provided password is identical to the existing password, before testing it against the password history.
The vendor is notified of this inconsistency.
SUMMARY
in some scenarios to construct_url() need subclass_4 support. MO l2extRsPathL2OutAtt which is 4th level from root.
ISSUE TYPE
optional arguments
ADDITIONAL INFORMATION:
This collection will be included in Ansible 2.10 because it contains modules and/or plugins that were included in Ansible 2.9. Please review:
The latest version of the collection available on August 18 will be included in Ansible 2.10.0, except possibly newer versions which differ only in the patch level. (For details, see the roadmap). Please release version 1.0.0 of your collection by this date! If 1.0.0 does not exist, the same 0.x.y version will be used in all of Ansible 2.10 without updates, and your 1.x.y release will not be included until Ansible 2.11 (unless you request an exception at a community working group meeting and go through a demanding manual process to vouch for backwards compatibility . . . you want to avoid this!).
Your collection versioning must follow all semver rules. This means:
Your collection should provide data for the Ansible 2.10 changelog and porting guide. The changelog and porting guide are automatically generated from ansible-base, and from the changelogs of the included collections. All changes from the breaking_changes
, major_changes
, removed_features
and deprecated_features
sections will appear in both the changelog and the porting guide. You have two options for providing changelog fragments to include:
changelogs/changelog.yaml
inside your collection (see the documentation of changelogs/changelog.yaml format).If you cannot contribute to the integrated Ansible changelog using one of these methods, please provide a link to your collection's changelog by creating an issue in https://github.com/ansible-community/ansible-build-data/. If you do not provide changelogs/changelog.yml
or a link, users will not be able to find out what changed in your collection from the Ansible changelog and porting guide.
Run ansible-test sanity --docker -v
in the collection with the latest ansible-base or stable-2.10
ansible/ansible checkout.
Be sure you're subscribed to:
If you have questions or want to provide feedback, please see the Feedback section in the collection requirements.
(Internal link to keep track of issues: ansible-collections/overview#102)
The Key generated by the openssl_privatekey ansible modules starts with:
-----BEGIN RSA PRIVATE KEY-----
However aci.py check for this string to validate the key:
if private_key_content.startswith('-----BEGIN PRIVATE KEY-----'):
See:
https://github.com/CiscoDevNet/ansible-aci/blob/master/plugins/module_utils/aci.py#L224
https://github.com/CiscoDevNet/ansible-aci/blob/master/plugins/module_utils/aci.py#L244
We should allow using also RSA PRIVATE KEY as they work just fine.
From @dagwieers on October 25, 2017 12:38
ISSUE TYPE
Bug Report
COMPONENT NAME
aci_
ANSIBLE VERSION
v2.5
SUMMARY
When you use the YAML or JSON payload format, ACI requires an attributes entry even when there are no attributes needed. It will complain with:
Attributes are missing, tag 'attributes' must be specified first, before any other tag
You can add an empty attributes entry by doing attributes: {} like the example below:
- name: Create a switch profile
aci_rest:
<<: *aci_login
path: /api/policymgr/mo/uni.json
method: post
content:
infraInfra:
attributes: {}
children:
- infraNodeP:
-cut-
We could make aci_rest add empty attributes-entries if they are missing.
Copied from original issue: datacenter/aci-ansible#167
SUMMARY
I was trying to use the aci_interface_policy_port_security module and I noticed that the timeout parameter is not working, I pass values different than 60 but the policy is always created with a timeout value of 60.
ISSUE TYPE
Bug Report
COMPONENT NAME
aci_interface_policy_port_security
ANSIBLE VERSION
ansible 2.7.5
CONFIGURATION
DEFAULT_BECOME(/etc/ansible/ansible.cfg) = True
DEFAULT_BECOME_ASK_PASS(/etc/ansible/ansible.cfg) = False
DEFAULT_BECOME_METHOD(/etc/ansible/ansible.cfg) = sudo
DEFAULT_BECOME_USER(/etc/ansible/ansible.cfg) = root
DEFAULT_ROLES_PATH(/etc/ansible/ansible.cfg) = [u'/opt/working/roles']
DEFAULT_VAULT_PASSWORD_FILE(/etc/ansible/ansible.cfg) = /opt/working/.ansible_vault
OS / ENVIRONMENT
CentOS Linux release 7.6.1810 (Core)
Target device: CISCO Application Policy Infrastructure Controller Version: 2.3(1f)
The playbook is launched with ansible-playbook command from a Rundeck job.
STEPS TO REPRODUCE
---
- hosts: localhost
gather_facts: no
vars_files:
- vars/aci.yml
- vars/policy.yml"
tasks:
- name: DEBUG
debug:
msg: "{{ ps_timeout }}"
- name: CREATE PORT SECURITY INTERFACE POLICY
aci_interface_policy_port_security:
hostname: "{{ aci_host }}"
username: "{{ aci_user }}"
password: "{{ aci_password }}"
validate_certs: False
port_security: "{{ ps_pol_name }}"
timeout: "{{ ps_timeout }}"
max_end_points: "{{ ps_max_end_points }}"
description: "{{ ps_description }}"
state: present
Contents of aci.yml is only the hostname, username and password for connection to the ACI device.
The contents of policy.yml are:
ps_pol_name: ansible_ps05
ps_timeout: 80
ps_max_end_points: 3
ps_description: test policy
EXPECTED RESULTS
To create an ACI interface port security policy with a timeout of 80 or any other value different than 60.
ACTUAL RESULTS
The ACI interface port security policy is always created with a timeout of 60, regardless of the value you choose/pass as parameter.
ansible-playbook 2.7.5
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/var/lib/rundeck/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /bin/ansible-playbook
python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
Using /etc/ansible/ansible.cfg as config file
/etc/ansible/hosts did not meet host_list requirements, check plugin documentation if this is unexpected
/etc/ansible/hosts did not meet script requirements, check plugin documentation if this is unexpected
Parsed /etc/ansible/hosts inventory source with ini plugin
Read vars_file 'vars/aci.yml'
Read vars_file 'vars/policy.yml'
PLAYBOOK: aci_create_intf_policy_ps.yml ****************************************
1 plays in /opt/working/roles/aci/playbooks/aci_create_intf_policy_ps.yml
Read vars_file 'vars/aci.yml'
Read vars_file 'vars/policy.yml'
Read vars_file 'vars/aci.yml'
Read vars_file 'vars/policy.yml'
PLAY [localhost] ***************************************************************
META: ran handlers
Read vars_file 'vars/aci.yml'
Read vars_file 'vars/policy.yml'
TASK [DEBUG] *******************************************************************
task path: /opt/working/roles/aci/playbooks/aci_create_intf_policy_ps.yml:11
ok: [localhost] => {
"msg": 80
}
Read vars_file 'vars/aci.yml'
Read vars_file 'vars/policyyml'
TASK [CREATE PORT SECURITY INTERFACE POLICY] ***********************************
task path: /opt/working/roles/aci/playbooks/aci_create_intf_policy_ps.yml:15
<localhost> ESTABLISH SSH CONNECTION FOR USER: None
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/var/lib/rundeck/.ansible/cp/8a5a4c6a60 localhost '/bin/sh -c '"'"'echo ~ && sleep 0'"'"''
<localhost> (0, '/var/lib/rundeck\n', '')
<localhost> ESTABLISH SSH CONNECTION FOR USER: None
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/var/lib/rundeck/.ansible/cp/8a5a4c6a60 localhost '/bin/sh -c '"'"'( umask 77 && mkdir -p "` echo /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602 `" && echo ansible-tmp-1548782932.26-63215767615602="` echo /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602 `" ) && sleep 0'"'"''
<localhost> (0, 'ansible-tmp-1548782932.26-63215767615602=/var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602\n', '')
Using module file /usr/lib/python2.7/site-packages/ansible/modules/network/aci/_aci_intf_policy_port_security.py
<localhost> PUT /var/lib/rundeck/.ansible/tmp/ansible-local-62668WFQnHO/tmp0xX5ic TO /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602/AnsiballZ__aci_intf_policy_port_security.py
<localhost> SSH: EXEC sftp -b - -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/var/lib/rundeck/.ansible/cp/8a5a4c6a60 '[localhost]'
<localhost> (0, 'sftp> put /var/lib/rundeck/.ansible/tmp/ansible-local-62668WFQnHO/tmp0xX5ic /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602/AnsiballZ__aci_intf_policy_port_security.py\n', '')
<localhost> ESTABLISH SSH CONNECTION FOR USER: None
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/var/lib/rundeck/.ansible/cp/8a5a4c6a60 localhost '/bin/sh -c '"'"'chmod u+x /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602/ /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602/AnsiballZ__aci_intf_policy_port_security.py && sleep 0'"'"''
<localhost> (0, '', '')
<localhost> ESTABLISH SSH CONNECTION FOR USER: None
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/var/lib/rundeck/.ansible/cp/8a5a4c6a60 -tt localhost '/bin/sh -c '"'"'sudo -H -S -n -u root /bin/sh -c '"'"'"'"'"'"'"'"'echo BECOME-SUCCESS-copwlrdecthkuqtlfgtnfhhxkequmwjh; /usr/bin/python /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602/AnsiballZ__aci_intf_policy_port_security.py'"'"'"'"'"'"'"'"' && sleep 0'"'"''
Escalation succeeded
<localhost> (0, '\r\n{"current": [{"l2PortSecurityPol": {"attributes": {"dn": "uni/infra/portsecurityP-ansible_ps05", "ownerKey": "", "name": "ansible_ps05", "descr": "test policy", "nameAlias": "", "violation": "protect", "maximum": "3", "timeout": "60", "ownerTag": ""}}}], "invocation": {"module_args": {"username": "ansible", "max_end_points": 3, "private_key": null, "protocol": "https", "use_proxy": true, "certificate_name": null, "hostname": "*****", "host": "*****", "output_level": "normal", "state": "present", "port_security": "ansible_ps05", "timeout": 80, "use_ssl": true, "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", "validate_certs": false, "port": null, "description": "test policy"}}, "changed": true}\r\n', 'Shared connection to localhost closed.\r\n')
<localhost> ESTABLISH SSH CONNECTION FOR USER: None
<localhost> SSH: EXEC ssh -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o ConnectTimeout=10 -o ControlPath=/var/lib/rundeck/.ansible/cp/8a5a4c6a60 localhost '/bin/sh -c '"'"'rm -f -r /var/lib/rundeck/.ansible/tmp/ansible-tmp-1548782932.26-63215767615602/ > /dev/null 2>&1 && sleep 0'"'"''
<localhost> (0, '', '')
changed: [localhost] => {
"changed": true,
"current": [
{
"l2PortSecurityPol": {
"attributes": {
"descr": "test policy",
"dn": "uni/infra/portsecurityP-ansible_ps05",
"maximum": "3",
"name": "ansible_ps05",
"nameAlias": "",
"ownerKey": "",
"ownerTag": "",
"timeout": "60",
"violation": "protect"
}
}
}
],
"invocation": {
"module_args": {
"certificate_name": null,
"description": "test policy",
"host": "*****",
"hostname": "*****",
"max_end_points": 3,
"output_level": "normal",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": null,
"port_security": "ansible_ps05",
"private_key": null,
"protocol": "https",
"state": "present",
"timeout": 80,
"use_proxy": true,
"use_ssl": true,
"username": "ansible",
"validate_certs": false
}
}
}
META: ran handlers
META: ran handlers
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0
Playbook creates AAEPs no problem. On subsequent runs Ansible reports the status as "changed" instead of "ok"
ansible 2.9.6 & 2.11.0.dev0
Here's the config:
- name: Add AAEPs
aci_aep:
<<: *aci_login
aep: '{{ item.access_policy_aci_aep_name }}'
description: '{{ item.access_policy_aci_aep_description }}'
infra_vlan: '{{ item.access_policy_aci_aep_enable_infra_vlan }}'
state: '{{ item.access_policy_aci_aep_state | default("present") }}'
with_items: '{{ aci_model_data|aci_listify("access_policy","aci_aep") }}'
Topology file (snippet):
- aci_aep:
- description:
domains:
- name: Phys-Dom
type: phys
enable_infra_vlan: false
name: Phys-AAEP
- description:
domains:
- name: VMM-Dom
type: vmm
vm_provider: vmware
enable_infra_vlan: false
name: VMM-AAEP
- description:
domains:
- name: Phys-Dom
type: phys
- name: L3Out-Dom
type: l3dom
enable_infra_vlan: false
name: External-AAEP
Result:
TASK [datacenter.aci-model : Add AAEPs] ***************************************************************************************************************
changed: [apic1] => (item={'access_policy_aci_aep_description': None, 'access_policy_aci_aep_enable_infra_vlan': False, 'access_policy_aci_aep_name': 'Phys-AAEP'})
changed: [apic1] => (item={'access_policy_aci_aep_description': None, 'access_policy_aci_aep_enable_infra_vlan': False, 'access_policy_aci_aep_name': 'VMM-AAEP'})
changed: [apic1] => (item={'access_policy_aci_aep_description': None, 'access_policy_aci_aep_enable_infra_vlan': False, 'access_policy_aci_aep_name': 'External-AAEP'})
Currently if the scope parameter is not specify the aci_l3out_extsubnet will crash.
The scope should either made mandatory or default to import-security.
Defaulting to import-security is better as is the most common use case and is also the default in APIC
For example, below is the detailed API spec for the aci-epg module. And as you can see, there is no way to add an annotation field while creating an EPG.....
https://docs.ansible.com/ansible/latest/modules/aci_epg_module.html#aci-epg-module
Thx.
SUMMARY
As noticed in #59907, lib/ansible/module_utils/network/aci/aci.py is using pyOpenSSL to sign something with a private key (https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/network/aci/aci.py#L212-L248). Since pyOpenSSL is not (anymore) supposed to be used for anything than TLS/SSL connections, it would be good to get rid of this eventually.
The best way forward is probably to first support the cryptography library as well (and prefer it over pyOpenSSL if it is around), and eventually deprecate pyOpenSSL support and later remove it.
New versions of pyOpenSSL have cryptography as a requirement, so eventually there should be no platforms left with pyOpenSSL but without a decent cryptography version.
ISSUE OPENER felixfontein
ISSUE TYPE
Bug Report
COMPONENT NAME
lib/ansible/module_utils/network/aci/aci.py
ANSIBLE VERSION
2.9.0
When ansible-playbook is run with --check the config should be added in the output_path dump file only for the objects that are not present on the ACI fabric.
This does not have any impact as NAE will simply ignore objects that are already present in ACI but is sub optimal.
ISSUE TYPE
Bug Report
COMPONENT NAME
aci_rest
ANSIBLE VERSION
v2.4+
SUMMARY
If you use a REST payload with aci_rest using status="created" the action is not idempotent. The first time (when the object does not exist) it works (changed=True), but a subsequent call fails as the APIC returns an HTTP failure.
However, if you do the same for removing an object using status="deleted" the action is idempotent. So a subsequent call works (and does not report a change, changed=False) as one would expect.
This seems an implementation issue in the APIC.
PS If you would add status="created,modified" or simply status="modified" your task will be idempotent and it will not lead to failures on subsequent runs.
STEPS TO REPRODUCE
This will cause a failure on a subsequent create:
<aaaUserCert dn="uni/userext/user-admin/usercert-admin" data="-----BEGIN CERTIFICATE-----\r\nMII<snip>NGg\r\n-----END CERTIFICATE\r\n" name="admin" rn="usercert-admin" status="created"/>
This will not cause a failure on a subsequent removal:
<aaaUserCert dn="uni/userext/user-admin/usercert-admin" name="admin" rn="usercert-admin" status="deleted"/>
However using status="modified" will always work.
This report wants to highlight that creation and deletion have a different behaviour.
The vendor has been notified of this inconsistency.
SUMMARY
In the ACI API, there are values called 'ownerKey' and 'ownerTag'. With our automation, we use non-user service accounts to connect to the APICs, so the user that ran a script isn't immediately known. As a result, we use these values to identify the user that ran the script and some sort of documentation identifier - Ticket Number, Change Number, etc. It would be great to expose these values in modules as an option.
ISSUE TYPE
Feature Idea
COMPONENT NAME
Ideally, this would be implemented on each ACI module.
ANSIBLE VERSION
2.4+
It is not currently possible, that I have seen, to provision a new port selector with an associated port block and policy group.
I have been using cisco.aci.aci_access_port_block_to_access_port
to create additional port blocks in a pre-existing port selector, but now I am looking to automate vpc deployments. These vpcs all need a unique port selector that is likely not created at playbook runtime.
Error received:
"text": "configured object ((Dn0)) not found Dn0=uni/infra/accportprof-LEAF_201:202_BAREMETAL_VPC_INT_PROF/hports-TESTANSIBLE01_PORT_SEL-typ-range/portblk-TESTANSIBLE01_PORT_SEL, "
accportprof-LEAF_201:202_BAREMETAL_VPC_INT_PROF
- exists and is already attached to a leaf switch profile
hports-TESTANSIBLE01_PORT_SEL-typ-range
- does not exist and was expected to be created at runtime
portblk-TESTANSIBLE01_PORT_SEL
- does not exist and is not created at runtime due to hports path not existing
Policy group for the interface selector is also not configurable and is expected to already exist and attach to hports.
Following change recently added, we should built the test file for this module to make sure it works for all cases.
SUMMARY
Would like the aci modules to support breakout cables. Breakout enables a 40 Gigabit (Gb) port to be split into four independent and logical 10Gb ports or a 100Gb port to be split into four independent and logical 25Gb ports. When using a breakout cable, you will need the ability to configure subports. The options for "fromSubPort" and "toSubPort" will need to be added when using the "aci_access_port_to_interface_policy_leaf_profile" module. We will also need the option to create a "leaf breakout port group" under the "leaf policy groups" menu. This is what tells the port that a breakout cable is being used how it will be divided (10g-x4 or 25g-x4). I believe a new module will need to be created for this as it will be pretty different from the "aci_interface_policy_leaf_policy_group" module.
ISSUE TYPE
Feature Idea
COMPONENT NAME
aci_access_port_to_interface_policy_leaf_profile
new module for creating "leaf breakout port group"
aci_interface_policy_leaf_policy_group
ADDITIONAL INFORMATION
This feature would allow you to configure access port selectors that include sub port ranges when breakout cables are being used. It will also allow you to create leaf breakout port groups so that they can be assigned as the "policy group" to the parent port. The actual leaf access/pc/vpc policy groups will be assigned to the sub ports.
Here is a cisco doc on breakout ports in ACI
https://www.cisco.com/c/en/us/td/docs/switches/datacenter/aci/apic/sw/2-x/L2_config/b_Cisco_APIC_Layer_2_Configuration_Guide/b_Cisco_APIC_Layer_2_Configuration_Guide_chapter_0110.html
I have attached an example XML code for configuring an access port selector with sub ports. Also attached an xml sample of a breakout port group as well as some pictures of the menus in the GUI
[Access Selector with sub ports example.txt]
(https://github.com/ansible/ansible/files/2885548/Access.Selector.with.sub.ports.example.txt)
brkoutportgrp-10g-4x.txt
SUMMARY
This is a new ACI module to manage DHCP Labels for Bridge Domains.
This is a reworked version of #32571
ISSUE TYPE
New Module Pull Request
COMPONENT NAME
aci_bd_dhcp_label
SUMMARY
Trying to compare to Cisco APIC Snapshots using aci_config_rollback module
ISSUE TYPE
task path:
/data/tools/ansible/playbooks/roles/cisco.apic/tasks/compare_snapshots.yml:20
ESTABLISH LOCAL CONNECTION FOR USER: root
EXEC /bin/sh -c 'echo ~root && sleep 0'
EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710" && echo ansible-tmp-1559753113.2-180977196103710="echo /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710" ) && sleep 0'
Using module file /usr/lib/python2.7/site-packages/ansible/modules/network/aci/aci_config_rollback.py
PUT /root/.ansible/tmp/ansible-local-4142tNAUms/tmpuI5x6D TO /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py
EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/ /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py && sleep 0'
EXEC /bin/sh -c '/usr/bin/python2 /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py && sleep 0'
EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 113, in
_ansiballz_main()
File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 105, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 48, in invoke_module
imp.load_module('main', mod, module, MOD_DESC)
File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/main.py", line 309, in
File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/main.py", line 273, in main
File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/main.py", line 292, in get_preview
AttributeError: 'NoneType' object has no attribute 'read'
fatal: [localhost -> localhost]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 113, in \n _ansiballz_main()\n File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 105, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 48, in invoke_module\n imp.load_module('main', mod, module, MOD_DESC)\n File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/main.py", line 309, in \n File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/main.py", line 273, in main\n File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/main.py", line 292, in get_preview\nAttributeError: 'NoneType' object has no attribute 'read'\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
to retry, use: --limit @/data/tools/ansible/playbooks/roles/cisco.apic/tasks/compare_snapshots.retry
COMPONENT NAME
aci_config_rollback
Snippet from module page:
name: Compare Snapshot Files
aci_config_rollback:
host: apic
username: admin
password: SomeSecretPassword
export_policy: config_backup
snapshot: run-2017-08-28T06-24-01
compare_export_policy: config_backup
compare_snapshot: run-2017-08-27T23-43-56
state: preview
delegate_to: localhost
ANSIBLE VERSION
ansible 2.7.10
config file = /etc/ansible/ansible.cfg
configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python2.7/site-packages/ansible
executable location = /usr/bin/ansible
python version = 2.7.5 (default, Mar 26 2019, 22:13:06) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]
CONFIGURATION
[root@localhost tasks]# ansible-config dump --only-changed
[root@localhost tasks]#
OS / ENVIRONMENT
Target is Cisco APIC
STEPS TO REPRODUCE
replace snapshot and compare_snapshot fields with your snapshot names
---
- name: Compare ACI Snapshots
hosts: localhost
gather_facts: true
- name: Compare APIC Snapshot
aci_config_rollback:
host: x.x.x.x
username: admin
password:
export_policy: config_backup
snapshot: run-2019-02-05T19-28-56
compare_export_policy: config_backup
compare_snapshot: run-2019-02-07T22-34-49
state: preview
validate_certs: no
delegate_to: localhost
register: snapshot_compare_result
- name: Print Snapshot Compare Results
debug:
msg: "{{ snapshot_compare_result }}"
EXPECTED RESULTS
Expected to see snapshot comparison results
ACTUAL RESULTS
Error - MUDULE FAILURE
task path: /data/tools/ansible/playbooks/roles/cisco.apic/tasks/compare_snapshots.yml:20
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~root && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710 `" && echo ansible-tmp-1559753113.2-180977196103710="` echo /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710 `" ) && sleep 0'
Using module file /usr/lib/python2.7/site-packages/ansible/modules/network/aci/aci_config_rollback.py
<localhost> PUT /root/.ansible/tmp/ansible-local-4142tNAUms/tmpuI5x6D TO /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/ /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python2 /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 113, in <module>
_ansiballz_main()
File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 105, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py", line 48, in invoke_module
imp.load_module('__main__', mod, module, MOD_DESC)
File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/__main__.py", line 309, in <module>
File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/__main__.py", line 273, in main
File "/tmp/ansible_aci_config_rollback_payload_ZNJN9z/__main__.py", line 292, in get_preview
AttributeError: 'NoneType' object has no attribute 'read'
fatal: [localhost -> localhost]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File \"/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py\", line 113, in <module>\n _ansiballz_main()\n File \"/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py\", line 105, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/root/.ansible/tmp/ansible-tmp-1559753113.2-180977196103710/AnsiballZ_aci_config_rollback.py\", line 48, in invoke_module\n imp.load_module('__main__', mod, module, MOD_DESC)\n File \"/tmp/ansible_aci_config_rollback_payload_ZNJN9z/__main__.py\", line 309, in <module>\n File \"/tmp/ansible_aci_config_rollback_payload_ZNJN9z/__main__.py\", line 273, in main\n File \"/tmp/ansible_aci_config_rollback_payload_ZNJN9z/__main__.py\", line 292, in get_preview\nAttributeError: 'NoneType' object has no attribute 'read'\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
to retry, use: --limit @/data/tools/ansible/playbooks/roles/cisco.apic/tasks/compare_snapshots.retry
Linked to #8
In support of Multi-Site configurations I would like to be able to create the following objects:
Spine Interface Policy Groups
Spine Interface Profiles (And associated port selectors)
Spine Switch Profiles (And associated switch selectors)
In the absence of that, I have tried creating this configuration with the aci_rest module.
Everything works except creation of the Spine Interface Profiles.
Here is the post:
url: https://{{apic}}/api/node/mo/uni/infra/spaccportprof-Test.json
payload: {"infraSpAccPortP":{"attributes":{"dn":"uni/infra/spaccportprof-Test","name":"Test","rn":"spaccportprof-Test","status":""},"children":[]}}
In Postman this creates the object.
In Ansible the playbook gives a status of OK, but does not create the object with the exact same url & payload.
โฆ selector
SUMMARY
ISSUE TYPE
Bugfix Pull Request
Docs Pull Request
Feature Pull Request
New Module Pull Request
COMPONENT NAME
ADDITIONAL INFORMATION
plugins/modules/aci_firmware_group.py:168:1: F401 'json' imported but unused
plugins/module_utils/aci.py:227:9: F841 local variable 'e' is assigned to but never used
plugins/module_utils/aci.py:236:17: F841 local variable 'err' is assigned to but never used
plugins/module_utils/aci.py:824:9: F841 local variable 'root_class' is assigned to but never used
plugins/module_utils/aci.py:826:9: F841 local variable 'root_filter' is assigned to but never used
plugins/module_utils/aci.py:828:9: F841 local variable 'ter_class' is assigned to but never used
plugins/module_utils/aci.py:830:9: F841 local variable 'ter_filter' is assigned to but never used
plugins/module_utils/aci.py:832:9: F841 local variable 'sec_class' is assigned to but never used
plugins/module_utils/aci.py:834:9: F841 local variable 'sec_filter' is assigned to but never used
plugins/module_utils/aci.py:836:9: F841 local variable 'parent_class' is assigned to but never used
plugins/module_utils/aci.py:838:9: F841 local variable 'parent_filter' is assigned to but never used
plugins/module_utils/aci.py:893:9: F841 local variable 'root_class' is assigned to but never used
plugins/module_utils/aci.py:895:9: F841 local variable 'root_filter' is assigned to but never used
plugins/module_utils/aci.py:897:9: F841 local variable 'quad_class' is assigned to but never used
plugins/module_utils/aci.py:899:9: F841 local variable 'quad_filter' is assigned to but never used
plugins/module_utils/aci.py:901:9: F841 local variable 'ter_class' is assigned to but never used
plugins/module_utils/aci.py:903:9: F841 local variable 'ter_filter' is assigned to but never used
plugins/module_utils/aci.py:905:9: F841 local variable 'sec_class' is assigned to but never used
plugins/module_utils/aci.py:907:9: F841 local variable 'sec_filter' is assigned to but never used
plugins/module_utils/aci.py:909:9: F841 local variable 'parent_class' is assigned to but never used
plugins/module_utils/aci.py:911:9: F841 local variable 'parent_filter' is assigned to but never used
ISSUE TYPE
Bug Report
maybe Enhancement request?
COMPONENT NAME
aci_rest
ANSIBLE VERSION
ansible 2.4.2.0
config file = None
configured module search path = [u'/home/dhamann/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
executable location = /usr/local/bin/ansible
python version = 2.7.12 (default, Nov 20 2017, 18:23:56) [GCC 5.4.0 20160609]
CONFIGURATION
DEFAULT_DEBUG(env: ANSIBLE_DEBUG) = False
DEFAULT_STRATEGY(env: ANSIBLE_STRATEGY) = linear
OS / ENVIRONMENT
N/A
SUMMARY
aci_rest module does not always detect changed config, but reports it as unchanged ("ok:")
STEPS TO REPRODUCE
Depending on how you push the config to APIC the aci_rest module detects it as changed or not:
This example will always report as unchanged:
- name: Create CDP Policies
tags:
- create
- network
aci_rest:
host: "{{ apic_hostname }}"
username: "{{ apic_username }}"
password: "{{ apic_password }}"
validate_certs: false
method: post
path: "api/node/mo/uni/infra.xml?rsp-subtree=modified"
content: |
<infraInfra>
<cdpIfPol adminSt="{{item.state}}" name="{{item.name}}" descr="CDP set to {{item.state}}"/>
</infraInfra>
with_items:
- "{{cdp_policies}}"
This playbook works as expected ("ok:" if nothing has changed and "changed:" otherwise)
- name: Create CDP Policies
tags:
- create
- network
aci_rest:
host: "{{ apic_hostname }}"
username: "{{ apic_username }}"
password: "{{ apic_password }}"
validate_certs: false
method: post
path: "api/node/mo/uni/infra/.xml?rsp-subtree=modified"
content: |
<cdpIfPol adminSt="{{item.state}}" name="{{item.name}}" descr="CDP set to {{item.state}}"/>
with_items:
- "{{cdp_policies}}"
Note the difference in path: parameter (infra.xml vs. infra/.xml) as well as adjusted content.
EXPECTED RESULTS
In both cases changes to actual APIC config should result in "changed:" status
ACTUAL RESULTS
The reason why the first playbook does not behave as expected is that APIC does not populate the "status=" parameter as expected by the aci_rest module (it will only report change if this parameter is set to either of 'created', 'modified', 'deleted')
(see https://github.com/datacenter/aci-ansible/blob/e87db8f15e34ea7dc2e1b30fd445a4c59561bbc9/library/aci_rest.py#L270-L284)
ok: [localhost] => (item={u'state': u'enabled', u'name': u'cdp_on2'}) => {
"changed": false,
"error_code": 0,
"error_text": "Success",
"imdata": [
{
"infraInfra": {
"attributes": {
"childAction": "deleteNonPresent",
"dn": "uni/infra",
"lcOwn": "local",
"modTs": "2017-08-17T01:40:52.471+01:00",
"monPolDn": "uni/fabric/monfab-default",
"name": "infra",
"nameAlias": "",
"ownerKey": "",
"ownerTag": "",
"rn": "",
"status": "",
"uid": "0"
},
"children": [
{
"cdpIfPol": {
"attributes": {
"adminSt": "enabled",
"childAction": "deleteNonPresent",
"descr": "",
"extMngdBy": "",
"lcOwn": "local",
"modTs": "2018-01-17T09:45:05.902+01:00",
"monPolDn": "",
"name": "cdp_on2",
"nameAlias": "",
"ownerKey": "",
"ownerTag": "",
"rn": "cdpIfP-cdp_on2",
"status": "",
"uid": "17805"
}
}
}
]
}
}
],
"invocation": {
"module_args": {
"content": "<infraInfra>\n <cdpIfPol adminSt=\"enabled\" name=\"cdp_on2\" />\n</infraInfra>\n",
"host": "apic.ddsdnlab.at",
"hostname": "apic.ddsdnlab.at",
"method": "post",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"path": "api/node/mo/uni/infra.xml?rsp-subtree=modified",
"protocol": "https",
"src": null,
"timeout": 30,
"use_proxy": true,
"use_ssl": true,
"username": "ansible",
"validate_certs": false
}
},
"item": {
"name": "cdp_on2",
"state": "enabled"
},
"response": "OK (544 bytes)",
"status": 200,
"totalCount": "1",
"url": "https://apic.ddsdnlab.at/api/node/mo/uni/infra.xml?rsp-subtree=modified"
}
On the other hand the second playbook runs as expected as returned data from APIC contains (status='modified'):
changed: [localhost] => (item={u'state': u'enabled', u'name': u'cdp_on'}) => {
"changed": true,
"error_code": 0,
"error_text": "Success",
"imdata": [
{
"cdpIfPol": {
"attributes": {
"adminSt": "enabled",
"childAction": "deleteNonPresent",
"descr": "CDP set to enabled",
"dn": "uni/infra/cdpIfP-cdp_on",
"extMngdBy": "",
"lcOwn": "local",
"modTs": "2018-01-18T05:26:34.072+01:00",
"monPolDn": "uni/fabric/monfab-default",
"name": "cdp_on",
"nameAlias": "",
"ownerKey": "",
"ownerTag": "",
"rn": "",
"status": "modified",
"uid": "15374"
}
}
}
],
"invocation": {
"module_args": {
"content": "<cdpIfPol adminSt=\"enabled\" name=\"cdp_on\" descr=\"CDP set to enabled\"/>\n",
"host": "apic.ddsdnlab.at",
"hostname": "apic.ddsdnlab.at",
"method": "post",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"path": "api/node/mo/uni/infra/.xml?rsp-subtree=modified",
"protocol": "https",
"src": null,
"timeout": 30,
"use_proxy": true,
"use_ssl": true,
"username": "ansible",
"validate_certs": false
}
},
"item": {
"name": "cdp_on",
"state": "enabled"
},
"response": "OK (375 bytes)",
"status": 200,
"totalCount": "1",
"url": "https://apic.ddsdnlab.at/api/node/mo/uni/infra/.xml?rsp-subtree=modified"
}
Given this (weired?) behavior of APIC (I confirmed this behavior is the same on APIC versions 3.0, 3.1 and 2.1), I think the current implementation of aci_changed() might be insufficient.
ISSUE TYPE
enhancement
COMPONENT NAME
aci_epg
ANSIBLE VERSION
v2.9
SUMMARY
To create microsegmented EPG, it will be good to add in the playload the following paramter:
"isAttrBasedEPg": "true"
For the module, the name of this paramter could be something like "useg" and the value is a boolean.
aci_epg_monitoring_policy seems to create a monitoring policy (primitively), but I cannot find a way to associate a monitoring policy with with an EPG or ANP in the aci_ap or aci_epg modules.
From @dagwieers on October 25, 2017 12:32
ISSUE TYPE
Bug Report
COMPONENT NAME
aci_rest
ANSIBLE VERSION
v2.5
SUMMARY
If you use the YAML syntax with aci_rest, but use an XML-path (ending with .xml), the aci_rest module currently fails with:
An unknown error occurred: unhashable type
The workaround is to change .xml to .json, however the real fix is to support YAML content with XML paths by converting the YAML to XML payload. Currently xmljson cannot convert from JSON to XML for the Cobra convention.
Copied from original issue: datacenter/aci-ansible#166
SUMMARY
The is a feature request to implement support for "Tags", "Global Alias" and Alias for all ACI modules where applicable, see for example aci_epg
ISSUE OPENER rsmeyers
ISSUE TYPE
Feature Idea
COMPONENT NAME
aci_epg, aci_tenant etc...
ISSUE TYPE
Feature Idea
COMPONENT NAME
ACI
ANSIBLE VERSION
v2.6
SUMMARY
The general idea is that the ACI modules would feel more native and better integrated with how Ansible works. This means that the information/credentials to connect to the APIC is stored in the inventory (using ansible_host, ansible_port, ansible_user and ansible_password) and the playbook tasks only take into account the parameters required for its specific use.
Other benefits of using an ACI connection plugin include:
It would manage the connection and could handle HTTP errors more gracefully
On connection problems it can rebuild the session transparantly
During maintenance or APIC cluster issues the connection plugin would switch between APICs (provides high-availability)
It would centralize connection information per node or per group, keeping credentials out of playbooks
It avoids too many consecutive auth API calls which may result in connection throttling and playbook failure
Currently we do:
- hosts: apic_cluster01
tasks:
- aci_tenant:
hostname: 10.1.2.1
username: admin
password: SecretPassword
tenant: customer-xyz
description: Customer XYZ
state: present
- aci_vrf:
hostname: 10.1.2.1
username: admin
password: SecretPassword
tenant: customer-xyz
vrf: lab
description: Lab VRF
policy_control_preference: enforced
policy_control_direction: ingress
- aci_bd:
hostname: 10.1.2.1
username: admin
password: SecretPassword
tenant: customer-xyz
vrf: lab
bd: app01
enable_routing: yes
- aci_bd_subnet:
hostname: 10.1.2.1
username: admin
password: SecretPassword
tenant: customer-xyz
bd: app01
gateway: 10.10.10.1
mask: 24
scope: private
...
A typical playbook would then look much more concise and readable:
- hosts: apic_cluster01
tasks:
- aci_tenant:
tenant: customer-xyz
description: Customer XYZ
state: present
- aci_vrf:
tenant: customer-xyz
vrf: lab
description: Lab VRF
policy_control_preference: enforced
policy_control_direction: ingress
- aci_bd:
tenant: customer-xyz
vrf: lab
bd: app01
enable_routing: yes
- aci_bd_subnet:
tenant: customer-xyz
bd: app01
gateway: 10.10.10.1
mask: 24
scope: private
...
The inventory for an ACI cluster would then look like:
all:
apic_cluster01:
ansible_host: [ 10.1.2.1, 10.1.2.2, 10.1.2.3 ]
ansible_connection: aci
ansible_user: admin
ansible_password: SuperSecret
proxy_env:
http_proxy: http://proxy.example.com:8080
This relates to #33887
SUMMARY
A new Cisco ACI Module to create contracts between epgs in different Tenants. Inter-Tenant contract deployment
ISSUE TYPE
Feature Idea
COMPONENT NAME
aci_inter_tenant_contract
ADDITIONAL INFORMATION
This would allow you to provide access between epgs that are in different tenants
SUMMARY
This is a new Ansible module for managing ACI Link Level policy.
ISSUE OPENER vasilyprokopov
ISSUE TYPE
New Module Pull Request
COMPONENT NAME
aci_interface_policy_link_level
Hi,
Should these modules be moved from community.network
into this repo:
https://github.com/ansible-collections/community.network/tree/master/plugins/modules/network/aci
PR1: Add the files to this repo
PR2: Delete files from community.general
PR3 Update ansible/ansible's lib/ansible/config/ansible_builtin_runtime.yml
to ensure that all ACI modules point to this collection.
Hi,
I have the following ssl error on Python 3.6.10 with ansible 2.9.12, using the cisco sandbox.
ansible-playbook
PLAY [aci] *********************************************************************************************
TASK [Add a new EPG] ***********************************************************************************
fatal: [sandboxapicdc.cisco.com]: FAILED! => {"changed": false, "msg": "Connection failed for https://sandboxapicdc.cisco.com/api/aaaLogin.json. Request failed: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1108)>"}
ERROR:ansible:fatal: [sandboxapicdc.cisco.com]: FAILED! => {"changed": false, "msg": "Connection failed for https://sandboxapicdc.cisco.com/api/aaaLogin.json. Request failed: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1108)>"}
PLAY RECAP *********************************************************************************************
sandboxapicdc.cisco.com : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Hello
as the modules belongs to cisco.aci
it is quite redundant to have the prefix aci_ on the name of module, and now as this is necessary to call them with the FQCN that make module unnecessary long.
Here is the current (as of v1.0.1) import warnings:
Following on from #36, we should really have (at minimum) ansible-test sanity
running against this repo.
If you put the following in .github/workflows/ansible-test.yml
(and fix any resulting issues) this will give you a solid base:
name: CI
on:
- pull_request
jobs:
sanity:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v1
with:
path: ansible_collections/cisco/aci
- name: Set up Python 3.6
uses: actions/setup-python@v1
with:
python-version: 3.6
- name: Install ansible-base (devel)
run: pip install https://github.com/ansible/ansible/archive/devel.tar.gz --disable-pip-version-check
- name: Run sanity tests
run: ansible-test sanity --docker -v --color --python 3.6
ISSUE TYPE
enhancement
COMPONENT NAME
aci_vrf
ANSIBLE VERSION
v2.10
SUMMARY
Update the aci_vrf module to enable preferred groups for the module. This has to be enabled under vzAny under the VRF. The aci_epg module already has support to add it to a preferred group so the aci_vrf module is missing the capability to add it.
The module should enable (or disable) preferred groups and also configure the match type (matchT) for vzAny contracts. Those vzAny contracts should be handled in a different module.
when using signature-based authentication, querying for certificate which doesn't match the given private key will fail
it's better to use another parameter to specify the certificate we want to manage.
Is there a document that lists the Platform Series or Software version supported by the ACI/MSO module?(Or a description of the support policy)
https://www.cisco.com/c/en/us/td/docs/switches/datacenter/aci/apic/sw/recommended-release/b_Recommended_Cisco_ACI_Releases.html
For example, the following document is an example of NXOS.
https://docs.ansible.com/ansible/latest/network/user_guide/platform_nxos.html
Cisco Nexus Platform Support Matrix
Am I correct in assuming that the N9K described in this matrix is the version supported by the ACI module?
thanks
Copied from original issue: ansible/ansible#68483
#67957 ### SUMMARY
Add the choice between Accept / Reject for the "allow promiscuous" option
ISSUE OPENER: AntoinePorte31
ISSUE LINK ansible/ansible#68109
ISSUE TYPE
Feature Idea
COMPONENT NAME
aci_epg_to_domain โ Bind EPGs to Domains (fv:RsDomAtt)
ADDITIONAL INFORMATION
Add in Parameter something like "promiscuous" and in the choices : Accept / Reject, in order to fully achieve the vmm domain association with ansible.
- name: Add a new physical domain to EPG binding
aci_epg_to_domain:
host: "{{ inventory_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
validate_certs: false
tenant: Prod_XXX
ap: Prod_XX
epg: "{{ epgname }}_EPG"
domain: dvSwitch_ACI_XX
domain_type: vmm
state: present
deploy_immediacy: immediate
promiscuous: accept OR reject <----- NEW OPTION
delegate_to: localhost
Following the output I get when I run the playbook. It works just fine when the lag_type is either node or link for PC or VPC but for Access it gives the below error. Tried it on the simulator as well as on a Hardware setup but the issue persists. Here is the output.
Rohits-MacBook-Pro:ansible-aci rohitborkar$ ansible-playbook playbooks/Access_Policies/10_interface_policy_groups-M.yml -vvvv
ansible-playbook 2.9.11
config file = /Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/ansible.cfg
configured module search path = [u'/Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/plugins/modules']
ansible python module location = /Library/Python/2.7/site-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 2.7.16 (default, Jul 5 2020, 02:24:03) [GCC 4.2.1 Compatible Apple LLVM 11.0.3 (clang-1103.0.29.21) (-macos10.15-objc-
Using /Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/dynamic_inventory.py as it did not pass its verify_file() method
Set default localhost to localhost
Parsed /Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/dynamic_inventory.py inventory source with script plugin
[WARNING]: Found both group and host with same name: ungrouped
Loading callback plugin default of type stdout, v2.0 from /Library/Python/2.7/site-packages/ansible/plugins/callback/default.pyc
PLAYBOOK: 10_interface_policy_groups-M.yml *********************************************************************************
Positional arguments: playbooks/Access_Policies/10_interface_policy_groups-M.yml
become_method: sudo
inventory: (u'/Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/dynamic_inventory.py',)
forks: 5
tags: (u'all',)
verbosity: 4
connection: smart
timeout: 10
1 plays in playbooks/Access_Policies/10_interface_policy_groups-M.yml
PLAY [localhost] ***********************************************************************************************************
META: ran handlers
TASK [Create leaf policy groups] *******************************************************************************************
task path: /Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/playbooks/Access_Policies/10_interface_policy_groups-M.yml:7
ESTABLISH LOCAL CONNECTION FOR USER: rohitborkar
EXEC /bin/sh -c 'echo ~rohitborkar && sleep 0'
EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /Users/rohitborkar/.ansible/tmp
"&& mkdir /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693232.61-19918-236071587691299 && echo ansible-tmp-1599693232.61-19918-236071587691299="echo /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693232.61-19918-236071587691299
" ) && sleep 0'
Attempting python interpreter discovery
EXEC /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'/usr/bin/python'"'"'; command -v '"'"'python3.7'"'"'; command -v '"'"'python3.6'"'"'; command -v '"'"'python3.5'"'"'; command -v '"'"'python2.7'"'"'; command -v '"'"'python2.6'"'"'; command -v '"'"'/usr/libexec/platform-python'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python'"'"'; echo ENDFOUND && sleep 0'
Python interpreter discovery fallback (unsupported platform for extended discovery: darwin)
Using module file /Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/plugins/modules/aci_interface_policy_leaf_policy_group.py
PUT /Users/rohitborkar/.ansible/tmp/ansible-local-19911HsbS9B/tmpmRf1Ky TO /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693232.61-19918-236071587691299/AnsiballZ_aci_interface_policy_leaf_policy_group.py
EXEC /bin/sh -c 'chmod u+x /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693232.61-19918-236071587691299/ /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693232.61-19918-236071587691299/AnsiballZ_aci_interface_policy_leaf_policy_group.py && sleep 0'
EXEC /bin/sh -c '/usr/bin/python /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693232.61-19918-236071587691299/AnsiballZ_aci_interface_policy_leaf_policy_group.py && sleep 0'
EXEC /bin/sh -c 'rm -f -r /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693232.61-19918-236071587691299/ > /dev/null 2>&1 && sleep 0'
[WARNING]: Platform darwin on host localhost is using the discovered Python interpreter at /usr/bin/python, but future
installation of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.
failed: [localhost] (item={u'aep': u'Phys_AEP', u'pc_policy': None, u'interface_policy_group': u'ACC_test_laptop_1', u'cdp_policy': u'CDP-Enabled-IntPol', u'stp_policy': None, u'link_level_policy': u'LnkSpd-Auto-IntPol', u'mcp_policy': u'MCP_Enabled', u'lag_type': u'leaf', u'pc_member_name': None, u'lldp_policy': u'LLDP-TxRx-Enabled-IntPol'}) => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"ansible_loop_var": "item",
"changed": false,
"error": {
"code": "400",
"text": "Invalid request. Can not contain child 'rslacpPol' under parent 'uni/infra/funcprof/accportgrp-ACC_test_laptop_1'"
},
"invocation": {
"module_args": {
"aep": "Phys_AEP",
"annotation": null,
"cdp_policy": "CDP-Enabled-IntPol",
"certificate_name": null,
"description": null,
"egress_data_plane_policing_policy": null,
"fibre_channel_interface_policy": null,
"host": "10.16.254.222",
"hostname": "10.16.254.222",
"ingress_data_plane_policing_policy": null,
"l2_interface_policy": null,
"lag_type": "leaf",
"link_level_policy": "LnkSpd-Auto-IntPol",
"lldp_policy": "LLDP-TxRx-Enabled-IntPol",
"mcp_policy": "MCP_Enabled",
"monitoring_policy": null,
"name": "ACC_test_laptop_1",
"name_alias": null,
"output_level": "normal",
"output_path": null,
"owner_key": null,
"owner_tag": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"policy_group": "ACC_test_laptop_1",
"port": null,
"port_channel_policy": "",
"port_security_policy": null,
"priority_flow_control_policy": null,
"private_key": null,
"protocol": "https",
"slow_drain_policy": null,
"state": "present",
"storm_control_interface_policy": null,
"stp_interface_policy": "",
"timeout": 30,
"use_proxy": true,
"use_ssl": true,
"username": "admin",
"validate_certs": false
}
},
"item": {
"aep": "Phys_AEP",
"cdp_policy": "CDP-Enabled-IntPol",
"interface_policy_group": "ACC_test_laptop_1",
"lag_type": "leaf",
"link_level_policy": "LnkSpd-Auto-IntPol",
"lldp_policy": "LLDP-TxRx-Enabled-IntPol",
"mcp_policy": "MCP_Enabled",
"pc_member_name": null,
"pc_policy": null,
"stp_policy": null
},
"msg": "APIC Error 400: Invalid request. Can not contain child 'rslacpPol' under parent 'uni/infra/funcprof/accportgrp-ACC_test_laptop_1'"
}
EXEC /bin/sh -c 'echo ~rohitborkar && sleep 0'
EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /Users/rohitborkar/.ansible/tmp
"&& mkdir /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693234.66-19918-71586901218594 && echo ansible-tmp-1599693234.66-19918-71586901218594="echo /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693234.66-19918-71586901218594
" ) && sleep 0'
Using module file /Users/rohitborkar/Documents/Ansible_MAC/ansible-aci/plugins/modules/aci_interface_policy_leaf_policy_group.py
PUT /Users/rohitborkar/.ansible/tmp/ansible-local-19911HsbS9B/tmpypBnAl TO /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693234.66-19918-71586901218594/AnsiballZ_aci_interface_policy_leaf_policy_group.py
EXEC /bin/sh -c 'chmod u+x /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693234.66-19918-71586901218594/ /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693234.66-19918-71586901218594/AnsiballZ_aci_interface_policy_leaf_policy_group.py && sleep 0'
EXEC /bin/sh -c '/usr/bin/python /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693234.66-19918-71586901218594/AnsiballZ_aci_interface_policy_leaf_policy_group.py && sleep 0'
EXEC /bin/sh -c 'rm -f -r /Users/rohitborkar/.ansible/tmp/ansible-tmp-1599693234.66-19918-71586901218594/ > /dev/null 2>&1 && sleep 0'
failed: [localhost] (item={u'aep': u'Phys_AEP', u'pc_policy': None, u'interface_policy_group': u'ACC_test_laptop_2', u'cdp_policy': u'CDP-Enabled-IntPol', u'stp_policy': None, u'link_level_policy': u'LnkSpd-Auto-IntPol', u'mcp_policy': u'MCP_Enabled', u'lag_type': u'leaf', u'pc_member_name': None, u'lldp_policy': u'LLDP-TxRx-Enabled-IntPol'}) => {
"ansible_loop_var": "item",
"changed": false,
"error": {
"code": "400",
"text": "Invalid request. Can not contain child 'rslacpPol' under parent 'uni/infra/funcprof/accportgrp-ACC_test_laptop_2'"
},
"invocation": {
"module_args": {
"aep": "Phys_AEP",
"annotation": null,
"cdp_policy": "CDP-Enabled-IntPol",
"certificate_name": null,
"description": null,
"egress_data_plane_policing_policy": null,
"fibre_channel_interface_policy": null,
"host": "10.16.254.222",
"hostname": "10.16.254.222",
"ingress_data_plane_policing_policy": null,
"l2_interface_policy": null,
"lag_type": "leaf",
"link_level_policy": "LnkSpd-Auto-IntPol",
"lldp_policy": "LLDP-TxRx-Enabled-IntPol",
"mcp_policy": "MCP_Enabled",
"monitoring_policy": null,
"name": "ACC_test_laptop_2",
"name_alias": null,
"output_level": "normal",
"output_path": null,
"owner_key": null,
"owner_tag": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"policy_group": "ACC_test_laptop_2",
"port": null,
"port_channel_policy": "",
"port_security_policy": null,
"priority_flow_control_policy": null,
"private_key": null,
"protocol": "https",
"slow_drain_policy": null,
"state": "present",
"storm_control_interface_policy": null,
"stp_interface_policy": "",
"timeout": 30,
"use_proxy": true,
"use_ssl": true,
"username": "admin",
"validate_certs": false
}
},
"item": {
"aep": "Phys_AEP",
"cdp_policy": "CDP-Enabled-IntPol",
"interface_policy_group": "ACC_test_laptop_2",
"lag_type": "leaf",
"link_level_policy": "LnkSpd-Auto-IntPol",
"lldp_policy": "LLDP-TxRx-Enabled-IntPol",
"mcp_policy": "MCP_Enabled",
"pc_member_name": null,
"pc_policy": null,
"stp_policy": null
},
"msg": "APIC Error 400: Invalid request. Can not contain child 'rslacpPol' under parent 'uni/infra/funcprof/accportgrp-ACC_test_laptop_2'"
}
PLAY RECAP *****************************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Rohits-MacBook-Pro:ansible-aci rohitborkar$
SUMMARY
Would like to be to create and modify Layer 3 Out Route Profiles. Including being able to manage the networks subtree and and adding and removing contracts.
ISSUE TYPE
Feature Idea
COMPONENT NAME
aci_l3out
ANSIBLE VERSION
ansible 2.5.2
OS / ENVIRONMENT
CentOS
EXPECTED RESULTS
Be able to create Layer 3 Out profiles under External Routed Networks and modifying the subtrees below it.
aci_epg module is misisng the ability to set EPG contract master associations which limits the ability for fully automated EPG creation when using inherited contracts which are useful for common infrastructure contracts such as AD, backups, monitoring.
SUMMARY
ansible.module_utils.network.aci.aci module is generating issues in custom module (uEPG) that is using this library. Issue appears to be in get_diff_children method:
def get_diff_children(self, aci_class):
proposed_children = self.proposed[aci_class].get('children')
if proposed_children:
child_updates = []
existing_children = self.existing[0][aci_class].get('children', []) """<<<<<<<< ISSUE IS HERE"""
This causes the line: aci.get_diff(aci_class='fvAEPg') from the uEPG module (listed below) to cause inconsistent results.
ISSUE TYPE
Bug Report
ISSUE OPENER iljdam
COMPONENT NAME
!component =lib/ansible/module_utils/network/aci/aci.py
Error seen in custom uEPG module based on native EPG module.
ANSIBLE VERSION
ansible 2.8.2
CONFIGURATION
OS / ENVIRONMENT
Test was done with ACI 3.2.6i, but error is ACI firmware agnostic
STEPS TO REPRODUCE
Run ansible_aci_send.yaml using the uEPG module and the host_data_created.json data set.
Problem appears in the first recurrence of the execution, in the case of delete uEPG using the following playbook to remove inherited EPGs from uEPG work from the second element of the ROLELIST (for every uEPG the first remove will fail and rest will be proceeded as expected):
uEPG:
host: 192.168.1.1
username: "admin"
password: "pass"
validate_certs: no
tenant: "TNT_TNT"
ap: "APP_ANP"
uepg: "{{ item.0.HOSTNAME }}"
bd: "BD_BD"
inherited_epg: "{{ item.1 }}"
state: absent
output_level: debug
register: query_result
with_subelements:
- "{{ list_uEPG.host_list }}"
- ROLELIST
ignore_errors: yes
The playbook, module and data used:
ansible_aci_send.yaml - the playbook
---
- name: test of using uEPG module
gather_facts: no
hosts: localhost
connection: local
tasks:
- name: include vars for templating
include_vars:
file: host_data_created.json
name: list_uEPG
## add section
- name: add EPGs from role list
aci_epg:
host: 192.168.1.1
username: "admin"
password: "pass"
validate_certs: no
name: "{{ item.1 }}"
tenant: "TNT_TNT"
ap: "APP_ANP"
bd: "BD_BD"
state: present
output_level: debug
with_subelements:
- "{{ list_uEPG.host_list }}"
- ROLELIST
ignore_errors: yes
- name: add inherit EPGs from uEPGs
uEPG:
host: 192.168.1.1
username: "admin"
password: "pass"
validate_certs: no
tenant: "TNT_TNT"
ap: "APP_ANP"
bd: "BD_BD"
uepg: "{{ item.0.HOSTNAME }}"
uepg_attribute_ip: "{{ item.0.IPADDRESS }}"
inherited_epg: "{{ item.1 }}"
state: present
output_level: debug
with_subelements:
- "{{ list_uEPG.host_list }}"
- ROLELIST
ignore_errors: yes
register: query_result_present
- name: rm inherit EPGs from uEPGs
uEPG:
host: 192.168.1.1
username: "admin"
password: "pass"
validate_certs: no
tenant: "TNT_TNT"
ap: "APP_ANP"
bd: "BD_BD"
uepg: "{{ item.0.HOSTNAME }}"
uepg_attribute_ip: "{{ item.0.IPADDRESS }}"
inherited_epg: "{{ item.1 }}"
state: absent
output_level: debug
register: query_result_absent
with_subelements:
- "{{ list_uEPG.host_list }}"
- ROLELIST
ignore_errors: yes
- copy: content="{{ query_result_present | to_nice_json }}" dest=uepg_present.json
- copy: content="{{ query_result_absent | to_nice_json }}" dest=uepg_absent.json
## end add section
uEPG.py - the implementation of the module
#!/usr/bin/python
# -*- coding: utf-8 -*-
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'certified'}
DOCUMENTATION = r'''
---
TBD
'''
EXAMPLES = r'''
TBD
'''
RETURN = r'''
TBD
'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.aci.aci import ACIModule, aci_argument_spec
def main():
argument_spec = aci_argument_spec()
argument_spec.update(
uepg=dict(type='str', aliases=['epg_name', 'name']), # Not required for querying all objects
bd=dict(type='str', aliases=['bd_name', 'bridge_domain']),
ap=dict(type='str', aliases=['app_profile', 'app_profile_name']), # Not required for querying all objects
tenant=dict(type='str', aliases=['tenant_name']), # Not required for querying all objects
description=dict(type='str', aliases=['descr']),
priority=dict(type='str', choices=['level1', 'level2', 'level3', 'unspecified']),
intra_epg_isolation=dict(choices=['enforced', 'unenforced']),
fwd_control=dict(type='str', choices=['none', 'proxy-arp']),
preferred_group=dict(type='bool'),
state=dict(type='str', default='query', choices=['present', 'absent', 'query']),
uepg_attribute_ip=dict(type='str'),
inherited_epg=dict(type='str'),
)
module = AnsibleModule(
argument_spec=argument_spec,
supports_check_mode=True,
required_if=[
['state', 'absent', ['ap', 'uepg', 'inherited_epg', 'tenant']],
['state', 'present', ['ap', 'uepg', 'uepg_attribute_ip', 'inherited_epg', 'tenant']],
],
)
aci = ACIModule(module)
uepg = module.params['uepg']
bd = module.params['bd']
description = module.params['description']
priority = module.params['priority']
intra_epg_isolation = module.params['intra_epg_isolation']
fwd_control = module.params['fwd_control']
preferred_group = aci.boolean(module.params['preferred_group'], 'include', 'exclude')
state = module.params['state']
tenant = module.params['tenant']
ap = module.params['ap']
uepg_attribute_ip = module.params['uepg_attribute_ip']
inherited_epg = module.params['inherited_epg']
inherited_epg_dn = 'uni/tn-{0}/ap-{1}/epg-{2}'.format(tenant, ap, inherited_epg)
uepg_dn = 'uni/tn-{0}/ap-{1}/epg-{2}'.format(tenant, ap, uepg)
to_del = 'deleted'
aci.construct_url(
root_class=dict(
aci_class='fvTenant',
aci_rn='tn-{0}'.format(tenant),
module_object=tenant,
target_filter={'name': tenant},
),
subclass_1=dict(
aci_class='fvAp',
aci_rn='ap-{0}'.format(ap),
module_object=ap,
target_filter={'name': ap},
),
subclass_2=dict(
aci_class='fvAEPg',
aci_rn='epg-{0}'.format(uepg),
module_object=uepg,
target_filter={'name': uepg},
),
child_classes=['fvRsBd', 'fvCrtrn', 'fvRsSecInherited'],
)
aci.get_existing()
if state == 'present':
aci.payload(
aci_class='fvAEPg',
class_config=dict(
name=uepg,
descr=description,
prio=priority,
pcEnfPref=intra_epg_isolation,
fwdCtrl=fwd_control,
isAttrBasedEPg='true',
prefGrMemb=preferred_group,
),
child_configs=[
dict(fvRsBd=dict(
attributes=dict(
#tnFvBDName=bd,
tnFvBDName=bd,
),
),
),
dict(fvRsSecInherited=dict(
attributes=dict(
# tnFvBDName=bd,
tDn=inherited_epg_dn,
),
),
),
dict(fvCrtrn=dict(
attributes=dict(
scope='scope-bd',
match="any",
name='default',
),
children=[dict(
fvIpAttr=dict(
attributes=dict(
ip=uepg_attribute_ip,
name='0',
),
),
)],
),
)
],
)
aci.get_diff(aci_class='fvAEPg')
aci.post_config()
elif state == 'absent':
aci.payload(
aci_class='fvAEPg',
class_config=dict(
dn=uepg_dn,
name=uepg,
descr=description,
prio=priority,
pcEnfPref=intra_epg_isolation,
fwdCtrl=fwd_control,
isAttrBasedEPg='true',
prefGrMemb=preferred_group,
),
child_configs=[
dict(fvRsSecInherited=dict(
attributes=dict(
annotation='',
tDn=inherited_epg_dn,
status=to_del,
),
),
)
],
)
aci.get_diff(aci_class='fvAEPg')
aci.post_config()
aci.exit_json()
if __name__ == "__main__":
main()
host_data_created.json - the data file used with info for the uEPGs
"host_list": [
{ "HOSTNAME": "host1","ENV": "os","IPADDRESS": "1.1.1.1","ROLELIST":[ "role_1", "type_1", "group_1", "role_12", "location_1", "domain_1"] },
{ "HOSTNAME": "host2","ENV": "os","IPADDRESS": "2.2.2.2","ROLELIST":[ "role_2", "type_2", "role_3", "sgroup_2", "location_3", "domain_3", "role_13"] },
{ "HOSTNAME": "host3","ENV": "os","IPADDRESS": "3.3.3.3","ROLELIST":[ "type_3", "sgroup_2", "location_1", "domain_4", "role_5"] },
{ "HOSTNAME": "host4": "os","IPADDRESS": "4.4.4.4","ROLELIST":[ "role_4", "type_5", "sgroup_3", "location_5", "domain_6", "role_6"] }
]
}
EXPECTED RESULTS
This is how it looks for a working element:
Key: {"fvAEPg": {"attributes": {"isAttrBasedEPg": "true"}, "children": [{"fvRsSecInherited": {"attributes": {"status": "deleted", "tDn": "uni/tn-sd/ap-APP_ANP/epg-role_1"}}}]}}
ACTUAL RESULTS
Run the playbook ansible_aci_send.yaml and you will see that one element from list named ROLELIST fails:
failed: [bdsol-aci16-apic1] (item=[{u'HOSTNAME': u'host1', u'IPADDRESS': u'1.1.1.1', u'ENV': os'}, u'role_1']) => {"ansible_loop_var": "item", "changed": false, "error": {"code": "822", "text": "naming property ('fvRsSecInherited.tDn') is not set."}, "filter_string": "?rsp-prop-include=config-only&rsp-subtree-class=fvCrtrn,fvRsBd,fvRsSecInherited&rsp-subtree=full", "imdata": [{"error": {"attributes": {"code": "822", "text": "naming property ('fvRsSecInherited.tDn') is not set."}}}]
Looking at what is being POSTed to APIC, we see that actually the Ansible is not sending the "tDn" element:
[Full request URI: http://bdsol-aci16-apic1/api/mo/uni/tn-sd/ap-APP_ANP/epg-role1.json]
Key: {"fvAEPg": {"attributes": {"isAttrBasedEPg": "true"}, "children": [{"fvRsSecInherited": {"attributes": {"status": "deleted"}}}]}}
SUMMARY
Gets rid of the last Could not lex literal_block as "guess". Highlighting skipped. errors in the docs build.
Thanks to @mattclay for the code revisions to the example!
Related to #63217.
ISSUE OPENER acozine
ISSUE LINK ansible/ansible#68095
ISSUE TYPE
Docs Pull Request
COMPONENT NAME
ACI
docs.ansible.com
SUMMARY
ISSUE OPENER nkatarmal-crest
ISSUE LINK ansible/ansible#67773
ISSUE TYPE
Added a pause attribute to the aci_config_rollback.
Feature Pull Request
COMPONENT NAME
aci_config_rollback
ADDITIONAL INFORMATION
Linked to #16
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.