Skip to content

Setting up Ansible To a Red Hat Server

Ansible can be installed easily with yum, but you may have to add Ansible Engine repository as in the installation manual https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html

Sample playbook to test connectivity to Cisco APIC will be created too.

After installation is complete, Ansible is ready to be set up. Basically all it needs is an inventory file and a playbook. I am testing it with Cisco ACI version 4.2, so instead of username and password, I'm using private key for authentication. This is due to that ACI contains brute-force prevention mechanisms if using a password and repetitive ansible tasks will cause this.

Inventory file is basically a file that contains your device hostname and IP address. For example, I am using hosts.ini in /ansible directory, which contains three APICs:

hosts.ini
[apic]
APIC1 ansible_ssh_host=172.30.0.1
APIC2 ansible_ssh_host=172.30.0.2
APIC3 ansible_ssh_host=172.30.0.3


OpenSSL can be used to generate a private key and a certificate:

[root@localhost]$ openssl req -newkey rsa:2048 -nodes -keyout ansible.key-x509 -days 365 -out ansible.crt

Associate the certificate in ACI user. Create a local user called "ansible" with read-all role, and set the certificate there.

APIC1# show running-config username ansible
# Command: show running-config username ansible
# Time: Thu Jul 23 09:44:25 2020
username ansible
    domain common
      role read-all
        exit
      exit
    domain all
      role admin
        priv-type writePriv
        exit
      role read-all
        exit
      exit
    certificate ansible
      data "-----BEGIN CERTIFICATE----- OUTPUT-OMITTED
 -----END CERTIFICATE-----"
      exit
    exit


Then we can create a sample playbook that queries ACI tenants and EPGs. I am using the private key and certificate in the variables so they are easy to be copied for tasks. Make sure that host matches the hostname in hosts.ini inventory file :-)

# aci-query-tenants.yaml
- name: Test playbook to gather data
  hosts: APIC1
  connection: local
  gather_facts: no

 vars:
   apic_username: "ansible"
   private_key: "/ansible/ansible.key"
   certificate_name: "ansible"

## TASKS ##

 tasks:
 - name: Query Tenants
   aci_tenant:
     hostname: "{{ ansible_host }}"
     username: "{{ apic_username }}"
     private_key: "{{ private_key }}"
     validate_certs: no
     state: query
 - name: Query EPGs
   aci_epg:
     hostname: "{{ ansible_host }}"
     username: "{{ apic_username }}"
     private_key: "{{ private_key }}"
     validate_certs: no
     state: query


Run the playbook with ansible-playbook command. Output will be in JSON format as in this example.

[root@localhost]$ ansible-playbook -i hosts.ini aci-query-tenants.yaml -v
[test@dcn1pinl151 ansible]$ ansible-playbook -i hosts.ini aci-query-tenants.yaml -v | more
Using etc/ansible/ansible.cfg as config file

PLAY [Test playbook to gather data] ******************************************************

TASK [Query Tenants] **********************************************************************

ok: [APIC1] => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "current": [{"fvTenant": {"attributes": {"annotation": "", "childAction": "", "descr": "", "dn": "uni/tn-TEST", "extMngdBy": "", "lcOwn": "local", "modTs": "2018-11-27T07:33:19.661+01:00", "monPolDn": "uni/tn-common/monepg-default", "name": "TEST", "nameAlias": "", "ownerKey": "", "ownerTag": "", "status": "", "uid": "15374"}}},{"fvTenant": {"attributes": {"annotation": "", "childAction": "", "descr": "", "dn": "uni/tn-mgmt", "extMngdBy": "", "lcOwn": "local", "modTs": "2018-11-13T04:36:52.227+01:00", "monPolDn": "uni/tn-common/monepg-default", "name": "mgmt", "nameAlias": "", "ownerKey": "", "ownerTag": "", "status":"", "uid": "0"}}}, {"fvTenant": {"attributes": {"annotation": "", "childAction": "", "descr": "", "dn": "uni/tn-common", "extMngdBy": "", "lcOwn": "local", "modTs": "2018-11-13T04:36:48.184+01:00", "monPolDn": "uni/tn-common/monepg-default", "name": "common", "nameAlias": "", "ownerKey": "", "ownerTag": "", "status": "", "uid": "0"}}}]}

TASK [Query EPGs] **********************************************************************
ok: [APIC1] => {"changed": false, "current": [{"fvAEPg": {"attributes": {"annotation": "", "childAction": "", "configIssues": "", "configSt": "applied", "descr": "Test EPG", "dn": "uni/tn-TEST/ap-TEST_AP/epg-TEST_EPG", "exceptionTag": "", "extMngdBy": "", "floodOnEncap": "disabled", "fwdCtrl": "", "hasMcastSource": "no", "isAttrBasedEPg": "no", "isS
haredSrvMsiteEPg": "no", "lcOwn": "local", "matchT": "AtleastOne", "modTs": "2018-11-15T05:38:22.777+01:00", "monPolDn": "uni/tn-common/monepg-default", "name": "TEST_EPG", "nameAlias":
"", "pcEnfPref": "unenforced", "pcTag": "16472", "prefGrMemb": "exclude", "prio": "unspecified", "scope": "2392064", "shutdown": "no", "status": "", "triggerSt": "triggerable", "txId": "97
99832789158287484", "uid": "15374"}, "children": [{"fvRsBd": {"attributes": {"annotation": "", "childAction": "", "extMngdBy": "", "forceResolve": "yes", "lcOwn": "local", "modTs": "2018-11
-15T05:38:22.702+01:00", "monPolDn": "uni/tn-common/monepg-default", "rType": "mo", "rn": "rsbd", "state": "formed", "stateQual": "none", "status": "", "tCl": "fvBD", "tContextDn": "", "tDn
": "uni/tn-PROD/BD-TEST_BD", "tRn": "BD-TEST_BD", "tType": "name", "tnFvBDName": "TEST_BD", "uid": "0"}, "children": [{"fvSubnetBDDefCont": {"attributes": {"bddefDn": "uni/bd-[u
ni/tn-PROD/BD-TEST_BD]-isSvc-no", "childAction": "deleteNonPresent", "lcOwn": "local", "modTs": "2018-11-15T05:38:22.702+01:00", "monPolDn": "uni/tn-common/monepg-default", "name": "",
"nameAlias": "", "rn": "subnetBddefDn-[uni/bd-[uni/tn-TEST/BD-TEST_BD]-isSvc-no]", "status": ""}}}]}}]}},

PLAY RECAP ********************************************************************

APIC1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0


Trackbacks

No Trackbacks

Comments

Display comments as Linear | Threaded

No comments

Add Comment

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.
E-Mail addresses will not be displayed and will only be used for E-Mail notifications.
Form options

Submitted comments will be subject to moderation before being displayed.