Under the majority of the role directories you'll notice a ".yml" file. Playbooks are written in a very simple markup language called YAML, which stands for Yet Another Markup Language. YAML is used as it's even easier to read than data structure formats such as XML or JSON.
YAML files optionally begin with --- at the top of the file to signify the start of the file. Following the file start, comes the Ansible modules written in YAML syntax. YAML syntax for Ansible modules are expressed as a list of key/value pairs. Below you can see an example of YAML syntax that contains a list of dictionaries and where the dictionaries contain lists:
- name: CREATE ACI TENANT
aci_tenant:
tenant: "My_Tenant"
descr: "This Tenant is for testing only"
host: "x.x.x.x"
username: "admin"
password: "superpass"
validate_certs: no
As you can see the first thing, we are doing is to introduce you is to an specific ansible module. In this case the
aci_tenant
is a ansible module . There are many ansible modules available and more added with each release.
Keep the reference to the
ACI documentation for Ansible saved.
Also the link for modules
is available. Just lick on the link and then click on content button.
An important key to any programing language is variables and Ansible is no different. If you would have had to create 100 tenants in an ACI fabric, you dont want to have to create 100 different YAML files with the configuration that we showed above. That makes no sense.
Ansible allows the placement of variables in the YAML file via what we know as templates. This template system is called Jinja Templates and is used in many aspects of Python, the core base of Ansible. This is how the syntax would be like for the example above:
- name: CREATE ACI TENANT
aci_tenant:
tenant: "{{ tenant_name }}"
descr: "{{ descr }}"
host: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
validate_certs: no
Variables can be defined in various locations and Ansible has a precedence system for understanding what and when a variable would be overridden if used in more than one location. The precedence for a variable can be seen below. As an example, a variable in the role defaults directory would be overridden by a variable in the playbook global_vars/all directory and file. Further, both of these are overridden by the local vars directory within the specific role, role vars.
As an example, each of these network modules have basic requirements for arguments to access the device, albeit, some of these parameters may not apply to the network operating system you work with:
You are now going to create a new file in the group_vars directory under the playbook/aci
directory. You will be doing this in the Visual Studio Code (VSC) editor. Right click on the
editor left pane where the group_vars
directory is and then click on New File
to create the all
file in group_vars
and populate the contents of the file
for the ansible_connection
, username
, password
, and protocol
to be
used in the ACI tasks.
group_vars/all is where you place universal variables that apply for all devices.
This new file will be called all
---
ansible_connection: local
user: aciproglab04
pass: cisco.123
For each role you're now going to create variables to be used per device that are common across all devices
specified within the role. The device specific variables can be defined under the host_vars directory
for each device - which we will not be doing for this lab.
The common variables to be used across all devices in the role will be defined under roles/apic/vars/main.yml
.
For this lab you are going to be leveraging a specific user that has write permissions for a specific tenant. For this reason we have created the Tenant for you. The ACI Tenant provides a user space domain for creating network elements and is controlled via RBAC.
You are going to edit a file that was created by Ansible Galaxy when you created your apic
role.
This file is called main.yml
and is located in your directory here: ~/ltrdcn-3225/ansible/playbooks/aci/roles/apic/vars/main.yml
.
Navigate to this file in the left Explorer pane and double click the file to open it.
Inset the variables for your tenant, VRFs, and application profile after the # vars file for apic
comment:
tenant: aciproglab04
vrf1: POD04_vrf_1
vrf2: POD04_vrf_2
app_profile_name: POD04_APP
The Ansible documentation for each network module provides a synopsis of what function the module performs and a table of parameters or keys. The tabulated parameters inform the user which parameters are required for the module to function as a task, which parameters are optional, and what the defaults are for parameters. There are many network modules that exist to configure Tenants, VRFs, BDs, APs, EPGs, Contracts, etc. Some of the modules that are available and the ones you will use today are the following:
aci_vrf
aci_bd
aci_ap
aci_epg
Cisco is commited to Ansible and continues to expand the library with new modules in the pursuit
of having 100% correlation between the module and ACI capabilities. In a place where an Ansible module is
not available, Cisco has developed a specific module that allows you to send specific ACI configuration objects into the fabric
via the REST interface called aci_rest
.
In the editor find the file main.yml
under the roles/apic/tasks
directory and open it by double-clicking on it.
You will be adding the following Ansible tasks using the beforementioned modules in YAML format after the # tasks file for apic
comment.
Pay attention to the line numbers as they should match with your editor.
- name: CREATE ACI TENANT VRF1
aci_vrf:
vrf: "{{ vrf1 }}"
state: present
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
- name: CREATE ACI TENANT VRF2
aci_vrf:
vrf: "{{ vrf2 }}"
state: present
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
- name: CREATE BRIDGE DOMAIN FOR DB
aci_bd:
bd: "database"
description: 'POD04 Database Bridge Domain'
state: present
vrf: "{{ vrf1 }}"
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
- name: CREATE SUBNET FOR DB BRIDGE DOMAIN
aci_bd_subnet:
bd: "database"
subnet_name: "POD04_subnet1"
description: 'POD04 Subnet for Database Bridge Domain'
gateway: "10.100.104.1"
mask: 24
scope: private
state: present
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
- name: CREATE BRIDGE DOMAIN FOR JAVA APP
aci_bd:
bd: "java_app"
description: 'POD04 JAVA APP Bridge Domain'
state: present
vrf: "{{ vrf1 }}"
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
- name: CREATE SUBNET FOR JAVA APP BRIDGE DOMAIN
aci_bd_subnet:
bd: "java_app"
subnet_name: "POD04_bd2_subnet1"
description: 'POD04 subnet for Java App Bridge Domain'
gateway: "10.100.204.1"
mask: 24
scope: private
state: present
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
In the editor, under the same file you will be adding the following modules. You will need to hit the Enter (or Return) key after your line 82.
- name: Create ACI Tenant Application Profile
aci_ap:
ap: "POD04_APP"
description: 'POD04 Application Profile'
state: present
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
- name: Create Database EPG
aci_epg:
ap: "POD04_APP"
bd: "database"
epg: "database"
description: 'POD04 Database EPG'
state: present
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
- name: Create Java APP EPG
aci_epg:
ap: "POD04_APP"
bd: "java_app"
epg: "java_app"
description: 'POD04 Java APP EPG'
state: present
tenant: "{{ tenant }}"
hostname: "{{ inventory_hostname }}"
username: "{{ user }}"
password: "{{ pass }}"
use_ssl: yes
validate_certs: false
Ansible refers to its host file as an inventory file. The inventory file has a default location in
/etc/ansible/hosts, but can also be specified directly within a playbook locally and used with the
-i hosts
option, where hosts happens to be in the inventory file name. Within the inventory file,
you can simply list all the devices/hosts or make use of group names using brackets which classifies
devices you are controlling at what times and for what purpose.
The host file will be created in the location ~/ltrdcn-3225/ansible/playbooks/aci
. Please
goto this location and create the file hosts
.
# hosts file for Ansible playbook
[apic]
10.0.226.41
As previously mentioned, Ansible calls its configuration and orchestration framework "playbooks" and is a collections of "play(s)" or tasks for configuration management and deployment to a device or multiple devices. While playbooks can be represented as a single file, Ansible best practices recommend a particular directory structure for playbooks that you built using roles for better organization and reuse. You built all of this over the last three sections. You now need to build the main playbook file, which would look like the below:
The below playbook file you will use for this lab designates the following behaviors, for each role ‘x’:
The host file will be created in the location ~/ltrdcn-3225/ansible/playbooks/aci
. Please
goto this location and create the file site.yml
and add the following content.
---
# main playbook
- hosts: apic
roles:
- role: apic
Now we can proceed to execute the ansible playbooks.