Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the easy-accordion-free domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php on line 6114

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the zoho-flow domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php on line 6114

Notice: Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the wordpress-seo domain was triggered too early. This is usually an indicator for some code in the plugin or theme running too early. Translations should be loaded at the init action or later. Please see Debugging in WordPress for more information. (This message was added in version 6.7.0.) in /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php on line 6114

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893

Warning: Cannot modify header information - headers already sent by (output started at /home/mother99/jacksonholdingcompany.com/wp-includes/functions.php:6114) in /home/mother99/jacksonholdingcompany.com/wp-includes/rest-api/class-wp-rest-server.php on line 1893
{"id":2164,"date":"2024-01-17T20:52:09","date_gmt":"2024-01-17T20:52:09","guid":{"rendered":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/"},"modified":"2024-01-17T20:52:09","modified_gmt":"2024-01-17T20:52:09","slug":"how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm","status":"publish","type":"post","link":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/","title":{"rendered":"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm"},"content":{"rendered":"

How can Ansible help people building simulations with Cisco Modeling Labs (CML)?<\/p>\n

Similar to <\/span>Terraform<\/span><\/a>, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous\u2026 Read more on Cisco Blogs<\/a><\/span><\/p>\n

\u200b<\/p>\n

How can Ansible help people building simulations with Cisco Modeling Labs (CML)?<\/p>\n

Similar to Terraform<\/a>, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous Deployment (CI\/CD) DevOps methodologies. They are both a type of Infrastructure as Code (IaC) or Infrastructure as Data that allow you to render your infrastructure as text files and control it using tools such as Git. The advantage is reproducibility, consistency, speed, and the knowledge that, when you change the code, people approve, and it gets tested before it\u2019s pushed out to your production network. This paradigm allows enterprises to run their network infrastructure in the same way they run their software and cloud practices. Afterall, the infrastructure is there to support the apps, so why manage them differently?\u00a0<\/p>\n

Although overlaps exist in the capabilities of Terraform and Ansible, they are very complementary. While Terraform is better at the initial deployment and ensuring ongoing consistency of the underlying infrastructure, Ansible is better at the initial configuration and ongoing management of the things that live in that infrastructure, such as systems, network devices, and so on.\u00a0<\/p>\n

In a common workflow in which an operator wants to make a change to the network, let\u2019s say adding a new network to be advertised via BGP, a network engineer would specify that change in the code or more likely as configuration data in YAML or JSON. In a typical CI workflow, that change would need to be approved by others for correctness or adherence to corporate and security concerns, for instance. In addition to the eyeball tests, a series of automated testing validates the data and then deploys the proposed change in a test network. Those tests can be run in a physical test network, a virtual test network, or a combination of the two. That flow might look like the following:\u00a0<\/p>\n\n

The advantage of leveraging virtual test networks is profound. The cost is dramatically lower, and the ability to automate testing is increased significantly. For example, a network engineer can spin up and configure a new, complex topology multiple times without the likelihood of old tests messing up the accuracy of the current testing. Cisco Modeling Labs is a great tool for this type of test.\u00a0<\/p>\n

Here\u2019s where the Ansible CML Collection comes in. Similar to the CML Terraform integration covered in a previous blog<\/a>, the Ansible CML Collection can automate the deployment of topologies in CML for testing. The Ansible CML Collection has modules to create, start, and stop a topology and the hosts within it, but more importantly, it has a dynamic inventory plugin for getting information about the topology. This is important for automation because topologies can change. Or multiple topologies could exist, depending on the tests being performed. If your topology uses dynamic host configuration protocol (DHCP) and\/or CML\u2019s PATty functionality, the information for how Ansible communicates with the nodes needs to be communicated to the playbook.\u00a0<\/p>\n

Let\u2019s go over some of the features of the Ansible CML Collection\u2019s dynamic inventory plugin.\u00a0<\/p>\n

First, we need to install the collection:\u00a0<\/p>\n

ansible-galaxy collection install cisco.cml\u00a0 <\/p>\n

Next, we create a cml.yml in the inventory with the following contents to tell Ansible to use the Ansible CML Collection\u2019s dynamic inventory plugin:\u00a0<\/p>\n

plugin: cisco.cml.cml_inventory\u00a0
\ngroup_tags: network, ios, nxos, router <\/p>\n

In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook:\u00a0<\/p>\n\n

In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook:<\/p>\n

CML_USERNAME: Username for the CML user
\nCML_PASSWORD: Password for the CML user
\nCML_HOST: The CML host
\nCML_LAB: The name of the lab\u00a0<\/p>\n

Once the plugin knows how to communicate with the CML server and which lab to use, it can return information about the nodes in the lab:\u00a0<\/p>\n

ok: [hq-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “cml_facts”: {\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “config”: “hostname hq-rtr1nvrf definition Mgmt-intfn!naddress-family ipv4nexit-address-familyn!naddress-family ipv6nexit-address-familyn!nusername admin privilege 15 secret 0 adminncdp runnno aaa new-modelnip domain-name mdd.cisco.comn!ninterface GigabitEthernet1nvrf forwarding Mgmt-intfnip address dhcpnnegotiation autonno cdp enablenno shutdownn!ninterface GigabitEthernet2ncdp enablen!ninterface GigabitEthernet3ncdp enablen!ninterface GigabitEthernet4ncdp enablen!nip http servernip http secure-servernip http max-connections 2n!nip ssh time-out 60nip ssh version 2nip ssh server algorithm encryption aes128-ctr aes192-ctr aes256-ctrnip ssh client algorithm encryption aes128-ctr aes192-ctr aes256-ctrn!nline vty 0 4nexec-timeout 30 0nabsolute-timeout 60nsession-limit 16nlogin localntransport input sshn!nend”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “cpus”: 1,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “data_volume”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “image_definition”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “interfaces”: [\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv4_addresses”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv6_addresses”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “mac_address”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “name”: “Loopback0”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “state”: “STARTED”\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 },\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv4_addresses”: [\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “192.168.255.199”\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv6_addresses”: [],\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “mac_address”: “52:54:00:13:51:66”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “name”: “GigabitEthernet1”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “state”: “STARTED”\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “node_definition”: “csr1000v”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ram”: 3072,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “state”: “BOOTED”\u00a0
\n\u00a0\u00a0\u00a0 }\u00a0
\n}\u00a0 <\/p>\n

The first IPv4 address found (in order of the interfaces) is used as `ansible_host` to enable the playbook to connect to the device. We can use the cisco.cml.inventory playbook included in the collection to show the inventory. In this case, we only specify that we want devices that are in the \u201crouter\u201d group created by the inventory plugin as informed by the tags on the devices:\u00a0<\/p>\n

mdd % ansible-playbook cisco.cml.inventory –limit=router\u00a0
\nok: [hq-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: hq-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.199:22”\u00a0
\n}\u00a0
\nok: [hq-rtr2] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: hq-rtr2(csr1000v), State: BOOTED, Address: 192.168.255.53:22”\u00a0
\n}\u00a0
\nok: [site1-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: site1-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.63:22”\u00a0
\n}\u00a0
\nok: [site2-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: site2-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.7:22”\u00a0
\n}\u00a0 <\/p>\n

In addition to group tags, the CML dynamic inventory plugin will also parse tags to pass information from PATty and to create generic inventory facts:\u00a0<\/p>\n\n

If a CML tag is specified that matches `^pat:(?:tcp|udp)?:?(d+):(d+)`, the CML server address (as opposed to the first IPv4 address found) will be used for `ansible_host`. To change `ansible_port` to point to the translated SSH port, the tag `ansible:ansible_port=2020` can be set. These two tags tell the Ansible playbook to connect to port 2020 of the CML server to automate the specified host in the topology. The `ansible:` tag can also be used to specify other host facts. For example, the tag `ansible:nso_api_port=2021` can be used to tell the playbook the port to use to reach the Cisco NSO API. Any arbitrary fact can be set in this way.\u00a0<\/p>\n

Getting started\u00a0<\/h2>\n

Trying out the CML Ansible Collection is easy. You can use the playbooks provided in the collection to load and start a topology in your CML server. To start, define the environment variable that tells the collection how to access your CML server:\u00a0<\/p>\n

% export CML_HOST=my-cml-server.my-domain.com\u00a0
\n% export CML_USERNAME=my-cml-username\u00a0
\n% export CML_PASSWORD=my-cml-password\u00a0<\/p>\n

The next step is to define your topology file. This is a standard topology file you can export from CML. There are two ways to define the topology file. First, you can use\u00a0 an environment variable:\u00a0<\/p>\n

% export CML_LAB=my-cml-labfile\u00a0<\/p>\n

Alternatively, you can specify the topology file when you run the playbook as an extra\u2013var.\u00a0 For example, to spin up a topology using the built in cisco.cml.build<\/em> playbook:\u00a0<\/p>\n

% ansible-playbook cisco.cml.build -e wait=’yes’ -e cml_lab_file=topology.yaml <\/p>\n

This command loads and starts the topology; then it waits until all nodes are running to complete.\u00a0 If -e startup=\u2019host\u2019<\/em> is specified, the playbook will start each host individually as opposed to starting them all at once.\u00a0 This allows for the config to be generated and fed into the host on startup.\u00a0 When cml_config_file is defined in the host\u2019s inventory, it is parsed as a Jinja file and fed into that host as config at startup.\u00a0 This allows for just-in-time configuration to occur.\u00a0<\/p>\n

Once the playbook completes, you can use another built-in playbook, cisco.cml.inventory<\/em>, to get the inventory for the topology.\u00a0 In order to use it, first create a cml.yml<\/em> in the inventory directory as shown above, then run the playbook as follows:\u00a0<\/p>\n

% ansible-playbook cisco.cml.inventory\u00a0
\nPLAY [cml_hosts] **********************************************************************\u00a0
\nTASK [debug] **********************************************************************\u00a0
\nok: [WAN-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: WAN-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.53:22”\u00a0
\n}\u00a0
\nok: [nso1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: nso1(ubuntu), State: BOOTED, Address: my-cml-server.my-domain.com:2010”\u00a0
\n}\u00a0
\nok: [site1-host1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: site1-host1(ubuntu), State: BOOTED, Address: site1-host1:22”\u00a0
\n}\u00a0<\/p>\n

In this truncated output, three different scenarios are shown.\u00a0 First, WAN-rtr1<\/em> is assigned the DHCP address it received for its ansible_host value, and ansible port <\/em>is 22<\/em>. If the host running the playbook has IP connectivity (either in the topology or a network connected to the topology with an external connector), it will be able to reach that host.\u00a0<\/p>\n

The second scenario shows an example of the PATty functionality with the host nso1<\/em> in which the dynamic inventory plugin reads those tags to determine that the host is available through the CML server\u2019s interface (i.e. ansible_host<\/em> is set to my-cml-server.my-domain.com<\/em>).\u00a0 Also, it knows that ansible_port should be set to the port specified in the tags (i.e. 2010).\u00a0 After these values are set, the ansible playbook can reach the host in the topology using the PATty functionality in CML.\u00a0<\/p>\n

The last example, site1-host1<\/em>, shows the scenario in which the CML dynamic inventory script can either find a DHCP allocated address or tags to specify to what ansible_host<\/em> should be set, so it uses the node name.\u00a0 For the playbook to reach those hosts, it would have to have IP connectivity and be able to resolve the node name to an IP address.\u00a0<\/p>\n

These built-in playbooks show examples of how to use the functionality in the CML Ansible Collection to build your own playbooks, but you can also use them directly as part of your pipeline.\u00a0 In fact, we often use them directly in the pipelines we build for customers.\u00a0<\/p>\n

If you want to learn more about the CML Ansible Collection, you can find it in Ansible Galaxy as well as on Github<\/a>.\u00a0<\/p>\n

You can also find a full, IaC CI\/CD pipeline using these modules here<\/a>.<\/p>\n

Join the\u202fCisco Learning Network<\/a>\u202ftoday for free.<\/p>\n

Follow Cisco Learning & Certifications<\/strong><\/h2>\n

Twitter<\/a>\u202f|\u202fFacebook<\/a>\u202f|\u202fLinkedIn<\/a>\u202f|\u202fInstagram<\/a><\/strong>\u202f|\u202fYouTube<\/a><\/strong><\/h3>\n

Use\u202f#CiscoCert<\/strong>\u202fto join the conversation.<\/p>\n

\n\t\tShare\n
\n
<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t <\/a>\n\t<\/div>\n<\/div>\n<\/div>\n
Share:<\/div>\n
\n
\n
<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t <\/a>\n\t<\/div>\n<\/div>\n<\/div>\n

\u00a0\u00a0Ansible can be used with CML (Cisco Modeling Labs) to automate the deployment and management of network infrastructure, offering reproducibility, consistency, and automation in network infrastructure management.\u00a0\u00a0Read More<\/a>\u00a0Cisco Blogs\u00a0<\/p>","protected":false},"excerpt":{"rendered":"

<\/p>\n

How can Ansible help people building simulations with Cisco Modeling Labs (CML)?<\/p>\n

Similar to <\/span>Terraform<\/span><\/a>, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous\u2026 Read more on Cisco Blogs<\/a><\/span><\/p>\n

\u200b<\/p>\n

How can Ansible help people building simulations with Cisco Modeling Labs (CML)?<\/p>\n

Similar to Terraform<\/a>, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous Deployment (CI\/CD) DevOps methodologies. They are both a type of Infrastructure as Code (IaC) or Infrastructure as Data that allow you to render your infrastructure as text files and control it using tools such as Git. The advantage is reproducibility, consistency, speed, and the knowledge that, when you change the code, people approve, and it gets tested before it\u2019s pushed out to your production network. This paradigm allows enterprises to run their network infrastructure in the same way they run their software and cloud practices. Afterall, the infrastructure is there to support the apps, so why manage them differently?\u00a0<\/p>\n

Although overlaps exist in the capabilities of Terraform and Ansible, they are very complementary. While Terraform is better at the initial deployment and ensuring ongoing consistency of the underlying infrastructure, Ansible is better at the initial configuration and ongoing management of the things that live in that infrastructure, such as systems, network devices, and so on.\u00a0<\/p>\n

In a common workflow in which an operator wants to make a change to the network, let\u2019s say adding a new network to be advertised via BGP, a network engineer would specify that change in the code or more likely as configuration data in YAML or JSON. In a typical CI workflow, that change would need to be approved by others for correctness or adherence to corporate and security concerns, for instance. In addition to the eyeball tests, a series of automated testing validates the data and then deploys the proposed change in a test network. Those tests can be run in a physical test network, a virtual test network, or a combination of the two. That flow might look like the following:\u00a0<\/p>\n

The advantage of leveraging virtual test networks is profound. The cost is dramatically lower, and the ability to automate testing is increased significantly. For example, a network engineer can spin up and configure a new, complex topology multiple times without the likelihood of old tests messing up the accuracy of the current testing. Cisco Modeling Labs is a great tool for this type of test.\u00a0<\/p>\n

Here\u2019s where the Ansible CML Collection comes in. Similar to the CML Terraform integration covered in a previous blog<\/a>, the Ansible CML Collection can automate the deployment of topologies in CML for testing. The Ansible CML Collection has modules to create, start, and stop a topology and the hosts within it, but more importantly, it has a dynamic inventory plugin for getting information about the topology. This is important for automation because topologies can change. Or multiple topologies could exist, depending on the tests being performed. If your topology uses dynamic host configuration protocol (DHCP) and\/or CML\u2019s PATty functionality, the information for how Ansible communicates with the nodes needs to be communicated to the playbook.\u00a0<\/p>\n

Let\u2019s go over some of the features of the Ansible CML Collection\u2019s dynamic inventory plugin.\u00a0<\/p>\n

First, we need to install the collection:\u00a0<\/p>\n

ansible-galaxy collection install cisco.cml\u00a0 <\/p>\n

Next, we create a cml.yml in the inventory with the following contents to tell Ansible to use the Ansible CML Collection\u2019s dynamic inventory plugin:\u00a0<\/p>\n

plugin: cisco.cml.cml_inventory\u00a0
\ngroup_tags: network, ios, nxos, router <\/p>\n

In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook:\u00a0<\/p>\n

In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook:<\/p>\n

CML_USERNAME: Username for the CML user
\nCML_PASSWORD: Password for the CML user
\nCML_HOST: The CML host
\nCML_LAB: The name of the lab\u00a0<\/p>\n

Once the plugin knows how to communicate with the CML server and which lab to use, it can return information about the nodes in the lab:\u00a0<\/p>\n

ok: [hq-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “cml_facts”: {\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “config”: “hostname hq-rtr1nvrf definition Mgmt-intfn!naddress-family ipv4nexit-address-familyn!naddress-family ipv6nexit-address-familyn!nusername admin privilege 15 secret 0 adminncdp runnno aaa new-modelnip domain-name mdd.cisco.comn!ninterface GigabitEthernet1nvrf forwarding Mgmt-intfnip address dhcpnnegotiation autonno cdp enablenno shutdownn!ninterface GigabitEthernet2ncdp enablen!ninterface GigabitEthernet3ncdp enablen!ninterface GigabitEthernet4ncdp enablen!nip http servernip http secure-servernip http max-connections 2n!nip ssh time-out 60nip ssh version 2nip ssh server algorithm encryption aes128-ctr aes192-ctr aes256-ctrnip ssh client algorithm encryption aes128-ctr aes192-ctr aes256-ctrn!nline vty 0 4nexec-timeout 30 0nabsolute-timeout 60nsession-limit 16nlogin localntransport input sshn!nend”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “cpus”: 1,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “data_volume”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “image_definition”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “interfaces”: [\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv4_addresses”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv6_addresses”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “mac_address”: null,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “name”: “Loopback0”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “state”: “STARTED”\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 },\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv4_addresses”: [\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “192.168.255.199”\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ipv6_addresses”: [],\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “mac_address”: “52:54:00:13:51:66”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “name”: “GigabitEthernet1”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “state”: “STARTED”\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “node_definition”: “csr1000v”,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “ram”: 3072,\u00a0
\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 “state”: “BOOTED”\u00a0
\n\u00a0\u00a0\u00a0 }\u00a0
\n}\u00a0 <\/p>\n

The first IPv4 address found (in order of the interfaces) is used as `ansible_host` to enable the playbook to connect to the device. We can use the cisco.cml.inventory playbook included in the collection to show the inventory. In this case, we only specify that we want devices that are in the \u201crouter\u201d group created by the inventory plugin as informed by the tags on the devices:\u00a0<\/p>\n

mdd % ansible-playbook cisco.cml.inventory –limit=router\u00a0
\nok: [hq-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: hq-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.199:22”\u00a0
\n}\u00a0
\nok: [hq-rtr2] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: hq-rtr2(csr1000v), State: BOOTED, Address: 192.168.255.53:22”\u00a0
\n}\u00a0
\nok: [site1-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: site1-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.63:22”\u00a0
\n}\u00a0
\nok: [site2-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: site2-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.7:22”\u00a0
\n}\u00a0 <\/p>\n

In addition to group tags, the CML dynamic inventory plugin will also parse tags to pass information from PATty and to create generic inventory facts:\u00a0<\/p>\n

If a CML tag is specified that matches `^pat:(?:tcp|udp)?:?(d+):(d+)`, the CML server address (as opposed to the first IPv4 address found) will be used for `ansible_host`. To change `ansible_port` to point to the translated SSH port, the tag `ansible:ansible_port=2020` can be set. These two tags tell the Ansible playbook to connect to port 2020 of the CML server to automate the specified host in the topology. The `ansible:` tag can also be used to specify other host facts. For example, the tag `ansible:nso_api_port=2021` can be used to tell the playbook the port to use to reach the Cisco NSO API. Any arbitrary fact can be set in this way.\u00a0<\/p>\n

Getting started\u00a0<\/h2>\n

Trying out the CML Ansible Collection is easy. You can use the playbooks provided in the collection to load and start a topology in your CML server. To start, define the environment variable that tells the collection how to access your CML server:\u00a0<\/p>\n

% export CML_HOST=my-cml-server.my-domain.com\u00a0
\n% export CML_USERNAME=my-cml-username\u00a0
\n% export CML_PASSWORD=my-cml-password\u00a0<\/p>\n

The next step is to define your topology file. This is a standard topology file you can export from CML. There are two ways to define the topology file. First, you can use\u00a0 an environment variable:\u00a0<\/p>\n

% export CML_LAB=my-cml-labfile\u00a0<\/p>\n

Alternatively, you can specify the topology file when you run the playbook as an extra\u2013var.\u00a0 For example, to spin up a topology using the built in cisco.cml.build<\/em> playbook:\u00a0<\/p>\n

% ansible-playbook cisco.cml.build -e wait=’yes’ -e cml_lab_file=topology.yaml <\/p>\n

This command loads and starts the topology; then it waits until all nodes are running to complete.\u00a0 If -e startup=\u2019host\u2019<\/em> is specified, the playbook will start each host individually as opposed to starting them all at once.\u00a0 This allows for the config to be generated and fed into the host on startup.\u00a0 When cml_config_file is defined in the host\u2019s inventory, it is parsed as a Jinja file and fed into that host as config at startup.\u00a0 This allows for just-in-time configuration to occur.\u00a0<\/p>\n

Once the playbook completes, you can use another built-in playbook, cisco.cml.inventory<\/em>, to get the inventory for the topology.\u00a0 In order to use it, first create a cml.yml<\/em> in the inventory directory as shown above, then run the playbook as follows:\u00a0<\/p>\n

% ansible-playbook cisco.cml.inventory\u00a0
\nPLAY [cml_hosts] **********************************************************************\u00a0
\nTASK [debug] **********************************************************************\u00a0
\nok: [WAN-rtr1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: WAN-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.53:22”\u00a0
\n}\u00a0
\nok: [nso1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: nso1(ubuntu), State: BOOTED, Address: my-cml-server.my-domain.com:2010”\u00a0
\n}\u00a0
\nok: [site1-host1] => {\u00a0
\n\u00a0\u00a0\u00a0 “msg”: “Node: site1-host1(ubuntu), State: BOOTED, Address: site1-host1:22”\u00a0
\n}\u00a0<\/p>\n

In this truncated output, three different scenarios are shown.\u00a0 First, WAN-rtr1<\/em> is assigned the DHCP address it received for its ansible_host value, and ansible port <\/em>is 22<\/em>. If the host running the playbook has IP connectivity (either in the topology or a network connected to the topology with an external connector), it will be able to reach that host.\u00a0<\/p>\n

The second scenario shows an example of the PATty functionality with the host nso1<\/em> in which the dynamic inventory plugin reads those tags to determine that the host is available through the CML server\u2019s interface (i.e. ansible_host<\/em> is set to my-cml-server.my-domain.com<\/em>).\u00a0 Also, it knows that ansible_port should be set to the port specified in the tags (i.e. 2010).\u00a0 After these values are set, the ansible playbook can reach the host in the topology using the PATty functionality in CML.\u00a0<\/p>\n

The last example, site1-host1<\/em>, shows the scenario in which the CML dynamic inventory script can either find a DHCP allocated address or tags to specify to what ansible_host<\/em> should be set, so it uses the node name.\u00a0 For the playbook to reach those hosts, it would have to have IP connectivity and be able to resolve the node name to an IP address.\u00a0<\/p>\n

These built-in playbooks show examples of how to use the functionality in the CML Ansible Collection to build your own playbooks, but you can also use them directly as part of your pipeline.\u00a0 In fact, we often use them directly in the pipelines we build for customers.\u00a0<\/p>\n

If you want to learn more about the CML Ansible Collection, you can find it in Ansible Galaxy as well as on Github<\/a>.\u00a0<\/p>\n

You can also find a full, IaC CI\/CD pipeline using these modules here<\/a>.<\/p>\n

Join the\u202fCisco Learning Network<\/a>\u202ftoday for free.<\/p>\n

Follow Cisco Learning & Certifications<\/strong><\/h2>\n

Twitter<\/a>\u202f|\u202fFacebook<\/a>\u202f|\u202fLinkedIn<\/a>\u202f|\u202fInstagram<\/a><\/strong>\u202f|\u202fYouTube<\/a><\/strong><\/h3>\n

Use\u202f#CiscoCert<\/strong>\u202fto join the conversation.<\/p>\n

\n\t\tShare<\/p>\n
\n
<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t <\/a>\n\t<\/div>\n<\/div>\n<\/div>\n
Share:<\/div>\n
\n
\n
<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t\t<\/a>\n\t<\/div>\n<\/div>\n
\n
\n\t <\/a>\n\t<\/div>\n<\/div>\n<\/div>\n

\u00a0\u00a0Ansible can be used with CML (Cisco Modeling Labs) to automate the deployment and management of network infrastructure, offering reproducibility, consistency, and automation in network infrastructure management.\u00a0\u00a0Read More<\/a>\u00a0Cisco Blogs\u00a0<\/p>\n

<\/p>\n","protected":false},"author":0,"featured_media":2165,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12],"tags":[],"class_list":["post-2164","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cisco-learning"],"yoast_head":"\nHow to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm - JHC<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm\" \/>\n<meta property=\"og:description\" content=\"How can Ansible help people building simulations with Cisco Modeling Labs (CML)? Similar to Terraform, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous\u2026 Read more on Cisco Blogs \u200b How can Ansible help people building simulations with Cisco Modeling Labs (CML)? Similar to Terraform, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous Deployment (CI\/CD) DevOps methodologies. They are both a type of Infrastructure as Code (IaC) or Infrastructure as Data that allow you to render your infrastructure as text files and control it using tools such as Git. The advantage is reproducibility, consistency, speed, and the knowledge that, when you change the code, people approve, and it gets tested before it\u2019s pushed out to your production network. This paradigm allows enterprises to run their network infrastructure in the same way they run their software and cloud practices. Afterall, the infrastructure is there to support the apps, so why manage them differently?\u00a0 Although overlaps exist in the capabilities of Terraform and Ansible, they are very complementary. While Terraform is better at the initial deployment and ensuring ongoing consistency of the underlying infrastructure, Ansible is better at the initial configuration and ongoing management of the things that live in that infrastructure, such as systems, network devices, and so on.\u00a0 In a common workflow in which an operator wants to make a change to the network, let\u2019s say adding a new network to be advertised via BGP, a network engineer would specify that change in the code or more likely as configuration data in YAML or JSON. In a typical CI workflow, that change would need to be approved by others for correctness or adherence to corporate and security concerns, for instance. In addition to the eyeball tests, a series of automated testing validates the data and then deploys the proposed change in a test network. Those tests can be run in a physical test network, a virtual test network, or a combination of the two. That flow might look like the following:\u00a0 The advantage of leveraging virtual test networks is profound. The cost is dramatically lower, and the ability to automate testing is increased significantly. For example, a network engineer can spin up and configure a new, complex topology multiple times without the likelihood of old tests messing up the accuracy of the current testing. Cisco Modeling Labs is a great tool for this type of test.\u00a0 Here\u2019s where the Ansible CML Collection comes in. Similar to the CML Terraform integration covered in a previous blog, the Ansible CML Collection can automate the deployment of topologies in CML for testing. The Ansible CML Collection has modules to create, start, and stop a topology and the hosts within it, but more importantly, it has a dynamic inventory plugin for getting information about the topology. This is important for automation because topologies can change. Or multiple topologies could exist, depending on the tests being performed. If your topology uses dynamic host configuration protocol (DHCP) and\/or CML\u2019s PATty functionality, the information for how Ansible communicates with the nodes needs to be communicated to the playbook.\u00a0 Let\u2019s go over some of the features of the Ansible CML Collection\u2019s dynamic inventory plugin.\u00a0 First, we need to install the collection:\u00a0 ansible-galaxy collection install cisco.cml\u00a0 Next, we create a cml.yml in the inventory with the following contents to tell Ansible to use the Ansible CML Collection\u2019s dynamic inventory plugin:\u00a0 plugin: cisco.cml.cml_inventory\u00a0 group_tags: network, ios, nxos, router In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook:\u00a0 In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook: CML_USERNAME: Username for the CML user CML_PASSWORD: Password for the CML user CML_HOST: The CML host CML_LAB: The name of the lab\u00a0 Once the plugin knows how to communicate with the CML server and which lab to use, it can return information about the nodes in the lab:\u00a0 ok: [hq-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 "cml_facts": {\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "config": "hostname hq-rtr1nvrf definition Mgmt-intfn!naddress-family ipv4nexit-address-familyn!naddress-family ipv6nexit-address-familyn!nusername admin privilege 15 secret 0 adminncdp runnno aaa new-modelnip domain-name mdd.cisco.comn!ninterface GigabitEthernet1nvrf forwarding Mgmt-intfnip address dhcpnnegotiation autonno cdp enablenno shutdownn!ninterface GigabitEthernet2ncdp enablen!ninterface GigabitEthernet3ncdp enablen!ninterface GigabitEthernet4ncdp enablen!nip http servernip http secure-servernip http max-connections 2n!nip ssh time-out 60nip ssh version 2nip ssh server algorithm encryption aes128-ctr aes192-ctr aes256-ctrnip ssh client algorithm encryption aes128-ctr aes192-ctr aes256-ctrn!nline vty 0 4nexec-timeout 30 0nabsolute-timeout 60nsession-limit 16nlogin localntransport input sshn!nend",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "cpus": 1,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "data_volume": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "image_definition": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "interfaces": [\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "ipv4_addresses": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "ipv6_addresses": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "mac_address": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "name": "Loopback0",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "state": "STARTED"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 },\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "ipv4_addresses": [\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "192.168.255.199"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "ipv6_addresses": [],\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "mac_address": "52:54:00:13:51:66",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "name": "GigabitEthernet1",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "state": "STARTED"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "node_definition": "csr1000v",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "ram": 3072,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 "state": "BOOTED"\u00a0 \u00a0\u00a0\u00a0 }\u00a0 }\u00a0 The first IPv4 address found (in order of the interfaces) is used as `ansible_host` to enable the playbook to connect to the device. We can use the cisco.cml.inventory playbook included in the collection to show the inventory. In this case, we only specify that we want devices that are in the \u201crouter\u201d group created by the inventory plugin as informed by the tags on the devices:\u00a0 mdd % ansible-playbook cisco.cml.inventory --limit=router\u00a0 ok: [hq-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 "msg": "Node: hq-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.199:22"\u00a0 }\u00a0 ok: [hq-rtr2] => {\u00a0 \u00a0\u00a0\u00a0 "msg": "Node: hq-rtr2(csr1000v), State: BOOTED, Address: 192.168.255.53:22"\u00a0 }\u00a0 ok: [site1-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 "msg": "Node: site1-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.63:22"\u00a0 }\u00a0 ok: [site2-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 "msg": "Node: site2-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.7:22"\u00a0 }\u00a0 In addition to group tags, the CML dynamic inventory plugin will also parse tags to pass information from PATty and to create generic inventory facts:\u00a0 If a CML tag is specified that matches `^pat:(?:tcp|udp)?:?(d+):(d+)`, the CML server address (as opposed to the first IPv4 address found) will be used for `ansible_host`. To change `ansible_port` to point to the translated SSH port, the tag `ansible:ansible_port=2020` can be set. These two tags tell the Ansible playbook to connect to port 2020 of the CML server to automate the specified host in the topology. The `ansible:` tag can also be used to specify other host facts. For example, the tag `ansible:nso_api_port=2021` can be used to tell the playbook the port to use to reach the Cisco NSO API. Any arbitrary fact can be set in this way.\u00a0 Getting started\u00a0 Trying out the CML Ansible Collection is easy. You can use the playbooks provided in the collection to load and start a topology in your CML server. To start, define the environment variable that tells the collection how to access your CML server:\u00a0 % export CML_HOST=my-cml-server.my-domain.com\u00a0 % export CML_USERNAME=my-cml-username\u00a0 % export CML_PASSWORD=my-cml-password\u00a0 The next step is to define your topology file. This is a standard topology file you can export from CML. There are two ways to define the topology file. First, you can use\u00a0 an environment variable:\u00a0 % export CML_LAB=my-cml-labfile\u00a0 Alternatively, you can specify the topology file when you run the playbook as an extra\u2013var.\u00a0 For example, to spin up a topology using the built in cisco.cml.build playbook:\u00a0 % ansible-playbook cisco.cml.build -e wait='yes' -e cml_lab_file=topology.yaml This command loads and starts the topology; then it waits until all nodes are running to complete.\u00a0 If -e startup=\u2019host\u2019 is specified, the playbook will start each host individually as opposed to starting them all at once.\u00a0 This allows for the config to be generated and fed into the host on startup.\u00a0 When cml_config_file is defined in the host\u2019s inventory, it is parsed as a Jinja file and fed into that host as config at startup.\u00a0 This allows for just-in-time configuration to occur.\u00a0 Once the playbook completes, you can use another built-in playbook, cisco.cml.inventory, to get the inventory for the topology.\u00a0 In order to use it, first create a cml.yml in the inventory directory as shown above, then run the playbook as follows:\u00a0 % ansible-playbook cisco.cml.inventory\u00a0 PLAY [cml_hosts] **********************************************************************\u00a0 TASK [debug] **********************************************************************\u00a0 ok: [WAN-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 "msg": "Node: WAN-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.53:22"\u00a0 }\u00a0 ok: [nso1] => {\u00a0 \u00a0\u00a0\u00a0 "msg": "Node: nso1(ubuntu), State: BOOTED, Address: my-cml-server.my-domain.com:2010"\u00a0 }\u00a0 ok: [site1-host1] => {\u00a0 \u00a0\u00a0\u00a0 "msg": "Node: site1-host1(ubuntu), State: BOOTED, Address: site1-host1:22"\u00a0 }\u00a0 In this truncated output, three different scenarios are shown.\u00a0 First, WAN-rtr1 is assigned the DHCP address it received for its ansible_host value, and ansible port is 22. If the host running the playbook has IP connectivity (either in the topology or a network connected to the topology with an external connector), it will be able to reach that host.\u00a0 The second scenario shows an example of the PATty functionality with the host nso1 in which the dynamic inventory plugin reads those tags to determine that the host is available through the CML server\u2019s interface (i.e. ansible_host is set to my-cml-server.my-domain.com).\u00a0 Also, it knows that ansible_port should be set to the port specified in the tags (i.e. 2010).\u00a0 After these values are set, the ansible playbook can reach the host in the topology using the PATty functionality in CML.\u00a0 The last example, site1-host1, shows the scenario in which the CML dynamic inventory script can either find a DHCP allocated address or tags to specify to what ansible_host should be set, so it uses the node name.\u00a0 For the playbook to reach those hosts, it would have to have IP connectivity and be able to resolve the node name to an IP address.\u00a0 These built-in playbooks show examples of how to use the functionality in the CML Ansible Collection to build your own playbooks, but you can also use them directly as part of your pipeline.\u00a0 In fact, we often use them directly in the pipelines we build for customers.\u00a0 If you want to learn more about the CML Ansible Collection, you can find it in Ansible Galaxy as well as on Github.\u00a0 You can also find a full, IaC CI\/CD pipeline using these modules here. Join the\u202fCisco Learning Network\u202ftoday for free. Follow Cisco Learning & Certifications Twitter\u202f|\u202fFacebook\u202f|\u202fLinkedIn\u202f|\u202fInstagram\u202f|\u202fYouTube Use\u202f#CiscoCert\u202fto join the conversation. Share Share: \u00a0\u00a0Ansible can be used with CML (Cisco Modeling Labs) to automate the deployment and management of network infrastructure, offering reproducibility, consistency, and automation in network infrastructure management.\u00a0\u00a0Read More\u00a0Cisco Blogs\u00a0\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/\" \/>\n<meta property=\"og:site_name\" content=\"JHC\" \/>\n<meta property=\"article:published_time\" content=\"2024-01-17T20:52:09+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif\" \/>\n\t<meta property=\"og:image:width\" content=\"1\" \/>\n\t<meta property=\"og:image:height\" content=\"1\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/gif\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm\",\"datePublished\":\"2024-01-17T20:52:09+00:00\",\"dateModified\":\"2024-01-17T20:52:09+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/\"},\"wordCount\":1798,\"publisher\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif\",\"articleSection\":[\"Cisco: Learning\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/\",\"url\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/\",\"name\":\"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm - JHC\",\"isPartOf\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif\",\"datePublished\":\"2024-01-17T20:52:09+00:00\",\"dateModified\":\"2024-01-17T20:52:09+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage\",\"url\":\"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif\",\"contentUrl\":\"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif\",\"width\":1,\"height\":1},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/jacksonholdingcompany.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/jacksonholdingcompany.com\/#website\",\"url\":\"https:\/\/jacksonholdingcompany.com\/\",\"name\":\"JHC\",\"description\":\"Your Business Is Our Business\",\"publisher\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/jacksonholdingcompany.com\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/jacksonholdingcompany.com\/#organization\",\"name\":\"JHC\",\"url\":\"https:\/\/jacksonholdingcompany.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/jacksonholdingcompany.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2023\/07\/cropped-cropped-jHC-white-500-\u00d7-200-px-1-1.png\",\"contentUrl\":\"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2023\/07\/cropped-cropped-jHC-white-500-\u00d7-200-px-1-1.png\",\"width\":452,\"height\":149,\"caption\":\"JHC\"},\"image\":{\"@id\":\"https:\/\/jacksonholdingcompany.com\/#\/schema\/logo\/image\/\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm - JHC","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/","og_locale":"en_US","og_type":"article","og_title":"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm","og_description":"How can Ansible help people building simulations with Cisco Modeling Labs (CML)? Similar to Terraform, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous\u2026 Read more on Cisco Blogs \u200b How can Ansible help people building simulations with Cisco Modeling Labs (CML)? Similar to Terraform, Ansible is a common, open-source automation tool often used in Continuous Integration\/Continuous Deployment (CI\/CD) DevOps methodologies. They are both a type of Infrastructure as Code (IaC) or Infrastructure as Data that allow you to render your infrastructure as text files and control it using tools such as Git. The advantage is reproducibility, consistency, speed, and the knowledge that, when you change the code, people approve, and it gets tested before it\u2019s pushed out to your production network. This paradigm allows enterprises to run their network infrastructure in the same way they run their software and cloud practices. Afterall, the infrastructure is there to support the apps, so why manage them differently?\u00a0 Although overlaps exist in the capabilities of Terraform and Ansible, they are very complementary. While Terraform is better at the initial deployment and ensuring ongoing consistency of the underlying infrastructure, Ansible is better at the initial configuration and ongoing management of the things that live in that infrastructure, such as systems, network devices, and so on.\u00a0 In a common workflow in which an operator wants to make a change to the network, let\u2019s say adding a new network to be advertised via BGP, a network engineer would specify that change in the code or more likely as configuration data in YAML or JSON. In a typical CI workflow, that change would need to be approved by others for correctness or adherence to corporate and security concerns, for instance. In addition to the eyeball tests, a series of automated testing validates the data and then deploys the proposed change in a test network. Those tests can be run in a physical test network, a virtual test network, or a combination of the two. That flow might look like the following:\u00a0 The advantage of leveraging virtual test networks is profound. The cost is dramatically lower, and the ability to automate testing is increased significantly. For example, a network engineer can spin up and configure a new, complex topology multiple times without the likelihood of old tests messing up the accuracy of the current testing. Cisco Modeling Labs is a great tool for this type of test.\u00a0 Here\u2019s where the Ansible CML Collection comes in. Similar to the CML Terraform integration covered in a previous blog, the Ansible CML Collection can automate the deployment of topologies in CML for testing. The Ansible CML Collection has modules to create, start, and stop a topology and the hosts within it, but more importantly, it has a dynamic inventory plugin for getting information about the topology. This is important for automation because topologies can change. Or multiple topologies could exist, depending on the tests being performed. If your topology uses dynamic host configuration protocol (DHCP) and\/or CML\u2019s PATty functionality, the information for how Ansible communicates with the nodes needs to be communicated to the playbook.\u00a0 Let\u2019s go over some of the features of the Ansible CML Collection\u2019s dynamic inventory plugin.\u00a0 First, we need to install the collection:\u00a0 ansible-galaxy collection install cisco.cml\u00a0 Next, we create a cml.yml in the inventory with the following contents to tell Ansible to use the Ansible CML Collection\u2019s dynamic inventory plugin:\u00a0 plugin: cisco.cml.cml_inventory\u00a0 group_tags: network, ios, nxos, router In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook:\u00a0 In addition to specifying the plugin name, we can also define tags that, when found on the devices in the topology, add that device to an Ansible group to be used later in the playbook: CML_USERNAME: Username for the CML user CML_PASSWORD: Password for the CML user CML_HOST: The CML host CML_LAB: The name of the lab\u00a0 Once the plugin knows how to communicate with the CML server and which lab to use, it can return information about the nodes in the lab:\u00a0 ok: [hq-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 \"cml_facts\": {\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"config\": \"hostname hq-rtr1nvrf definition Mgmt-intfn!naddress-family ipv4nexit-address-familyn!naddress-family ipv6nexit-address-familyn!nusername admin privilege 15 secret 0 adminncdp runnno aaa new-modelnip domain-name mdd.cisco.comn!ninterface GigabitEthernet1nvrf forwarding Mgmt-intfnip address dhcpnnegotiation autonno cdp enablenno shutdownn!ninterface GigabitEthernet2ncdp enablen!ninterface GigabitEthernet3ncdp enablen!ninterface GigabitEthernet4ncdp enablen!nip http servernip http secure-servernip http max-connections 2n!nip ssh time-out 60nip ssh version 2nip ssh server algorithm encryption aes128-ctr aes192-ctr aes256-ctrnip ssh client algorithm encryption aes128-ctr aes192-ctr aes256-ctrn!nline vty 0 4nexec-timeout 30 0nabsolute-timeout 60nsession-limit 16nlogin localntransport input sshn!nend\",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"cpus\": 1,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"data_volume\": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"image_definition\": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"interfaces\": [\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"ipv4_addresses\": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"ipv6_addresses\": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"mac_address\": null,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"name\": \"Loopback0\",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"state\": \"STARTED\"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 },\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"ipv4_addresses\": [\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"192.168.255.199\"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"ipv6_addresses\": [],\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"mac_address\": \"52:54:00:13:51:66\",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"name\": \"GigabitEthernet1\",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"state\": \"STARTED\"\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ],\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"node_definition\": \"csr1000v\",\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"ram\": 3072,\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \"state\": \"BOOTED\"\u00a0 \u00a0\u00a0\u00a0 }\u00a0 }\u00a0 The first IPv4 address found (in order of the interfaces) is used as `ansible_host` to enable the playbook to connect to the device. We can use the cisco.cml.inventory playbook included in the collection to show the inventory. In this case, we only specify that we want devices that are in the \u201crouter\u201d group created by the inventory plugin as informed by the tags on the devices:\u00a0 mdd % ansible-playbook cisco.cml.inventory --limit=router\u00a0 ok: [hq-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 \"msg\": \"Node: hq-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.199:22\"\u00a0 }\u00a0 ok: [hq-rtr2] => {\u00a0 \u00a0\u00a0\u00a0 \"msg\": \"Node: hq-rtr2(csr1000v), State: BOOTED, Address: 192.168.255.53:22\"\u00a0 }\u00a0 ok: [site1-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 \"msg\": \"Node: site1-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.63:22\"\u00a0 }\u00a0 ok: [site2-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 \"msg\": \"Node: site2-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.7:22\"\u00a0 }\u00a0 In addition to group tags, the CML dynamic inventory plugin will also parse tags to pass information from PATty and to create generic inventory facts:\u00a0 If a CML tag is specified that matches `^pat:(?:tcp|udp)?:?(d+):(d+)`, the CML server address (as opposed to the first IPv4 address found) will be used for `ansible_host`. To change `ansible_port` to point to the translated SSH port, the tag `ansible:ansible_port=2020` can be set. These two tags tell the Ansible playbook to connect to port 2020 of the CML server to automate the specified host in the topology. The `ansible:` tag can also be used to specify other host facts. For example, the tag `ansible:nso_api_port=2021` can be used to tell the playbook the port to use to reach the Cisco NSO API. Any arbitrary fact can be set in this way.\u00a0 Getting started\u00a0 Trying out the CML Ansible Collection is easy. You can use the playbooks provided in the collection to load and start a topology in your CML server. To start, define the environment variable that tells the collection how to access your CML server:\u00a0 % export CML_HOST=my-cml-server.my-domain.com\u00a0 % export CML_USERNAME=my-cml-username\u00a0 % export CML_PASSWORD=my-cml-password\u00a0 The next step is to define your topology file. This is a standard topology file you can export from CML. There are two ways to define the topology file. First, you can use\u00a0 an environment variable:\u00a0 % export CML_LAB=my-cml-labfile\u00a0 Alternatively, you can specify the topology file when you run the playbook as an extra\u2013var.\u00a0 For example, to spin up a topology using the built in cisco.cml.build playbook:\u00a0 % ansible-playbook cisco.cml.build -e wait='yes' -e cml_lab_file=topology.yaml This command loads and starts the topology; then it waits until all nodes are running to complete.\u00a0 If -e startup=\u2019host\u2019 is specified, the playbook will start each host individually as opposed to starting them all at once.\u00a0 This allows for the config to be generated and fed into the host on startup.\u00a0 When cml_config_file is defined in the host\u2019s inventory, it is parsed as a Jinja file and fed into that host as config at startup.\u00a0 This allows for just-in-time configuration to occur.\u00a0 Once the playbook completes, you can use another built-in playbook, cisco.cml.inventory, to get the inventory for the topology.\u00a0 In order to use it, first create a cml.yml in the inventory directory as shown above, then run the playbook as follows:\u00a0 % ansible-playbook cisco.cml.inventory\u00a0 PLAY [cml_hosts] **********************************************************************\u00a0 TASK [debug] **********************************************************************\u00a0 ok: [WAN-rtr1] => {\u00a0 \u00a0\u00a0\u00a0 \"msg\": \"Node: WAN-rtr1(csr1000v), State: BOOTED, Address: 192.168.255.53:22\"\u00a0 }\u00a0 ok: [nso1] => {\u00a0 \u00a0\u00a0\u00a0 \"msg\": \"Node: nso1(ubuntu), State: BOOTED, Address: my-cml-server.my-domain.com:2010\"\u00a0 }\u00a0 ok: [site1-host1] => {\u00a0 \u00a0\u00a0\u00a0 \"msg\": \"Node: site1-host1(ubuntu), State: BOOTED, Address: site1-host1:22\"\u00a0 }\u00a0 In this truncated output, three different scenarios are shown.\u00a0 First, WAN-rtr1 is assigned the DHCP address it received for its ansible_host value, and ansible port is 22. If the host running the playbook has IP connectivity (either in the topology or a network connected to the topology with an external connector), it will be able to reach that host.\u00a0 The second scenario shows an example of the PATty functionality with the host nso1 in which the dynamic inventory plugin reads those tags to determine that the host is available through the CML server\u2019s interface (i.e. ansible_host is set to my-cml-server.my-domain.com).\u00a0 Also, it knows that ansible_port should be set to the port specified in the tags (i.e. 2010).\u00a0 After these values are set, the ansible playbook can reach the host in the topology using the PATty functionality in CML.\u00a0 The last example, site1-host1, shows the scenario in which the CML dynamic inventory script can either find a DHCP allocated address or tags to specify to what ansible_host should be set, so it uses the node name.\u00a0 For the playbook to reach those hosts, it would have to have IP connectivity and be able to resolve the node name to an IP address.\u00a0 These built-in playbooks show examples of how to use the functionality in the CML Ansible Collection to build your own playbooks, but you can also use them directly as part of your pipeline.\u00a0 In fact, we often use them directly in the pipelines we build for customers.\u00a0 If you want to learn more about the CML Ansible Collection, you can find it in Ansible Galaxy as well as on Github.\u00a0 You can also find a full, IaC CI\/CD pipeline using these modules here. Join the\u202fCisco Learning Network\u202ftoday for free. Follow Cisco Learning & Certifications Twitter\u202f|\u202fFacebook\u202f|\u202fLinkedIn\u202f|\u202fInstagram\u202f|\u202fYouTube Use\u202f#CiscoCert\u202fto join the conversation. Share Share: \u00a0\u00a0Ansible can be used with CML (Cisco Modeling Labs) to automate the deployment and management of network infrastructure, offering reproducibility, consistency, and automation in network infrastructure management.\u00a0\u00a0Read More\u00a0Cisco Blogs\u00a0","og_url":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/","og_site_name":"JHC","article_published_time":"2024-01-17T20:52:09+00:00","og_image":[{"width":1,"height":1,"url":"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif","type":"image\/gif"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#article","isPartOf":{"@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/"},"author":{"name":"","@id":""},"headline":"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm","datePublished":"2024-01-17T20:52:09+00:00","dateModified":"2024-01-17T20:52:09+00:00","mainEntityOfPage":{"@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/"},"wordCount":1798,"publisher":{"@id":"https:\/\/jacksonholdingcompany.com\/#organization"},"image":{"@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage"},"thumbnailUrl":"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif","articleSection":["Cisco: Learning"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/","url":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/","name":"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm - JHC","isPartOf":{"@id":"https:\/\/jacksonholdingcompany.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage"},"image":{"@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage"},"thumbnailUrl":"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif","datePublished":"2024-01-17T20:52:09+00:00","dateModified":"2024-01-17T20:52:09+00:00","breadcrumb":{"@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#primaryimage","url":"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif","contentUrl":"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2024\/01\/16537533-pDJXy6.gif","width":1,"height":1},{"@type":"BreadcrumbList","@id":"https:\/\/jacksonholdingcompany.com\/how-to-use-ansible-with-cml-steven-carter-on-january-17-2024-at-800-pm\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/jacksonholdingcompany.com\/"},{"@type":"ListItem","position":2,"name":"How to Use Ansible with CML Steven Carter on January 17, 2024 at 8:00 pm"}]},{"@type":"WebSite","@id":"https:\/\/jacksonholdingcompany.com\/#website","url":"https:\/\/jacksonholdingcompany.com\/","name":"JHC","description":"Your Business Is Our Business","publisher":{"@id":"https:\/\/jacksonholdingcompany.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jacksonholdingcompany.com\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/jacksonholdingcompany.com\/#organization","name":"JHC","url":"https:\/\/jacksonholdingcompany.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jacksonholdingcompany.com\/#\/schema\/logo\/image\/","url":"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2023\/07\/cropped-cropped-jHC-white-500-\u00d7-200-px-1-1.png","contentUrl":"https:\/\/jacksonholdingcompany.com\/wp-content\/uploads\/2023\/07\/cropped-cropped-jHC-white-500-\u00d7-200-px-1-1.png","width":452,"height":149,"caption":"JHC"},"image":{"@id":"https:\/\/jacksonholdingcompany.com\/#\/schema\/logo\/image\/"}}]}},"_links":{"self":[{"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/posts\/2164","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/comments?post=2164"}],"version-history":[{"count":0,"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/posts\/2164\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/media\/2165"}],"wp:attachment":[{"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/media?parent=2164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/categories?post=2164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jacksonholdingcompany.com\/wp-json\/wp\/v2\/tags?post=2164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}