{"id":1643,"date":"2023-04-10T20:22:03","date_gmt":"2023-04-10T19:22:03","guid":{"rendered":"http:\/\/192.168.1.213:8088\/?p=1643"},"modified":"2023-10-13T05:40:09","modified_gmt":"2023-10-13T04:40:09","slug":"unleashing-the-power-of-network-digital-twins-within-ci-cd-environments-part-2","status":"publish","type":"post","link":"http:\/\/192.168.1.213:8088\/unleashing-the-power-of-network-digital-twins-within-ci-cd-environments-part-2\/","title":{"rendered":"Unleashing the Power of Network Digital Twins within CI\/CD Environments – Part 2"},"content":{"rendered":"\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t

\n\t\t\t\tTable of Contents\t\t\t<\/h4>\n\t\t\t\t\t\t\t
<\/i><\/div>\n\t\t\t\t
<\/i><\/div>\n\t\t\t\t\t<\/div>\n\t\t
\n\t\t\t
\n\t\t\t\t<\/i>\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\t\t
\n\t\t\t\t
\n\t\t\t
Introduction<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

Alright, let’s get down to business \ud83d\ude80 ! In this part, I will show you how an end-to-end pipeline can be built using the digital-twin approach.\u00a0<\/p>

I will use the following scenario as an example:<\/strong><\/p>

A network administrator by the name of Pawel finds himself entrusted with the responsibility of expanding the configuration on a VPC back-to-back<\/a> environment in the data center. Awaiting their network configurations, new servers stand ready to be integrated into the environment.<\/p>

Pawel’s mission is threefold: to create a new VLAN specifically tailored for these servers, configure the ports with this VLAN, and establish SVIs on each Nexus switch.<\/strong><\/p>

While these tasks may appear to be a walk in the park for seasoned network administrators, Pawel, being a recent addition to the company, is determined to prove his mettle and ensure his first assignment is a resounding success.<\/p>

In pursuit of this goal, Pawel meticulously approaches each step, embracing the challenges and opportunities that come with being the company’s newest network administrator. With a keen eye for detail and an unwavering commitment to excellence, Pawel sets out to make a lasting impression on his colleagues and demonstrate that he has what it takes to succeed in his new role.<\/p>

To give a better idea, the network diagram looks like this:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t

\n\t\t\t\t
\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\"\"\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t
The importance of separating data from code<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t
\n\t\t\t\t
\n\t\t\t\t\t\t\t

When working with automation, it’s important to separate data from the code that processes it. This makes everything easier to manage and maintain in the future.<\/p>

One way to help with this separation is by using a data model, like OpenConfig<\/a>. OpenConfig is a standard that makes it simpler to manage network devices from different vendors using the same set of rules.<\/p>

By using OpenConfig, you can manage and automate your network more easily, no matter what devices you’re working with. This makes your automation tasks more organized, efficient, and multi-vendor friendly.<\/p>

In my particular use case, I have opted to craft a custom data model tailored specifically for this scenario, ensuring a seamless fit with my requirements and offering a personalized touch to address the challenges at hand.<\/strong><\/p>

The following example shows the data model for one Nexus device:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t

\n\t\t\t\t
\n\t\t\t\t\t
\n\t\t\t
\n\t\t\t\t\n\t\t\t\t\t---\n\nNXOS01:\n  feature:\n    - feature_name: interface-vlan\n  vlan:\n    - vlan_id: 172\n      vlan_name: \"VLAN172\"\n  interfaces:\n    - name: Ethernet1\/4\n      type: access\n      vlan: 172\n  interface_vlan:\n    - name: vlan 172\n      address: 172.16.16.211\n      netmask: 255.255.255.0<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-64dd9fe elementor-widget elementor-widget-heading\" data-id=\"64dd9fe\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Choosing the right toolset<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-274b606 elementor-widget elementor-widget-text-editor\" data-id=\"274b606\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Finding the right tools for automation can be tough when you&#8217;re new to it. Focus on your goal and what you want to achieve. Your first solution might not be perfect, but it&#8217;s better to start and learn from it than to do nothing at all. Keep trying, and you&#8217;ll improve your automation skills over time.<\/p><p><strong>My advice to you:<\/strong><\/p><ul style=\"font-weight: 400;\"><li data-aria-posinset=\"1\" data-aria-level=\"1\"><strong>Purpose<\/strong><span data-usefontface=\"false\" data-contrast=\"none\">: Determine the specific tasks you want to automate and ensure the\u00a0<\/span><span data-usefontface=\"false\" data-contrast=\"none\">tool can support them<\/span><\/li><li data-aria-posinset=\"2\" data-aria-level=\"1\"><b><span data-usefontface=\"false\" data-contrast=\"none\">Vendor support<\/span><\/b><span data-usefontface=\"false\" data-contrast=\"none\">: Check the compatibility and integration of the automation\u00a0<\/span><span data-usefontface=\"false\" data-contrast=\"none\">tool with your current implemented solutions\u00a0<\/span><\/li><li data-aria-posinset=\"3\" data-aria-level=\"1\"><b><span data-usefontface=\"false\" data-contrast=\"none\">Scalability<\/span><\/b><span data-usefontface=\"false\" data-contrast=\"none\">: Ensure the tool can scale with your business needs and growth<\/span><\/li><li data-aria-posinset=\"4\" data-aria-level=\"1\"><b><span data-usefontface=\"false\" data-contrast=\"none\">Customization<\/span><\/b><span data-usefontface=\"false\" data-contrast=\"none\">: Check if the tool can be customized to meet your specific\u00a0<\/span><span data-usefontface=\"false\" data-contrast=\"none\">requirements<\/span><\/li><\/ul><div>\u00a0<\/div><p><strong>In this use case, I am going to use the following toolset:<\/strong><\/p><ul><li><strong>CML (Cisco Modeling Lab)<\/strong> as a network simulation software to create the digital twin<\/li><li><strong>Ansible<\/strong> as a configuration tool for the digital twin creation as well as the Nexus devices<\/li><li><strong>Robot framework<\/strong> to execute functional testing on the devices<\/li><li><strong>GitLab<\/strong> as my CI\/CD tool (as you most probably could see from my recent posts \ud83d\ude1c)\u00a0<\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2844e93 elementor-widget elementor-widget-heading\" data-id=\"2844e93\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">The steps that are involved<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-5858d87 elementor-widget elementor-widget-text-editor\" data-id=\"5858d87\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>To successfully execute the desired use case, the following steps are needed:<\/p><ul><li><p><strong>Docker file construction and registry upload<\/strong>: Create a Docker file that encapsulates all dependencies and configurations required for your project. Once built, upload it to the Docker registry to ensure easy deployment and consistency across environments.<\/p><\/li><li><p><strong>Ansible file linting<\/strong>: Review and check all Ansible files for syntax, best practices, and potential errors. Linting will help maintain high code quality and reduce the possibility of unforeseen issues during execution.<\/p><\/li><li><p><strong>Digital twin creation in CML<\/strong>: Utilize Ansible to create a digital twin within Cisco Modeling Labs (CML), providing a virtual replica of your production environment. This allows for testing and validation of configurations without affecting the live system.<\/p><\/li><li><p><strong>Nexus device configuration<\/strong>: Apply the necessary configurations to the Nexus devices in the digital twin environment using Ansible. This process will ensure that the devices are set up correctly and ready for testing.<\/p><\/li><li><p><strong>VLAN and VLAN interface validation<\/strong>: Implement the Robot framework to test whether the VLAN and VLAN interface have been created correctly. This step helps confirm that your configurations are functional and error-free.<\/p><\/li><li><p><strong>Production Nexus device configuration<\/strong>: Once the digital twin environment has been thoroughly tested and validated, apply the same configurations to the production Nexus devices. This step ensures that the live environment is aligned with the successful digital twin setup.<\/p><\/li><li><p><strong>Production environment testing<\/strong>: Run the same test cases used in the digital twin environment on the production setup. This process validates that the configurations work as intended in the live environment, further ensuring system stability and reliability.<\/p><\/li><li><p><strong>Digital twin removal in CML<\/strong>: After successfully implementing and validating the configurations in both the digital twin and production environments, delete the digital twin in CML. This action keeps your workspace clean and efficient, minimizing resource usage.<\/p><\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-97cedb9 elementor-widget elementor-widget-heading\" data-id=\"97cedb9\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Build the pipeline<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-8d15b08 elementor-widget elementor-widget-text-editor\" data-id=\"8d15b08\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Given the extensive collection of files involved in this project, I will highlight just a few key examples with their content.<\/p><p class=\"p1\"><strong><a href=\"http:\/\/beye.blog\/brkops-2317\" target=\"_blank\" rel=\"noopener\">\u2b50 To explore the complete set of files, please visit my GitHub repository at: beye.blog\/brkops-2317 <\/a><\/strong><strong><a href=\"http:\/\/beye.blog\/brkops-2317\" target=\"_blank\" rel=\"noopener\">\u2b50<\/a><\/strong><\/p><p class=\"p1\">The list of files are the following:<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4c71472 elementor-widget elementor-widget-code-highlight\" data-id=\"4c71472\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-twilight  \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-markup \">\n\t\t\t\t<code readonly=\"true\" class=\"language-markup\">\n\t\t\t\t\t<xmp>\u251c\u2500\u2500 Dockerfile\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 ansible\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 00_create_CML_lab.yaml\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 01_config_devices.yaml\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 02_delete_CML_lab.yaml\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 ansible.cfg\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 data\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 brkops-2317_digital-twin.yaml\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 switch_configuration.yaml\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 group_vars\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 cml_host.yaml\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 digital_twin.yaml\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 production.yaml\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 inventory\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 inventory_digital-twin\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 inventory_production\n\u2514\u2500\u2500 robot_framework\n    \u251c\u2500\u2500 testbed_digital-twin.yaml\n    \u251c\u2500\u2500 testbed_production.yaml\n    \u251c\u2500\u2500 testcases_digital-twin.robot\n    \u2514\u2500\u2500 testcases_production.robot<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d873834 elementor-widget elementor-widget-heading\" data-id=\"d873834\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h6 class=\"elementor-heading-title elementor-size-default\">Dockerfile<\/h6>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d55b693 elementor-widget elementor-widget-text-editor\" data-id=\"d55b693\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>As usual, I am creating my own Docker image which hosts all the tools that are needed for the project.\u00a0<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6573b4b elementor-widget elementor-widget-code-highlight\" data-id=\"6573b4b\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-markup line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-markup\">\n\t\t\t\t\t<xmp>FROM ubuntu:22.04\n\nRUN apt-get update && \\\n  apt-get install -y gcc python3.11 git && \\\n  apt-get install -y python3-pip ssh && \\\n  pip3 install --upgrade pip && \\\n  pip3 install ansible requests && \\\n  pip3 install ansible-pylibssh && \\\n  pip3 install pyats[full] && \\\n  pip3 install ansible-lint && \\\n  pip3 install virl2-client==2.4.0 && \\\n  ansible-galaxy collection install cisco.nxos && \\\n  ansible-galaxy collection install cisco.cml<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-f122f94 elementor-widget elementor-widget-heading\" data-id=\"f122f94\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h6 class=\"elementor-heading-title elementor-size-default\">Ansible<\/h6>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-99db9b1 elementor-widget elementor-widget-text-editor\" data-id=\"99db9b1\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>First, you need to create the CML digital twin this is done by loading the lab file YAML file into the CML controller. The devices will boot with a basic configuration which includes the user and password as well as the IP address for the management interface to access the devices.\u00a0<\/p><p>This takes some time make sure to set the <strong>command_timeout<\/strong> parameter with a higher value for example 1800.\u00a0<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d8b7151 elementor-widget elementor-widget-code-highlight\" data-id=\"d8b7151\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-markup line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-markup\">\n\t\t\t\t\t<xmp>- name: Build the topology\n  hosts: localhost\n  connection: local\n  gather_facts: false\n\n  vars:\n    cml_lab_file: data\/brkops-2317_digital-twin.yaml\n    cml_lab: BRKOPS-2317_DIGITAL-TWIN\n    startup: 'all'\n    wait: 'no'\n    cml_login: &cml_login\n      host: xyz.xyz.xyz.xyz\n      user: user\n      password: password\n\n  tasks:\n    - name: Check for the lab file # Check lab file exists\n      ansible.builtin.stat:\n        path: \"{{ cml_lab_file }}\"\n      register: stat_result\n      delegate_to: localhost\n\n    - name: Check for the CML host, credentials, and topology file # Check CML host, credentials, and topology file are defined\n      ansible.builtin.assert:\n        that:\n          - stat_result.stat.exists\n          - cml_login.host != \"\"\n          - cml_login.user != \"\"\n          - cml_login.password != \"\"\n          - cml_lab != \"\"\n        msg: \"CML host, credentials, and topology file are required.  Verify the requirements in README are met.\"\n      delegate_to: localhost\n\n    - name: Create the lab # Create the lab\n      cisco.cml.cml_lab:\n        <<: *cml_login\n        lab: \"{{ cml_lab }}\"\n        state: \"{{ 'started' if startup == 'all' else 'present' }}\"\n        file: \"{{ cml_lab_file }}\"\n        topology: \"{{ lookup('template', cml_lab_file) }}\"\n        wait: \"True\"\n      register: results\n\n    - name: Check to see if the Lab is there # Check to see if the Lab is there\n      cisco.cml.cml_lab_facts:\n        <<: *cml_login\n        lab: \"{{ cml_lab }}\"\n      register: cml_lab_facts\n      when: wait | bool\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-452b26a elementor-widget elementor-widget-text-editor\" data-id=\"452b26a\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p><strong>This will import and boot the digital twin environment.\u00a0<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-d0748c1 elementor-widget elementor-widget-image\" data-id=\"d0748c1\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_002.png\" data-elementor-open-lightbox=\"yes\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTY1NSwidXJsIjoiaHR0cDpcL1wvMTkyLjE2OC4xLjIxMzo4MDg4XC93cC1jb250ZW50XC91cGxvYWRzXC8yMDIzXC8wNFwvdW5sZWFzaGluZy10aGUtcG93ZXItb2YtbmV0d29yay1kaWdpdGFsLXR3aW5zLXdpdGhpbi1DSUNELWVudmlyb25tZW50c19wYXJ0MDJfMDAyLnBuZyJ9\">\n\t\t\t\t\t\t\t<img decoding=\"async\" width=\"800\" height=\"507\" src=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_002-1024x649.png\" class=\"attachment-large size-large wp-image-1655\" alt=\"\" srcset=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_002-1024x649.png 1024w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_002-300x190.png 300w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_002-768x487.png 768w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_002.png 1058w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e4e5d1c elementor-widget elementor-widget-text-editor\" data-id=\"e4e5d1c\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>Following that, Ansible takes charge of configuring the devices by seamlessly loading the defined data model and iterating through the values.<\/p><ul><li><p><strong>Load variables<\/strong>: It loads the switch configuration data from the <code>data\/switch_configuration.yaml<\/code> file and stores it in the <code>switch_configuration<\/code> variable.<\/p><\/li><li><p><strong>Show version command<\/strong>: The playbook runs the <code>show version<\/code> and <code>show interface mgmt0<\/code> commands on the targeted Cisco Nexus devices and stores the output in the <code>show_version_output<\/code> variable. It retries up to 50 times with a 30-second delay between attempts until the commands are successful.<\/p><\/li><li><p><strong>Create VLAN<\/strong>: The playbook creates VLANs on the Nexus devices based on the data stored in the <code>switch_configuration<\/code> variable.<\/p><\/li><li><p><strong>Configure interface<\/strong>: It configures the interfaces as specified in the <code>switch_configuration<\/code> variable, setting a description, and enabling them.<\/p><\/li><li><p><strong>Configure access VLAN on interface<\/strong>: The playbook assigns the access VLANs to the interfaces as specified in the <code>switch_configuration<\/code> variable.<\/p><\/li><li><p><strong>Ensure the feature is enabled<\/strong>: It ensures that the required features (e.g., interface-vlan) are enabled on the Nexus devices as specified in the <code>switch_configuration<\/code> variable.<\/p><\/li><li><p><strong>Configure VLAN interface<\/strong>: Finally, the playbook configures the VLAN interfaces (SVI) with their respective IP addresses and netmasks as specified in the <code>switch_configuration<\/code> variable, and ensures they are not in shutdown state.<\/p><\/li><\/ul><p>In summary, this playbook automates the process of configuring VLANs, interfaces, and related settings on Cisco Nexus devices, using the data defined in the <code>switch_configuration.yaml<\/code> file.<\/p><p>Execute the playbook using the appropriate inventory file and group, ensuring a precise and targeted configuration process:<\/p><div><div><em><strong>ansible-playbook 01_config_devices.yaml -i inventory_digital-twin &#8211;extra-vars &#8220;host_var=digital_twin&#8221;<\/strong><\/em><\/div><\/div><div>\u00a0<\/div><div>This ensures that the playbook can be used for the digital twin and the production:<\/div>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9d864f6 elementor-widget elementor-widget-code-highlight\" data-id=\"9d864f6\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-markup line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-markup\">\n\t\t\t\t\t<xmp>---\n\n- name: Configure VLAN and interface # Configure devices\n  hosts: \"{{ host_var|default([]) }}\"\n  gather_facts: false\n  serial: 1\n  order: sorted\n\n  tasks:\n\n    - name: Load variables # Load fabric data from file\n      ansible.builtin.include_vars:\n        file: data\/switch_configuration.yaml\n        name: switch_configuration\n\n    - name: Show version command\n      cisco.nxos.nxos_command:\n        commands:\n          - show version\n          - show interface mgmt0\n      register: show_version_output\n      until: show_version_output is success\n      retries: 50\n      delay: 30\n\n    - name: Display the show version output\n      ansible.builtin.debug:\n        var: show_version_output.stdout_lines\n\n\n    - name: Create VLAN # Create VLAN\n      cisco.nxos.nxos_vlans:\n        config:\n          - vlan_id: '{{ item.vlan_id }}'\n            name: '{{ item.vlan_name }}'\n        state: merged\n      with_items:\n        - '{{ switch_configuration[inventory_hostname].vlan }}'\n\n    - name: Configure interface # Configure interface\n      cisco.nxos.nxos_interfaces:\n        config:\n        - name: '{{ item.name }}'\n          description: Configured by Ansible\n          enabled: true\n      with_items:\n        - '{{ switch_configuration[inventory_hostname].interfaces }}'\n\n    - name: Configure access VLAN on interface # Configure access VLAN on interface\n      cisco.nxos.nxos_l2_interfaces:\n        config:\n          - name: '{{ item.name }}'\n            access:\n              vlan: '{{ item.vlan }}'\n        state: merged\n      with_items:\n        - '{{ switch_configuration[inventory_hostname].interfaces }}'\n\n    - name: Ensure the feature is enabled # Ensure the feature is enabled\n      cisco.nxos.nxos_feature:\n        feature: '{{ item.feature_name }}'\n        state: enabled\n      with_items:\n        - '{{ switch_configuration[inventory_hostname].feature }}'\n\n    - name: Configure VLAN interface # Configure VLAN interface\n      cisco.nxos.nxos_config:\n        lines:\n          - interface {{ item.name }}\n          - ip address {{ item.address }} {{ item.netmask }}\n          - no shutdown\n      with_items:\n        - '{{ switch_configuration[inventory_hostname].interface_vlan }}'<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ff92067 elementor-widget elementor-widget-text-editor\" data-id=\"ff92067\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>At the end of the process the CML digital twin will be deleted to release resources.\u00a0<\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0ce5486 elementor-widget elementor-widget-code-highlight\" data-id=\"0ce5486\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-markup line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-markup\">\n\t\t\t\t\t<xmp>---\n\n- name: Delete the topology\n  hosts: localhost\n  connection: local\n  gather_facts: false\n\n  vars:\n    cml_lab: BRKOPS-2317_DIGITAL-TWIN\n    startup: 'all'\n    wait: 'no'\n    cml_login: &cml_login\n      host: xyz.xyz.xyz.xyz\n      user: user\n      password: password\n\n  tasks:\n\n    - name: Check for the CML host, credentials, and topology file # Check CML host, credentials, and topology file are defined\n      ansible.builtin.assert:\n        that:\n          - stat_result.stat.exists\n          - cml_login.host != \"\"\n          - cml_login.user != \"\"\n          - cml_login.password != \"\"\n          - cml_lab != \"\"\n        msg: \"CML host, credentials, and topology file are required.  Verify the requirements in README are met.\"\n      delegate_to: localhost\n\n    - name: Delete the lab # Create the lab\n      cisco.cml.cml_lab:\n        <<: *cml_login\n        lab: \"{{ cml_lab }}\"\n        state: \"absent\"\n        topology: \"{{ lookup('template', cml_lab_file) }}\"\n      register: results\n<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-3cd6b19 elementor-widget elementor-widget-heading\" data-id=\"3cd6b19\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h6 class=\"elementor-heading-title elementor-size-default\">Robot framework test cases<\/h6>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4ddfbc8 elementor-widget elementor-widget-text-editor\" data-id=\"4ddfbc8\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>This Robot Framework test suite validates the presence of a specified VLAN and its corresponding VLAN interface on a set of Cisco Nexus devices, ensuring that the network configurations are properly applied and functional.<\/p><ul><li><p><strong>Settings<\/strong>: The suite imports necessary libraries, including <code>pyATSRobot<\/code>, <code>UniconRobot<\/code>, and <code>GenieRobot<\/code>, which are essential for interacting with Cisco devices and parsing their output.<\/p><\/li><li><p><strong>Suite Setup<\/strong>: The suite setup defines a keyword chain to load the testbed file <code>testbed_digital-twin.yaml<\/code> and establish connections to all devices specified in the testbed.<\/p><\/li><li><p><strong>Variables<\/strong>: The suite specifies variables, including a list of devices (<code>DEVICES<\/code>), the target VLAN ID (<code>VLAN_ID<\/code>), and the target VLAN name (<code>VLAN_NAME<\/code>).<\/p><\/li><li><p><strong>Test Cases<\/strong>:<\/p><ul><li><p><strong>Validate VLAN on device<\/strong>: This test case iterates through the devices listed in the <code>DEVICES<\/code> variable. It executes the <code>show vlan<\/code> command on each device and parses the output. The test then uses a Data Query (DQ) to filter and find the target VLAN ID in the parsed data. The test case passes if the target VLAN ID is found, otherwise, it fails with the message &#8220;VLAN not found.&#8221;<\/p><\/li><li><p><strong>Validate VLAN interface on device<\/strong>: This test case also iterates through the devices listed in the <code>DEVICES<\/code> variable. It executes the <code>show interface vlan 172<\/code> command on each device and parses the output. The test checks if the link state of the VLAN interface is &#8220;up&#8221; and if the parsed data contains the target VLAN interface. The test case passes if both conditions are met, otherwise, it fails with the message &#8220;VLAN interface not found.&#8221;<\/p><\/li><\/ul><\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-1591f20 elementor-widget elementor-widget-code-highlight\" data-id=\"1591f20\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-markup line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-markup\">\n\t\t\t\t\t<xmp>*** Settings ***\nLibrary         pyats.robot.pyATSRobot\nLibrary         unicon.robot.UniconRobot\nLibrary         genie.libs.robot.GenieRobot\n\nSuite Setup    Run Keywords    use testbed \"testbed_digital-twin.yaml\"    AND    connect to all devices\n\n*** Variables ***\n@{DEVICES}         nxos01    nxos02    nxos03    nxos04\n${VLAN_ID}         172\n${VLAN_NAME}       VLAN172\n\n*** Test Cases ***\nValidate VLAN on device\n    FOR    ${DEVICE}    IN    @{DEVICES}\n        ${output}=      parse \"show vlan\" on device \"${DEVICE}\"\n        ${response}=      dq query    data=${output}    filters=contains('${VLAN_ID}')\n        Should Not Be Empty    ${response}    msg=VLAN not found\n    END\n\nValidate VLAN interface on device\n    FOR    ${DEVICE}    IN    @{DEVICES}\n        ${output}=      parse \"show interface vlan 172\" on device \"${DEVICE}\"\n        Should be Equal    ${output}[Vlan172][link_state]    up \n        Should Not Be Empty    ${output}    msg=VLAN interface not found\n    END<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0a5f532 elementor-widget elementor-widget-image\" data-id=\"0a5f532\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_004.png\" data-elementor-open-lightbox=\"yes\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTY2MywidXJsIjoiaHR0cDpcL1wvMTkyLjE2OC4xLjIxMzo4MDg4XC93cC1jb250ZW50XC91cGxvYWRzXC8yMDIzXC8wNFwvdW5sZWFzaGluZy10aGUtcG93ZXItb2YtbmV0d29yay1kaWdpdGFsLXR3aW5zLXdpdGhpbi1DSUNELWVudmlyb25tZW50c19wYXJ0MDJfMDA0LnBuZyJ9\">\n\t\t\t\t\t\t\t<img decoding=\"async\" width=\"800\" height=\"403\" src=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_004-1024x516.png\" class=\"attachment-large size-large wp-image-1663\" alt=\"\" srcset=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_004-1024x516.png 1024w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_004-300x151.png 300w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_004-768x387.png 768w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_004.png 1110w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ab3071d elementor-widget elementor-widget-heading\" data-id=\"ab3071d\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h6 class=\"elementor-heading-title elementor-size-default\">GitLab pipeline file<\/h6>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6d936d7 elementor-widget elementor-widget-text-editor\" data-id=\"6d936d7\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>This GitLab CI\/CD pipeline automates the process of creating, configuring, testing, and deleting a digital twin environment for a network setup using Cisco Nexus devices. The pipeline consists of several stages and jobs:<\/p><ul><li><p><strong>Build<\/strong>: In this stage, two jobs (<code>build_image<\/code> and <code>push_image<\/code>) build a Docker image containing the necessary dependencies and configurations for the project and push it to the GitLab registry.<\/p><\/li><li><p><strong>Linting<\/strong>: The <code>ansible_linting<\/code> job checks the Ansible playbook for syntax, best practices, and potential errors to ensure high code quality.<\/p><\/li><li><p><strong>Create Digital Twin<\/strong>: The <code>create_digital-twin<\/code> job uses Ansible to create a digital twin within Cisco Modeling Labs (CML), providing a virtual replica of the production environment for testing.<\/p><\/li><li><p><strong>Configure Digital Twin<\/strong>: The <code>configure_digital-twin<\/code> job applies the necessary configurations to the Nexus devices in the digital twin environment using Ansible.<\/p><\/li><li><p><strong>Test Digital Twin<\/strong>: The <code>testcases_digital-twin<\/code> job runs Robot Framework test cases to validate the VLAN and VLAN interface configurations on the Nexus devices in the digital twin environment.<\/p><\/li><li><p><strong>Configure Production<\/strong>: The <code>configure_production<\/code> job applies the validated configurations to the production Nexus devices.<\/p><\/li><li><p><strong>Test Production<\/strong>: The <code>testcases_production<\/code> job runs the same test cases as in the digital twin environment, now on the production setup, to ensure the configurations work as intended in the live environment.<\/p><\/li><li><p><strong>Delete Digital Twin<\/strong>: The <code>delete_digital-twin<\/code> job removes the digital twin from the CML environment after successful implementation and validation of the configurations in both digital twin and production environments.<\/p><\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c2191fe elementor-widget elementor-widget-image\" data-id=\"c2191fe\" data-element_type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_003.png\" data-elementor-open-lightbox=\"yes\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MTY1NiwidXJsIjoiaHR0cDpcL1wvMTkyLjE2OC4xLjIxMzo4MDg4XC93cC1jb250ZW50XC91cGxvYWRzXC8yMDIzXC8wNFwvdW5sZWFzaGluZy10aGUtcG93ZXItb2YtbmV0d29yay1kaWdpdGFsLXR3aW5zLXdpdGhpbi1DSUNELWVudmlyb25tZW50c19wYXJ0MDJfMDAzLnBuZyJ9\">\n\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"159\" src=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_003-1024x204.png\" class=\"attachment-large size-large wp-image-1656\" alt=\"\" srcset=\"http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_003-1024x204.png 1024w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_003-300x60.png 300w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_003-768x153.png 768w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_003-1536x307.png 1536w, http:\/\/192.168.1.213:8088\/wp-content\/uploads\/2023\/04\/unleashing-the-power-of-network-digital-twins-within-CICD-environments_part02_003.png 1948w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6b52463 elementor-widget elementor-widget-code-highlight\" data-id=\"6b52463\" data-element_type=\"widget\" data-widget_type=\"code-highlight.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div class=\"prismjs-default copy-to-clipboard \">\n\t\t\t<pre data-line=\"\" class=\"highlight-height language-markup line-numbers\">\n\t\t\t\t<code readonly=\"true\" class=\"language-markup\">\n\t\t\t\t\t<xmp>workflow:\n  rules:\n    - changes:\n      - data\/switch_configuration.yaml\n    - if: $CI_COMMIT_BRANCH != \"main\" && $CI_PIPELINE_SOURCE != \"merge_request_event\"\n      when: never\n    - when: always\n\nvariables:\n  IMAGE_NAME_ANSIBLE: $CI_REGISTRY_IMAGE\/ansible  \n  IMAGE_TAG_ANSIBLE: \"1.0\"\n\nstages:\n  - build \n  - linting\n  - create_digital-twin\n  - configure_digital-twin\n  - test_digital-twin\n  - configure_production\n  - test_production\n  - delete_digital-twin\n\nbuild_image:\n  stage: build\n  tags:\n    - local-runner\n  script:\n    - docker build -t $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE .\n\npush_image:\n  stage: build\n  needs:\n    - build_image\n  tags:\n    - local-runner\n  before_script:\n    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY\n  script:\n    - docker push $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n\nansible_linting:\n  stage: linting\n  image: $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n  needs: \n    - push_image\n  tags:\n    - docker-runner\n  before_script:\n    - cd ansible\n  script: \n    - ansible-lint --profile=min 00_create_CML_lab.yaml\n\n\ncreate_digital-twin:\n  stage: create_digital-twin\n  image: $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n  needs: \n    - ansible_linting\n  environment: CML\n  tags:\n    - docker-runner\n  before_script:\n    - cd ansible\n    - unset http_proxy \n    - unset http_proxys\n  script: \n    - ansible-playbook 00_create_CML_lab.yaml\n\nconfigure_digital-twin:\n  stage: create_digital-twin\n  image: $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n  needs: \n    - create_digital-twin\n  environment: CML\n  tags:\n    - docker-runner\n  before_script:\n    - cd ansible\n  script: \n    - ansible-playbook 01_config_devices.yaml -i inventory_digital-twin --extra-vars \"host_var=digital_twin\"\n\ntestcases_digital-twin:\n  stage: test_digital-twin\n  image: $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n  needs:\n    - configure_digital-twin\n  environment: CML\n  tags:\n    - docker-runner\n  before_script:\n    - cd robot_framework\n    - mkdir reports_digital-twin\n  script:\n    - robot --outputdir reports_digital-twin\/ testcases_digital-twin.robot\n  artifacts:\n    untracked: false\n    when: always\n    expire_in: \"1 days\"\n    paths:\n      - \"$CI_BUILDS_DIR\/$CI_PROJECT_PATH\/robot_framework\/reports_digital-twin\/log.html\"\n      - \"$CI_BUILDS_DIR\/$CI_PROJECT_PATH\/robot_framework\/reports_digital-twin\/report.html\"\n\nconfigure_production:\n  stage: configure_production\n  image: $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n  needs: \n    - testcases_digital-twin\n  environment: CML\n  tags:\n    - docker-runner\n  before_script:\n    - cd ansible\n  script: \n    - ansible-playbook 01_config_devices.yaml -i inventory_production --extra-vars \"host_var=production\"\n\ntestcases_production:\n  stage: test_production\n  image: $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n  needs:\n    - configure_production\n  environment: CML\n  tags:\n    - docker-runner\n  before_script:\n    - cd robot_framework\n    - mkdir reports_production\n  script:\n    - robot --outputdir reports_production\/ testcases_production.robot\n  artifacts:\n    untracked: false\n    when: always\n    expire_in: \"1 days\"\n    paths:\n      - \"$CI_BUILDS_DIR\/$CI_PROJECT_PATH\/robot_framework\/reports_production\/log.html\"\n      - \"$CI_BUILDS_DIR\/$CI_PROJECT_PATH\/robot_framework\/reports_production\/report.html\"\n\ndelete_digital-twin:\n  stage: delete_digital-twin\n  image: $IMAGE_NAME_ANSIBLE:$IMAGE_TAG_ANSIBLE\n  needs: \n    - testcases_production\n  environment: CML\n  tags:\n    - docker-runner\n  before_script:\n    - cd ansible\n    - unset http_proxy \n    - unset http_proxys\n  script: \n    - ansible-playbook 02_delete_CML_lab.yaml<\/xmp>\n\t\t\t\t<\/code>\n\t\t\t<\/pre>\n\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-722f4bb elementor-widget elementor-widget-heading\" data-id=\"722f4bb\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">Summary and next steps<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7c44fa7 elementor-widget elementor-widget-text-editor\" data-id=\"7c44fa7\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p>This process demonstrates the simplicity and effectiveness of establishing a workflow that incorporates a digital twin approach. It&#8217;s an excellent method for validating and testing network changes before they wreak havoc, saving network administrators from potential headaches and sleepless nights.<\/p><p>By the way, our hero Pawel emerged victorious, ensuring the application team could deploy their servers on time for the project. The day was saved, and Pawel earned himself a well-deserved reputation for reliability and competence, all thanks to the <strong>power of digital twins and a bit of automation magic<\/strong>!<\/p><p>But wait, is this the grand finale of my blog series? Absolutely not! In my next article, we&#8217;ll dive headfirst into even more challenging territory, tackling the deployment of a <span style=\"text-decoration: underline;\">BGP EVPN fabric<\/span> using a <span style=\"text-decoration: underline;\">Cisco Nexus Dashboard fabric controller<\/span>.<\/p><p>Buckle up and hold onto your hats, because we&#8217;re about to take network automation and digital twins to new heights.<\/p><p><strong>So, stay tuned, and don&#8217;t miss the next exciting episode in our ongoing journey through the captivating world of network automation!<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-948cc30 elementor-widget elementor-widget-heading\" data-id=\"948cc30\" data-element_type=\"widget\" data-widget_type=\"heading.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<h5 class=\"elementor-heading-title elementor-size-default\">References<\/h5>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-6029a65 elementor-widget elementor-widget-text-editor\" data-id=\"6029a65\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<ul><li><a href=\"https:\/\/www.openconfig.net\/\" target=\"_blank\" rel=\"noopener\">https:\/\/www.openconfig.net\/<\/a><\/li><li><a href=\"https:\/\/docs.ansible.com\/ansible\/latest\/collections\/cisco\/nxos\/index.html\" target=\"_blank\" rel=\"noopener\">https:\/\/docs.ansible.com\/ansible\/latest\/collections\/cisco\/nxos\/index.html<\/a><\/li><li><a href=\"https:\/\/robotframework.org\/robotframework\/latest\/RobotFrameworkUserGuide.html\" target=\"_blank\" rel=\"noopener\">https:\/\/robotframework.org\/robotframework\/latest\/RobotFrameworkUserGuide.html<\/a><\/li><li><a href=\"https:\/\/ansible-lint.readthedocs.io\/\" target=\"_blank\" rel=\"noopener\">https:\/\/ansible-lint.readthedocs.io\/<\/a><\/li><\/ul>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-30f8d44 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"30f8d44\" data-element_type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-5a43dde\" data-id=\"5a43dde\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-129db93 elementor-widget elementor-widget-text-editor\" data-id=\"129db93\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p class=\"p1\"><a href=\"http:\/\/192.168.1.213:8088\/unleashing-the-power-of-network-digital-twins-within-ci-cd-environments-part-1\/\"><strong>\u2b05\ufe0f Part 1 on the previous page<\/strong><\/a><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-1f59505\" data-id=\"1f59505\" data-element_type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b819d26 elementor-widget elementor-widget-text-editor\" data-id=\"b819d26\" data-element_type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<p class=\"p1\"><strong>Part 3 is coming soon \u27a1\ufe0f<\/strong><\/p>\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-41906a5 elementor-widget elementor-widget-html\" data-id=\"41906a5\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t<script type=\"text\/javascript\">\n(function($) {\n    $(window).load(function() {\n        $('.token.entity').each(function() {\n            var title = $(this).attr('title');\n            $(this).html(title);\n        })\n    });\n})(jQuery);\n<\/script>\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Table of Contents Introduction Alright, let&#8217;s get down to business \ud83d\ude80 ! In this part, I will show you how an end-to-end pipeline can be built using the digital-twin approach.\u00a0 I will use the following scenario as an example: A network administrator by the name of Pawel finds himself entrusted with the responsibility of expanding [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":1565,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_lock_modified_date":false,"footnotes":""},"categories":[11,14],"tags":[],"class_list":["post-1643","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-automation","category-cisco-technologies"],"_links":{"self":[{"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/posts\/1643"}],"collection":[{"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/comments?post=1643"}],"version-history":[{"count":25,"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/posts\/1643\/revisions"}],"predecessor-version":[{"id":1678,"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/posts\/1643\/revisions\/1678"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/media\/1565"}],"wp:attachment":[{"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/media?parent=1643"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/categories?post=1643"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/192.168.1.213:8088\/wp-json\/wp\/v2\/tags?post=1643"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}