This lab pushes the topology significantly further. A second Juniper router has been added, OSPF has been removed from the edge devices, and the named routers have been trimmed back to area zero only. Your task is to configure OSPF on both Juniper routers to bring them into the routing domain, then deploy iBGP across all four named Cisco routers using a Jinja2 template driven entirely by host variable files. By the end of this session you have a functioning multi-vendor OSPF and iBGP topology configured entirely through Ansible without touching a single CLI prompt.
The lab works through six tasks across two distinct phases – Juniper OSPF first, then Cisco iBGP.
The first task is inspecting the host variable files for the Juniper devices. At this point the host_vars files for junos1 and junos2 contain interface details only, collected using the same automated get_interfaces approach introduced in the previous lab but adapted for Juniper. The Juniper version uses show interfaces terse display json and show interfaces descriptions display json, leverages a Juniper-specific interface template, and writes the output directly into the host_vars YAML file. An important warning is covered here – the script overwrites rather than appends, so if you have manually added OSPF or BGP data to a host_vars file and then re-run the interface collection script, you will lose everything you added. This is a real operational gotcha worth understanding before you rely on these scripts in a production-like environment.
The second task is writing the Juniper OSPF playbook. Because both Junos routers share the same interface layout – ge-0/0/0, ge-0/0/1 and ge-0/0/2 – there is no need for a Jinja2 template here. The configuration is consistent across both devices so we can write it directly. The module used is junipernetworks.junos.junos_ospfv2, which follows a structured config block with an areas list. Area ID is specified in dotted notation as 0.0.0.0, which is the Juniper convention rather than the integer zero used on IOS. The interfaces list includes the three physical gigabit interfaces plus loopback lo0.0 set as passive, preventing Juniper from attempting to form an OSPF neighborship on the loopback interface. The playbook targets only the junos host group and uses gather_facts: false.
The third task is verifying the Juniper OSPF configuration using a dedicated show playbook with the junipernetworks.junos.junos_command module. Two show commands are run – show ospf neighbor and show route protocols ospf. A subtle but important point is covered here: the correct Juniper command is show route protocols ospf, not show route ospf, and the lab demonstrates the failure you get from the incorrect syntax before correcting it. Output is registered to named variables and displayed using the debug module with var and stdout_lines. The verification confirms that junos1 has established OSPF neighbourships with Manchester and London, and junos2 has adjacencies with Asia and America, with all loopback routes learned correctly across the topology.
The fourth task is inspecting the updated host_vars files for the named Cisco routers. Since the previous lab, an ibgp section has been added to each file containing the autonomous system number, the BGP router ID matching the router loopback address, and a peers list. Each entry in the peers list contains the neighbour IP address and the remote AS number. All four named routers are in the same autonomous system – AS 65000 – making this a full iBGP mesh. The key naming convention used here is worth noting: the YAML key is ibgp but it could be named anything. Ansible does not care about the key name, only that the playbook and template reference it consistently.
The fifth task is building the BGP Jinja2 template. The template follows the same structure as the OSPF template from the previous lab but with BGP-specific commands. It opens with router bgp and pulls the ASN from ibgp.asn. It then sets bgp router-id from ibgp.bgp_router_id. A Jinja2 for loop iterates over ibgp.peers and generates three lines per neighbour – neighbor address remote-as pulling from peer.peer_asn, neighbor address update-source loopback0 to ensure BGP sessions source from the loopback interface for stability, and neighbor address next-hop-self to ensure that when eBGP is eventually added at the edge, iBGP peers can forward traffic correctly without route blackholing due to next-hop reachability issues. The loop closes with endfor. The entire template is compact but generates a complete and correct iBGP neighbour stanza for every peer defined in the host_vars file.
The sixth task is writing and running the BGP deployment playbook and verification playbook. The deployment playbook uses cisco.ios.ios_config with the lookup parameter pointing at the bgp.j2 template file, exactly as was done for OSPF in the previous lab. Ansible automatically searches the templates directory so no full path is required. The playbook targets only the routers group – the four named Cisco routers – and gather_facts is disabled. The verification playbook uses cisco.ios.ios_command to run show bgp neighbor and show bgp summary across all four routers, registering output and displaying it via the debug module. The output confirms neighbourships are established, prefixes are being sent and received, and iBGP is operational across the full mesh.
By the end of this lab you will understand how to configure OSPF on Juniper JunOS devices using the junos_ospfv2 module including passive interface configuration, how to specify Juniper area IDs in dotted notation, how to build a Jinja2 BGP template with for loops iterating over a peers list from host variable files, how to deploy iBGP across multiple routers from a single playbook with no hardcoded neighbour addresses, how to use update-source loopback and next-hop-self correctly in an iBGP context, and how to verify BGP neighbour state and prefix exchange across a multi-router topology using Ansible.
All host variable files, Jinja2 templates and playbooks from this lab are available on the GitHub lab 7 repo linked in the course resources.