LAB 5 — Multi-Device Network Automation: Comparing SSH, RESTCONF, and NETCONF

Learning Objectives

By the end of this lab, you will:

  • Compare and contrast SSH/Netmiko, RESTCONF, and NETCONF for network automation

  • Implement the same configuration task using all three methods

  • Understand when to use each automation method based on requirements

  • Configure a multi-device network topology using multiple automation methods

  • Handle errors and device failures across multiple devices

  • Build a hybrid automation solution that leverages strengths of each method

  • Evaluate trade-offs: code complexity, error handling, performance, and reliability

  • Deploy routing protocols and VLANs across multiple devices programmatically

  • Collect and parse operational data using different automation approaches

Purpose

This lab is the capstone of the network automation sequence. You’ve learned three distinct automation methods in previous labs:

  • Lab 1: SSH automation with Netmiko

  • Lab 3: RESTCONF with YANG models

  • Lab 4: NETCONF with ncclient

Now you’ll compare them side-by-side in realistic scenarios to understand:

  • Why we need multiple automation methods

  • Which method works best for specific tasks

  • How to build hybrid solutions that use the right tool for each job

  • Real-world decision-making for production network automation

Prerequisites

You must complete:

  • Lab 1 — SSH/Netmiko automation

  • Lab 2 — REST API fundamentals

  • Lab 3 — RESTCONF/YANG with network devices

  • Lab 4 — NETCONF/ncclient fundamentals

You should be comfortable with:

  • Python dictionaries, lists, loops, and functions

  • SSH-based device configuration with Netmiko

  • RESTCONF API calls with requests library

  • NETCONF operations with ncclient

  • CCNA-level networking (OSPF, VLANs, interface configuration)

  • Parsing structured (JSON/XML) and unstructured (CLI) data

You will need:

  • Python 3.7+ with netmiko, requests, and ncclient libraries

  • Access to 2 x Cisco 4331 routers and 2 x Cisco 3650 switches

  • All four devices pre-configured for SSH, RESTCONF, and NETCONF access

Lab Environment & Network Topology

In this lab, you will work with a four-device network connected to a management PC:

                    Management PC
                    10.10.99.5/24
                         |
         ________________|________________
         |                               |
         |                               |
    [R1] G0/0/0                    [R2] G0/0/0
    10.10.99.10/24                10.10.99.20/24
         |                               |
         | S0/1/0 (10.10.10.0/30)       | S0/1/0 (10.10.10.0/30)
         | S0/1/1 (10.10.10.4/30)       | S0/1/1 (10.10.10.4/30)
         |_______________________________|
    [R1]----------[R2]
    | G0/0/1           | G0/0/1
    | (Trunk)          | (Trunk)
    |                  |
    [S1] G0/0/1     [S2] G0/0/1
    [S1] G1/0/23    [S2] G1/0/23
    10.10.99.30/24  10.10.99.40/24
       |             |
       |  G1/0/1-4   |
       |_4 LINKS_____|
       (S1 <-> S2 trunk links)

Device Addressing:

  • R1: Management IP 10.10.99.10/24 (G0/0/0), subinterface G0/0/1.10 192.168.10.1/24 (VLAN 10)

  • R2: Management IP 10.10.99.20/24 (G0/0/0), subinterfaces G0/0/1.20 192.168.20.1/24 (VLAN 20) and G0/0/1.30 192.168.30.1/24 (VLAN 30)

  • S1: Management IP 10.10.99.30/24, connected via G1/0/23

  • S2: Management IP 10.10.99.40/24, connected via G1/0/23

  • Your Workstation: 10.10.99.5/24

  • R1-R2 Serial Links: 10.10.10.0/30 (S0/1/0) and 10.10.10.4/30 (S0/1/1)

  • User VLAN Networks:

    • VLAN 10: 192.168.10.0/24 (gateway: R1 G0/0/1.10)

    • VLAN 20: 192.168.20.0/24 (gateway: R2 G0/0/1.20)

    • VLAN 30: 192.168.30.0/24 (gateway: R2 G0/0/1.30)

  • Switch Trunk Links:

    • R1 G0/0/1 <→ S1 G0/0/1 (router-on-a-stick trunk)

    • R2 G0/0/1 <→ S2 G0/0/1 (router-on-a-stick trunk)

    • S1 G1/0/1-4 <→ S2 G1/0/1-4 (switch-to-switch quad trunk)

Lab Strategy: Because the management network (10.10.99.0/24) is pre-configured on all devices, you can reach them via SSH, RESTCONF, and NETCONF immediately after minimal console setup. This lab demonstrates the power of automation:

  1. Section 1: Minimal console setup (only management interface + API enablement)

  2. Section 2: Verify connectivity and automation access

  3. Sections 3-9: Use automation to configure everything else:

    • Serial link interfaces (R1/R2)

    • Router-on-a-stick subinterfaces (R1/R2)

    • User VLANs (S1/S2)

    • Trunk links (routers and switch-to-switch)

    • OSPF routing (R1/R2)

    • Port security and advanced features

    • Operational data collection and compliance audits

This mirrors real-world scenarios where you get initial management access quickly, then automate the rest of the network build-out.

Method Coverage Requirement: By the end of this lab, you must implement at least one complete solution using each method: Netmiko (SSH), RESTCONF, and NETCONF. Plan your method choices across Sections 3-9 to ensure all three are used.

Section 1 - Minimal Console Setup for Automation Access

In this section, you configure the absolute minimum on each device to enable management network access and remote automation APIs. After this step, all remaining configuration happens programmatically via SSH, RESTCONF, or NETCONF.

Key Principle: Minimize manual console work. The goal is to get to the automation methods as quickly as possible, then use them for all subsequent configuration. This demonstrates the value of infrastructure-as-code and programmatic management.

What’s NOT done here: Serial interfaces, user VLANs, OSPF, port security, etc. All of these will be configured via automation in subsequent sections (Sections 3-9).

Step 1: Access Device Console

Connect to each device via console cable. You’ll need to repeat Steps 2-5 for each of the four devices.

Connection Details:

  • Baud rate: 9600

  • Data bits: 8

  • Parity: None

  • Stop bits: 1

  • Flow control: None

Step 2: Basic Device Configuration (All Devices)

Perform these steps on R1, R2, S1, and S2. The configuration is nearly identical except for hostnames and IP addresses.

R1 Configuration Example

! Press Enter to get to Router> prompt
Router> enable
Router# configure terminal

! Set hostname
Router(config)# hostname R1

! Disable DNS lookup to prevent command delays on typos
Router(config)# no ip domain-lookup

! Set domain name (required for SSH key generation)
Router(config)# ip domain-name lab.local

! Create privileged user for automation access
! Username: admin, Privilege 15 (full access), Password: Cisco123!
Router(config)# username admin privilege 15 secret Cisco123!

! Generate RSA keys for SSH (minimum 1024 bits)
Router(config)# crypto key generate rsa modulus 2048
! When prompted: "Do you really want to replace them? [yes/no]:" type yes

! Set SSH version 2 only (more secure)
Router(config)# ip ssh version 2

! Configure VTY lines for SSH access
Router(config)# line vty 0 15
Router(config-line)# transport input ssh
Router(config-line)# login local
Router(config-line)# exit

Configure Management Interface (R1)

! Configure GigabitEthernet0/0/0 as management interface
R1(config)# interface GigabitEthernet0/0/0
R1(config-if)# description Management Interface
R1(config-if)# ip address 10.10.99.10 255.255.255.0
R1(config-if)# no shutdown
R1(config-if)# exit

! Set default gateway (for reaching management workstation if needed)
R1(config)# ip route 0.0.0.0 0.0.0.0 10.10.99.1

Configure Management Interface (R2)

Repeat the above but use:

  • Hostname: R2

  • Management IP: 10.10.99.20 255.255.255.0 on GigabitEthernet0/0/0

Switch-Specific Configuration: VLAN 99 Isolation

Important: Management VLAN 99 must be isolated on switches to:

  • Prevent Spanning Tree Protocol (STP) from blocking the management interface (G1/0/23)

  • Ensure management traffic cannot flow over trunk links between S1 and S2

  • Maintain strict separation between management and user traffic networks

  • Prevent accidental management access or configuration via user VLANs

Configure Management Interface (S1)

For switches, configure the management interface port directly and ensure VLAN 99 is isolated:

! After completing basic config (hostname, domain, user, SSH)
! Configure GigabitEthernet1/0/23 as management interface (connects to management PC)
S1(config)# interface GigabitEthernet1/0/23
S1(config-if)# description Management Interface to PC
S1(config-if)# switchport mode access
S1(config-if)# switchport access vlan 99
S1(config-if)# no shutdown
S1(config-if)# exit

! Assign management VLAN 99 and IP address
S1(config)# vlan 99
S1(config-vlan)# name Management
S1(config-vlan)# exit

S1(config)# interface vlan 99
S1(config-if)# description Management VLAN
S1(config-if)# ip address 10.10.99.30 255.255.255.0
S1(config-if)# no shutdown
S1(config-if)# exit

! Set default gateway
S1(config)# ip default-gateway 10.10.99.1

! Configure trunk ports (G1/0/1 through G1/0/4) to exclude VLAN 99 from user traffic
S1(config)# interface range GigabitEthernet1/0/1-4
S1(config-if-range)# description Trunk to S2 (user VLANs only)
S1(config-if-range)# switchport mode trunk
S1(config-if-range)# switchport trunk allowed vlan remove 99
S1(config-if-range)# no shutdown
S1(config-if-range)# exit

Configure Management Interface (S2)

Repeat the above configuration but use:

  • Hostname: S2

  • Management IP: 10.10.99.40 255.255.255.0 on VLAN 99

  • Management interface: GigabitEthernet1/0/23

  • Same trunk port configuration (G1/0/1-4) excluding VLAN 99

Step 3: Enable RESTCONF (All Devices)

On each device, enable the RESTCONF API:

! Enable HTTPS server (required for RESTCONF)
R1(config)# ip http secure-server

! Enable RESTCONF over HTTPS
R1(config)# restconf

! Optional but recommended: disable plain HTTP
R1(config)# no ip http server

Verify RESTCONF is running:

R1# show platform software yang-management process

You should see output indicating RESTCONF is running with status "running".

Step 4: Enable NETCONF (All Devices)

On each device, enable the NETCONF API:

! Enable NETCONF-YANG (runs on port 830 by default)
R1(config)# netconf-yang

! Optional: Enable NETCONF SSH for troubleshooting
R1(config)# netconf-yang feature candidate-datastore

Verify NETCONF is enabled:

R1# show platform software yang-management process

You should see netconf listed with status "running".

Step 5: Save Configuration (All Devices)

Critical: Save the running configuration on each device:

R1# write memory
! or
R1# copy running-config startup-config

Step 6: Test Connectivity from Management Workstation

From your management workstation (10.10.99.5), verify network connectivity to all four devices:

# Ping all devices
ping -c 3 10.10.99.10  # R1
ping -c 3 10.10.99.20  # R2
ping -c 3 10.10.99.30  # S1
ping -c 3 10.10.99.40  # S2

Expected Result: All pings should succeed. If not, troubleshoot:

  • Check interface status: show ip interface brief

  • Verify VLAN 99 is up on switches: show vlan brief

  • Check physical cable connections

  • Verify workstation has IP 10.10.99.5/24 and default gateway 10.10.99.1

Step 7: Create Device Inventory File

Create a Python inventory file to store device information for use throughout the lab.

Save this file as device_inventory.py in your lab working directory. You’ll import it in all subsequent scripts:

from device_inventory import devices, routers, switches, all_devices

Step 8: Summary Checklist

Before proceeding, verify you have completed these tasks on all four devices:

R1 Configuration Checklist:

  • Hostname set to R1

  • Domain name: lab.local

  • User admin created with password Cisco123!

  • RSA keys generated (2048 bits)

  • SSH version 2 enabled

  • VTY lines configured for SSH

  • GigabitEthernet0/0/0: IP 10.10.99.10/24, up

  • RESTCONF enabled (ip http secure-server, restconf)

  • NETCONF enabled (netconf-yang)

  • Configuration saved to startup-config

  • Ping successful from workstation

R2 Configuration Checklist:

  • Same as R1 but hostname R2, IP 10.10.99.20/24

S1 Configuration Checklist:

  • Hostname set to S1

  • Domain name: lab.local

  • User admin created with password Cisco123!

  • RSA keys generated (2048 bits)

  • SSH version 2 enabled

  • VTY lines configured for SSH

  • VLAN 99 created and named Management

  • Interface VLAN 99: IP 10.10.99.30/24, up

  • GigabitEthernet1/0/23: access port, VLAN 99 only

  • GigabitEthernet1/0/1-4: trunk ports with VLAN 99 removed

  • RESTCONF enabled

  • NETCONF enabled

  • Configuration saved to startup-config

  • Ping successful from workstation

S2 Configuration Checklist:

  • Same as S1 but hostname S2, IP 10.10.99.40/24

  • GigabitEthernet1/0/23 configured as management interface

Management Workstation:

  • IP address 10.10.99.5/24 configured

  • Can ping all four devices

  • device_inventory.py file created

Once all checkboxes are complete, you’re ready to proceed to Section 2.

Section 2 - Environment Verification

Step 1: Create Device Inventory Structure

You already created device_inventory.py in Section 1, Step 7. Verify you can import it in a test script:

# test_inventory.py
from device_inventory import devices, routers, switches, all_devices

# Display device information
print(f"Total devices: {len(all_devices)}")
print(f"Routers: {routers}")
print(f"Switches: {switches}")

# Show one device's details
print(f"\nR1 Details:")
for key, value in devices['R1'].items():
    print(f"  {key}: {value}")

Expected Output:

Total devices: 4
Routers: ['R1', 'R2']
Switches: ['S1', 'S2']

R1 Details:
  device_type: cisco_ios
  host: 10.10.99.10
  username: admin
  password: Cisco123!
  port: 22
  restconf_url: https://10.10.99.10
  netconf_port: 830

Step 2: Baseline Configuration Collection

Write a script which collects the current configurations from each device and saves them to the management host.

Section 3: Serial Interfaces and Router-on-a-Stick Subinterfaces via Three Methods

Objective: Configure the R1↔R2 serial interfaces (S0/1/0 and S0/1/1) and router-on-a-stick subinterfaces (G0/0/1.x) using SSH, RESTCONF, and NETCONF to compare approaches for interface configuration.

Context: You’ve configured interfaces manually (Section 1, console) and via single-method scripts (Labs 1, 3, 4). Now you’ll implement all three methods in one section to directly compare their differences, including subinterfaces for router-on-a-stick.

Configuration Target:

R1:
  interface Serial0/1/0
    ip address 10.10.10.1 255.255.255.252
    no shutdown
  interface Serial0/1/1
    ip address 10.10.10.5 255.255.255.252
    no shutdown
   interface GigabitEthernet0/0/1
      no shutdown
   interface GigabitEthernet0/0/1.10
      encapsulation dot1q 10
      ip address 192.168.10.1 255.255.255.0
      no shutdown

R2:
  interface Serial0/1/0
    ip address 10.10.10.2 255.255.255.252
    no shutdown
  interface Serial0/1/1
    ip address 10.10.10.6 255.255.255.252
    no shutdown
   interface GigabitEthernet0/0/1
      no shutdown
   interface GigabitEthernet0/0/1.20
      encapsulation dot1q 20
      ip address 192.168.20.1 255.255.255.0
      no shutdown
   interface GigabitEthernet0/0/1.30
      encapsulation dot1q 30
      ip address 192.168.30.1 255.255.255.0
      no shutdown

3.1 Method A: SSH with Netmiko

Your Task:

  1. Review Lab 1 Section 3 (SSH with Netmiko) for the connection and configuration patterns

  2. Design a Python function that:

    • Takes a device name and connect dictionary (from device_inventory)

    • Generates the serial interface and subinterface commands for R1 and R2 (they differ!)

    • For R1: Configure S0/1/0, S0/1/1, and subinterface G0/0/1.10 for VLAN 10

    • For R2: Configure S0/1/0, S0/1/1, and subinterfaces G0/0/1.20 (VLAN 20) and G0/0/1.30 (VLAN 30)

    • Sends them to the device using Netmiko’s send_config_set() method

    • Returns success/failure status and any error messages

  3. Test on R1 first, then R2

  4. Verify using show ip interface brief via Netmiko

Hints:

  • Use a loop or conditional to generate different commands based on which router you’re configuring

  • The parent interface (G0/0/1) must be up before subinterfaces will pass traffic

  • Reference Lab 1 for how to handle Netmiko authentication and error handling

  • Capture the output from send_config_set() to detect configuration errors

3.2 Method B: RESTCONF

Your Task:

  1. You’ll use the Cisco-IOS-XE-native YANG model (used in Lab 3)

  2. The YANG paths for interfaces are:

    • Serial: /native/interface/Serial

    • GigabitEthernet: /native/interface/GigabitEthernet

  3. Design a Python function that:

    • Constructs JSON representing a Serial interface with IP address and no shutdown state

    • Constructs JSON for the parent physical interface (G0/0/1) and its subinterfaces

    • Uses HTTP PATCH to apply the configuration to https://<device>/restconf/data/…​;

    • Handles HTTPS certificate validation (TLS warnings from self-signed certs)

    • Returns success/failure status

  4. Test on R1 first

Resources:

  • Lab 3 Section 1-2 shows how to construct RESTCONF payloads

  • Use requests.patch() with proper headers: Content-Type: application/yang-data+json

  • Remember to include Basic Auth credentials

Key Challenge: Unlike Netmiko (which accepts traditional CLI), RESTCONF requires you to understand the YANG model structure for subinterfaces. Research the Cisco-IOS-XE-native model for encapsulation and subinterface layout on Cisco’s DevNet or use netconf_yang on a device to inspect the model.

3.3 Method C: NETCONF

Your Task:

  1. Review Lab 4 Section 1-2 for NETCONF pattern and ncclient usage

  2. Design a Python function that:

    • Connects via ncclient to port 830

    • Constructs XML <edit-config> RPCs for serial interfaces and subinterfaces

    • Applies it with operation="merge" (nondestructive)

    • Returns success/failure status

  3. Test on R1 first

Resources:

  • Lab 4 shows the edit-config RPC structure

  • The XML structure differs from JSON but describes the same configuration

  • Use manager.edit_config() with the constructed XML

Key Challenge: NETCONF requires XML instead of JSON. Build the XML step-by-step on a test device using NETCONF get-config to inspect existing structure, then mimic it. Pay attention to how subinterfaces are nested under the parent interface.

3.4 Comparison Analysis

Your Task:

Create a comparison table addressing:

  • Lines of Code: Which method required the least code?

  • Readability: Which is easiest to understand 6 months from now?

  • Error Handling: Which method provided the clearest error messages?

  • Verification: How did you verify the configuration was correct for each method?

  • Learning Curve: Which required the most research/documentation reading?

  • Production Viability: Which would you choose for a large-scale deployment? Why?

3.5 Verify Configuration via All Three Methods

Your Task:

  1. Retrieve interface configuration using all three methods (SSH, RESTCONF, NETCONF)

  2. Verify that configured interfaces show:

    • Serial interfaces (S0/1/0, S0/1/1): Correct IPs, "up" status, correct subnet mask

    • Parent interface (G0/0/1): "up" status

    • Subinterfaces (G0/0/1.10, .20, .30): Correct VLAN IDs, encapsulation dot1q, correct IPs

  3. Compare how verification output differs between methods:

    • SSH returns text (requires parsing)

    • RESTCONF returns JSON (structured)

    • NETCONF returns XML (structured)

Section 4: Bulk Interface Deployment across All Routers

Objective: Apply your best implementation from Section 3 (serial interfaces and subinterfaces) to both R1 and R2 in a single, production-ready script with proper error handling.

Context: Section 3 tested single methods on one device. Section 4 focuses on scalability, robustness, and reporting across multiple devices—the hallmark of production automation.

Task:

  1. Choose one method (SSH, RESTCONF, or NETCONF) from Section 3

    • Reminder: Your overall lab choices must include at least one Netmiko, one RESTCONF, and one NETCONF solution.

  2. Refactor your code to:

    • Iterate over the routers list from device_inventory.py

    • Apply serial and subinterface configuration to each router

    • Handle per-device failures gracefully (don’t abort if one device fails)

    • Track which devices succeeded and which failed

  3. Generate a structured report (table, JSON, or CSV) showing:

    • Device name

    • Configuration status (success/failure)

    • Timestamp

    • Any error messages

4.1 Multi-Device Loop Structure

Your Task:

  1. Create a function that takes a method name ("ssh", "restconf", or "netconf") and a list of devices

  2. Iterate over each device and attempt to configure it

  3. Use try/except to catch errors per-device and continue (don’t abort)

  4. Store results in a data structure (list of dicts, or similar) for reporting

Guidance:

  • Review how Lab 1, 3, and 4 handled connection errors

  • Ensure connection objects are created/destroyed cleanly for each device

  • Consider: Should you reuse a connection for multiple operations? When should you open/close connections?

4.2 Error Handling and Logging

Your Task:

  1. Your script must handle:

    • Connection timeouts

    • Authentication failures

    • Missing device inventory entries

    • Configuration rejection (device refuses the config)

  2. For each error, log:

    • The device name

    • The error type

    • The error message

    • Recovery action taken (e.g., "skipped device", "will retry", "aborted")

  3. Do not show raw credentials in logs or error output

Guidance:

  • Python’s built-in logging module is recommended

  • Alternatively, print to a file with timestamps

  • Consider: What errors are retryable vs. fatal?

4.3 Results Collection and Reporting

Your Task:

  1. After all devices are processed, generate a report showing: [source] ---- Configuration Report: Serial and Subinterfaces (2024-02-16 14:30:00)

    Device    | Status  | Interfaces Configured | Notes
    -----------+---------+----------------------+-----------
    R1        | SUCCESS | S0/1/0, S0/1/1, G0/0/1.10 | Verified via SSH
    R2        | SUCCESS | S0/1/0, S0/1/1, G0/0/1.20, G0/0/1.30 | Verified via SSH
    -----------+---------+----------------------+-----------
    Summary: 2/2 devices configured successfully (100%)
    ----
  2. Include:

    • Total devices attempted

    • Total devices succeeded/failed

    • Percentage success rate

    • List of failed devices (if any)

4.4 Analysis: Single vs. Bulk Configuration

Your Task:

  1. Compare your experience configuring one device (Section 3) vs. multiple devices (Section 4)

  2. Document:

    • What complexity was added by handling multiple devices?

    • How did error handling change?

    • What assumptions did you make (all devices reachable? Same config? Different configs?)?

    • Would your code work if R1 and R2 needed slightly different configurations?

    • How would you modify the code to support S1, S2, and future routers?

Reflection Questions:

  • Why is error handling more important in bulk operations?

  • How would you handle a scenario where R1 succeeds but R2 fails?

  • Should partial success (1/2 devices configured) be treated as success or failure?

Section 5: Routing Protocol Deployment (OSPF)

Objective: Configure OSPF on both routers to enable dynamic routing between R1 and R2.

Important: This is your first encounter with OSPF via automation. You will NOT see complete code examples. Instead, you’ll apply CCNA routing knowledge combined with automation techniques from Labs 1, 3, and 4.

Background: OSPF (Open Shortest Path First) is a dynamic routing protocol. Both R1 and R2 need to:

  1. Enable OSPF process 1 in area 0

  2. Advertise their networks (serial links, management network, and VLAN networks)

  3. Form a neighbor relationship

Manual CLI Example (for reference—what you’re automating):

R1(config)# router ospf 1
R1(config-router)# network 10.10.10.0 0.0.0.3 area 0
R1(config-router)# network 10.10.99.0 0.0.0.255 area 0
R1(config-router)# network 192.168.10.0 0.0.0.255 area 0
R1(config-router)# exit
R1# show ip ospf neighbors

R2(config)# router ospf 1
R2(config-router)# network 10.10.10.4 0.0.0.3 area 0
R2(config-router)# network 10.10.99.0 0.0.0.255 area 0
R2(config-router)# network 192.168.20.0 0.0.0.255 area 0
R2(config-router)# network 192.168.30.0 0.0.0.255 area 0
R2(config-router)# exit
R2# show ip ospf neighbors

5.1 OSPF Configuration via Your Chosen Method

Your Task:

  1. Choose ONE method (SSH, RESTCONF, or NETCONF) to configure OSPF

    • Reminder: Your overall lab choices must include at least one Netmiko, one RESTCONF, and one NETCONF solution.

  2. Implement configuration for R1 and R2

  3. Your implementation must:

    • Detect which router is being configured (R1 vs. R2) and send appropriate networks (serial, management, VLANs)

    • Handle errors gracefully

    • Allow verification after configuration

Method Guidance:

Option A (SSH/Netmiko):

  • Reference Lab 1 for Netmiko patterns

  • Use send_config_set() with OSPF commands

  • Challenge: How do you verify OSPF came up successfully? Parse show ip ospf neighbors output?

Option B (RESTCONF):

  • The Cisco-IOS-XE-native YANG model has paths under /native/router/ospf

  • You’ll need to research the structure of the OSPF configuration in the YANG model

  • Challenge: OSPF configuration in YANG is complex; understand the hierarchy before you code

Option C (NETCONF):

  • Similar to RESTCONF but using XML in edit-config RPCs

  • Lab 4 Section 3 shows OSPF examples (use them for reference, not copy-paste)

  • Challenge: XML structure can be tricky; build and test incrementally

5.2 Verification: OSPF Adjacencies

Your Task:

  1. After configuring OSPF, verify it’s working by:

    • Retrieving OSPF neighbor status on both R1 and R2

    • Checking that R1 and R2 see each other as neighbors

    • Confirming neighbor state is "FULL"

  2. Use whichever method you chose (or a different one for comparison)

Verification Commands:

show ip ospf neighbors    # Shows neighbor state
show ip ospf               # Shows OSPF process status
show ip route ospf         # Shows learned routes

Challenge: Parse the output to extract neighbor state. If using structured data (RESTCONF/NETCONF), navigate the JSON/XML to find the neighbor state. This is harder than CLI but more reliable.

5.3 Troubleshooting: What to Do If OSPF Doesn’t Come Up

Debugging Checklist:

  1. Verify serial interfaces are up: show ip interface brief | include Serial

  2. Verify IP addresses match your configuration from Section 3

  3. Verify subinterfaces are up: show ip interface brief | include GigabitEthernet0/0/1

  4. Check OSPF interfaces: show ip ospf interface brief

  5. Look for interface errors: show ip ospf interface S0/1/0

  6. Check OSPF process is enabled: show ip ospf

Common Issues:

  • OSPF network statement uses inverse netmask (not CIDR)

  • Both sides must reference the same OSPF process number (1)

  • Both sides must use the same area number (0)

  • Interfaces must be up and have compatible IP addresses

Section 6: VLAN Deployment Across Switches

Objective: Create user VLANs on both S1 and S2, configure trunk links, and verify consistency across both switches.

Configuration Target:

vlan 10
  name Engineering
vlan 20
  name Sales
vlan 30
  name Guest

Reference Only (Trunk Expectations, Not a Solution):

interface GigabitEthernet0/0/1
   switchport mode trunk
   switchport trunk allowed vlan 10,20,30

interface range GigabitEthernet1/0/1-4
   switchport mode trunk
   switchport trunk allowed vlan 10,20,30

Task: Configure all three VLANs and the required trunk links on both S1 and S2 using your chosen method.

6.1 VLAN Configuration via Your Chosen Method

Your Task:

Choose ONE method (SSH, RESTCONF, or NETCONF) and implement switch VLAN and trunk configuration. * Reminder: Your overall lab choices must include at least one Netmiko, one RESTCONF, and one NETCONF solution.

Method-Specific Guidance:

Option A (SSH/Netmiko):

  • Use Lab 1 patterns for Netmiko

  • Send VLAN configuration commands: vlan X, name Y, exit

  • Configure trunk ports for router uplinks (G0/0/1) and switch-to-switch links (G1/0/1-4)

  • Challenge: Ensure commands are sent in the correct global config context

Option B (RESTCONF):

  • Use Cisco-IOS-XE-native YANG model with path /native/vlan

  • Structure your JSON payload to create multiple VLANs

  • Configure trunk ports under /native/interface/GigabitEthernet

  • Challenge: Can you create all three VLANs in a single PATCH request, or do you need three separate requests?

Option C (NETCONF):

  • Use edit-config RPC with XML payload

  • Lab 4 Section 2 shows VLAN configuration examples (reference, don’t copy-paste)

  • Configure trunk ports with XML under the GigabitEthernet interface tree

  • Challenge: Efficiently represent all three VLANs in a single edit-config

Implementation Requirements:

  • Apply to both S1 and S2

  • Configure trunk links:

    • S1 G0/0/1 and S2 G0/0/1 (router uplinks) as trunks

    • S1 G1/0/1-4 and S2 G1/0/1-4 (switch-to-switch links) as trunks

    • Allow VLANs 10, 20, 30 only (do not allow VLAN 99 on trunks)

  • Handle per-switch errors

  • Log which VLANs and trunk ports were configured on which switch

6.2 Verification and Consistency Check

Your Task:

  1. Verify on each switch: Retrieve VLAN configuration from both S1 and S2 using your chosen method

  2. Check consistency: Do both switches have the exact same VLANs and names?

  3. Generate a report:

    [source]
    ----
    VLAN Consistency Report
    S1 VLANs:
      10 (Engineering)
      20 (Sales)
      30 (Guest)
    S2 VLANs:
      10 (Engineering)
      20 (Sales)
      30 (Guest)
    Status: CONSISTENT
    ----

6.3 Comparison: Structured vs. Unstructured Verification

Your Task:

Try verifying VLANs using both structured (JSON/XML) and unstructured (CLI text) methods:

  1. If you used SSH: Also retrieve VLAN data via RESTCONF and compare

  2. If you used RESTCONF/NETCONF: Also use SSH to get CLI show vlan output

  3. Document:

    • Which method provided clearer output?

    • Which was easier to parse programmatically?

    • Which method caught errors better (e.g., if a VLAN wasn’t created)?

Section 7: Operational Data Collection

Objective: Collect and compare operational data (interface status, OSPF neighbors, VLAN status) across all four devices using all three methods.

Why This Matters: In real networks, automation isn’t just about configuring devices—it’s about verifying that configurations are actually working. You need to gather operational data to answer: "Is the network healthy?"

Method Choice: You may implement Section 7 using Netmiko, RESTCONF, or NETCONF. This section can count toward the requirement to complete at least one solution with each method.

7.1 Multi-Device Data Collection: Interfaces

Your Task:

  1. Write a script that collects interface status from all 4 devices (R1, R2, S1, S2)

  2. For each interface, extract:

    • Interface name

    • IP address (if present)

    • Status (up/down)

    • Protocol status (up/down)

  3. Format output as a table or CSV for easy review

Method Guidance:

SSH Method:

  • Use show ip interface brief on routers, show interfaces on switches

  • Parse the text output using regex or the textfsm library (used in Labs 1-4)

  • Challenge: CLI output format differs between routers and switches—handle both

RESTCONF Method:

  • Use GET on /restconf/data/ietf-interfaces:interfaces (standard YANG model)

  • Returns JSON with interface operational state

  • More consistent across device types than CLI

NETCONF Method:

  • Use get-config to retrieve interface configuration

  • Use get to retrieve operational data

  • Parse XML to find interface status

7.2 Data Collection: OSPF Status

Your Task:

  1. Retrieve OSPF neighbor status from both routers (R1 and R2)

  2. Extract:

    • Neighbor router ID

    • Neighbor IP address

    • Neighbor state (should be FULL)

    • Interface where neighbor is seen

  3. Verify both routers see each other as neighbors

Method Guidance:

SSH: Parse show ip ospf neighbors output

RESTCONF/NETCONF: Navigate to OSPF operational state in the YANG model

7.3 Data Collection: VLAN Status

Your Task:

  1. Verify that VLANs 10, 20, 30 exist on both S1 and S2

  2. Extract:

    • VLAN ID

    • VLAN name

    • Number of ports in VLAN

  3. Check for consistency (same VLANs on both switches)

Method Guidance:

SSH: Parse show vlan brief output (tricky—different columns on different platforms)

RESTCONF/NETCONF: Query VLAN operational data from YANG model

Section 8: Port Security Configuration

Objective: Configure port security on switch ports to protect against MAC address spoofing attacks.

Important: This is your first encounter with port security configuration via automation. Like OSPF, you’ll apply CCNA knowledge combined with automation techniques.

Background - Understand the Configuration

Port security protects switches from attacks where devices send traffic with forged MAC addresses. The typical configuration on an access port:

interface GigabitEthernet1/0/5
  switchport mode access
  switchport access vlan 10
  switchport port-security
  switchport port-security maximum 2          # Max devices (MACs) allowed
  switchport port-security violation restrict # Action: drop frames if violation
  switchport port-security mac-address sticky # Learn MACs dynamically

8.1 Port Security Configuration

Your Task:

Method Choice: You may implement Section 8 using Netmiko, RESTCONF, or NETCONF. This section can count toward the requirement to complete at least one solution with each method.

  1. Configure port security on 5 ports per switch (e.g., Gi1/0/1-5 on both S1 and S2)

  2. Settings:

    • Maximum 2 MAC addresses per port

    • Violation action: restrict (silent drop)

    • MAC learning: sticky (dynamic learning)

  3. Ports should already be in VLAN 10 from Section 6

Method Guidance:

Choose your approach, but note:

  • SSH: Interface range configuration works: interface range Gi1/0/1-5

  • RESTCONF: May require per-interface iteration (no range support in API)

  • NETCONF: Same as RESTCONF—per-interface is more straightforward

Implementation Requirements:

  • Create a function that takes a switch name and port range

  • Apply port-security settings

  • Handle errors gracefully

8.2 Verification: Port Security Status

Your Task:

  1. Retrieve port-security configuration from both switches

  2. Verify all configured ports have:

    • Port-security enabled

    • Maximum set to 2

    • Violation action set to restrict

    • MAC address learning enabled

  3. Create a report comparing configured vs. actual settings

Verification Commands (reference):

show port-security                    # Summary
show port-security interface Gi1/0/5  # Detailed per-port
show port-security mac-address        # Learned MACs

Section 9: Configuration Audit and Compliance

Objective: Build tools to verify that all devices have the expected configuration (no drift, no manual changes).

Context: In a production network, devices may be manually changed, or configurations may drift due to bugs or failed automation. Auditing tools catch these issues.

Method Choice: You may implement Section 9 using Netmiko, RESTCONF, or NETCONF. This section can count toward the requirement to complete at least one solution with each method.

9.1 Configuration Snapshot

Your Task:

  1. Create a function that gathers the current configuration from all devices

  2. Store it in a structured format (JSON or YAML)

  3. Include:

    • Hostname

    • Interface configuration (IP addresses)

    • OSPF configuration

    • VLAN configuration

    • Port-security settings

Guidance:

  • Use your preferred method (SSH, RESTCONF, NETCONF) to gather config

  • Structure the output so it’s easy to query and compare

  • Consider: What’s the difference between show running-config and YANG model inspection?

9.2 Compliance Check

Your Task:

  1. Define expected configuration (what "correct" looks like): [source, python] ---- expected_config = { 'R1': { 'hostname': 'R1', 'interfaces': { 'S0/1/0': {'ip': '10.10.10.1', 'mask': '255.255.255.252'}, 'S0/1/1': {'ip': '10.10.10.5', 'mask': '255.255.255.252'}, 'G0/0/0': {'ip': '10.10.99.10', 'mask': '255.255.255.0'} }, 'ospf': {'enabled': True, 'process_id': 1} }, # …​ similar for R2, S1, S2 } ----

  2. Write a comparison function that:

    • Retrieves actual configuration

    • Compares it to expected configuration

    • Reports differences (drift)

9.3 Remediation Report

Your Task:

  1. If drift is detected, generate a report showing:

    • Device name

    • Configuration item that drifted

    • Expected value

    • Actual value

    • Resolution (e.g., "auto-correct available" or "manual review required")

  2. Include suggestions for how to fix drift

Example Output:

Compliance Audit Report (2024-02-16 15:00:00)

Device R1:
  ✓ Hostname: COMPLIANT
  ✓ Serial Interface S0/1/0: COMPLIANT (IP: 10.10.10.1)
  ✓ Serial Interface S0/1/1: COMPLIANT (IP: 10.10.10.5)
  ✓ OSPF: COMPLIANT

Device R2:
  ✓ Hostname: COMPLIANT
  ✗ Serial Interface S0/1/0: DRIFT
      Expected IP: 10.10.10.2
      Actual IP: 192.168.1.1
      Suggestion: Reconfigure using Section 3/4 scripts

Summary: 3/4 devices compliant (75%)

Additional Resources

What’s Next?

After completing this capstone lab, you’ll be prepared for:

  • Ansible network automation (declarative approach)

  • Infrastructure as Code with version control

  • Network CI/CD pipelines

  • Python network automation frameworks (Nornir, Napalm)

  • Building production-grade network automation solutions

You now have the foundation to choose the right tool for any network automation task and can make informed architectural decisions for automation projects.