+++
title = "Chapter 7: Python and Nornir for Dynamic VLAN Management"
topic = "networking"
date = 2026-01-24
draft = false
weight = 7
description = "Explore dynamic VLAN management using Python and the Nornir automation framework, covering multi-vendor configuration, security, troubleshooting, and best practices for enterprise networks."
slug = "python-nornir-vlan-management"
keywords = ["Python", "Nornir", "VLAN", "Automation", "Network Engineering", "NetDevOps", "Cisco", "Juniper", "Arista", "802.1Q", "802.1ad", "Network Security"]
tags = ["Network Automation", "VLANs", "Python", "Nornir", "Enterprise Networking", "Configuration Management", "NetDevOps"]
categories = ["Networking", "Automation"]
+++

## Chapter 7: Python and Nornir for Dynamic VLAN Management

### 7.1 Introduction

In the intricate landscape of modern enterprise networks, Virtual Local Area Networks (VLANs) are fundamental for segmenting traffic, enhancing security, and optimizing performance. However, manually managing VLAN configurations across hundreds or thousands of devices can be a time-consuming, error-prone, and inefficient process. This chapter introduces a powerful solution: leveraging Python with the Nornir automation framework for dynamic and scalable VLAN management.

This chapter will guide you through the principles of network automation applied to VLANs, the technical underpinnings of VLANs, and practical, multi-vendor examples using Nornir. You will learn how to automate VLAN creation, modification, and deletion, ensuring consistency and reducing operational overhead.

**What this chapter covers:**
*   The essential technical concepts behind VLANs, including IEEE standards and common design patterns.
*   Detailed multi-vendor configuration examples for Cisco, Juniper, and Arista devices.
*   A deep dive into Nornir's architecture and how to build production-ready Python scripts for VLAN automation.
*   Critical security considerations and mitigation strategies for VLAN environments.
*   Effective verification and troubleshooting techniques.
*   Strategies for optimizing VLAN performance in large-scale deployments.

**Why it's important:**
Network automation is no longer a luxury but a necessity. By automating VLAN management, organizations can achieve faster deployment cycles, reduce human error, improve network reliability, and free up engineering resources for more strategic tasks. Nornir, with its Pythonic approach, offers a flexible and powerful toolset for achieving these goals in complex, multi-vendor environments.

**What you'll be able to do after:**
Upon completing this chapter, you will be proficient in using Python and Nornir to manage VLANs dynamically across diverse network infrastructures. You will be equipped to design, implement, secure, and troubleshoot automated VLAN solutions, significantly enhancing your network engineering capabilities.

### 7.2 Technical Concepts

VLANs allow you to logically segment a single physical network into multiple broadcast domains. This segmentation improves network performance by localizing broadcast traffic, enhances security by isolating different user groups or sensitive data, and simplifies network management by allowing for flexible reconfigurations without physical rewiring.

#### 7.2.1 VLAN Fundamentals and IEEE Standards

At its core, VLAN technology is defined by the IEEE 802.1Q standard.

*   **IEEE 802.1Q (Virtual Bridged Local Area Networks):** This standard specifies a system of tagging Ethernet frames with VLAN identification (VID). A 4-byte tag is inserted into the Ethernet frame header, containing a 12-bit VLAN ID (allowing for 4096 possible VLANs, from 0-4095) and other fields like Priority Code Point (PCP) for Quality of Service (QoS). VLANs 0 and 4095 are typically reserved. VLAN 1 is often the default native VLAN on many switches.
    *   **Access Ports:** Carry traffic for a single VLAN. Frames sent or received on an access port are typically untagged, with the switch adding or removing the 802.1Q tag internally.
    *   **Trunk Ports:** Carry traffic for multiple VLANs. Frames traversing a trunk port are usually 802.1Q tagged (except for the native VLAN traffic).
    *   **Native VLAN:** On 802.1Q trunks, one VLAN is designated as the "native VLAN". Frames belonging to the native VLAN are sent untagged across the trunk. It's a common security best practice to configure the native VLAN to an unused VLAN ID to prevent VLAN hopping attacks.

*   **IEEE 802.1ad (Provider Bridges / QinQ):** Also known as "Q-in-Q", this amendment extends 802.1Q to allow for multiple VLAN tags in a single Ethernet frame. This is primarily used in service provider networks where customers might send their own 802.1Q tagged traffic, which the provider then encapsulates with an additional "provider" tag. This creates a logical tunnel for customer VLANs over the service provider's network without consuming the provider's VLAN ID space.

**RFC/Standard References:**
*   IEEE 802.1Q: Virtual Bridged Local Area Networks - The foundational standard for VLANs. (Latest version is IEEE 802.1Q-2022)
*   IEEE 802.1ad: Provider Bridges - Extends 802.1Q for nested VLANs (QinQ).

#### 7.2.2 Network Automation Principles for VLAN Management

Automating VLAN management leverages several core NetDevOps principles:

*   **Idempotence:** An automation script should produce the same result regardless of how many times it's run. If a VLAN already exists with the desired configuration, the script should not attempt to re-create it or generate errors. This is crucial for maintaining network state.
*   **Declarative Configuration:** Instead of telling the device *how* to achieve a state (imperative), you declare *what* the desired final state should be. The automation tool (like Nornir with NAPALM) figures out the necessary steps to reach that state. This simplifies scripts and reduces complexity.
*   **Source of Truth (SoT):** A central repository (e.g., YAML files, a CMDB, NetBox) defining the desired state of your network. For VLANs, this SoT would define VLAN IDs, names, associated ports, and IP addresses. Nornir's inventory can serve as a simple SoT.
*   **Version Control:** All automation code, inventory, and templates should be stored in a version control system (like Git) to track changes, facilitate collaboration, and enable rollbacks.

#### 7.2.3 Nornir Architecture and Workflow

Nornir is a pure Python automation framework designed for inventory management, multi-vendor interaction, and flexible task execution. It focuses on being lightweight and extensible, allowing network engineers to build robust automation solutions.

**Nornir Core Components:**
*   **Inventory:** Defines your network devices (hosts), their groups, and associated data. Nornir supports various inventory plugins (YAML, NetBox, Ansible inventory).
*   **Hosts:** Individual network devices with attributes like hostname, IP address, platform, and credentials.
*   **Groups:** Logical collections of hosts, allowing you to apply common variables or tasks to subsets of your network.
*   **Tasks:** Python functions that perform operations on devices. Nornir ships with core tasks (e.g., `netmiko_send_command`, `napalm_get`) and allows custom tasks.
*   **Runners:** Determine how tasks are executed (e.g., serial, threaded, forked).
*   **Plugins:** Extend Nornir's capabilities, including inventory plugins, connection plugins (Netmiko, NAPALM), and transform functions.

**Nornir Workflow:**
1.  **Define Inventory:** Specify your devices, groups, and variables (e.g., VLAN details).
2.  **Initialize Nornir:** Load the configuration and inventory.
3.  **Filter Hosts:** Select specific devices or groups to operate on.
4.  **Define Tasks:** Write Python functions (or use built-in Nornir tasks) to interact with devices.
5.  **Run Tasks:** Execute tasks against the filtered hosts using a chosen runner.
6.  **Process Results:** Handle the output, check for errors, and store results.

```plantuml
@startuml
!theme mars

' Step 1: Define ALL elements first
component "Python Script" as PY_SCRIPT
rectangle "Nornir Framework" as NORNIR
rectangle "Inventory (YAML/NetBox)" as INVENTORY
cloud "Network Devices\n(Cisco, Juniper, Arista)" as DEVICES
component "Netmiko / NAPALM" as CONNECTORS
database "Source of Truth\n(e.g., VLAN Definitions)" as SOT

' Step 2: Then connect them
PY_SCRIPT [label="> NORNIR : Initializes
NORNIR"] INVENTORY : Loads device data
SOT [label="NORNIR : Data Input
NORNIR"] CONNECTORS : Executes tasks via
CONNECTORS [label="> DEVICES : Sends commands/configs
DEVICES"] CONNECTORS : Returns output
CONNECTORS [label="> NORNIR : Passes results
NORNIR"] PY_SCRIPT : Provides aggregated results

@enduml

Figure 7.1: Nornir Automation Workflow Architecture

nwdiag {
  network core_network {
    address = "10.0.0.0/24"
    color = "#CCFFCC"
    description = "Core Network Segment"

    core_switch_1 [address = "10.0.0.10"];
    core_switch_2 [address = "10.0.0.11"];
  }

  network access_network_a {
    address = "10.0.1.0/24"
    color = "#FFCCCC"
    description = "Access Segment A"

    access_switch_a1 [address = "10.0.1.10"];
    access_switch_a2 [address = "10.0.1.11"];
  }

  network access_network_b {
    address = "10.0.2.0/24"
    color = "#CCCCFF"
    description = "Access Segment B"

    access_switch_b1 [address = "10.0.2.10"];
    access_switch_b2 [address = "10.0.2.11"];
  }

  // Connections
  core_switch_1 -- core_switch_2;
  core_switch_1 -- access_switch_a1;
  core_switch_1 -- access_switch_b1;
  access_switch_a1 -- access_switch_a2;
  access_switch_b1 -- access_switch_b2;

  // VLAN traffic paths (conceptual)
  access_switch_a1 -- core_switch_1 [label = "VLAN 10,20"];
  access_switch_b1 -- core_switch_1 [label = "VLAN 30,40"];
}

Figure 7.2: Example Multi-VLAN Network Topology

7.3 Configuration Examples

Before diving into automation, let’s establish the manual configuration syntax for creating VLANs and assigning them to interfaces on common multi-vendor platforms. We will create VLAN 10 (Name: “Data_Users”) and VLAN 20 (Name: “Voice_Phones”), and configure an access port for VLAN 10 and a trunk port allowing both.

7.3.1 Cisco IOS-XE/NX-OS

VLAN Creation and Interface Assignment

! Cisco IOS-XE Configuration Example (also applies to NX-OS with minor syntax variations)

! Global configuration to create VLANs
vlan 10
  name Data_Users
!
vlan 20
  name Voice_Phones
!

! Configure an access port (e.g., GigabitEthernet0/1) for VLAN 10
interface GigabitEthernet0/1
  description Access Port for Data Users
  switchport mode access
  switchport access vlan 10
  switchport port-security                  ! Best practice: enable port-security
  switchport port-security maximum 2
  switchport port-security violation restrict
  switchport port-security mac-address sticky
  spanning-tree portfast                    ! Best practice: enable portfast on access ports
  spanning-tree bpduguard enable            ! Best practice: enable BPDU guard on access ports
!

! Configure a trunk port (e.g., GigabitEthernet0/2) for VLANs 10 and 20
interface GigabitEthernet0/2
  description Trunk to Core Switch
  switchport mode trunk
  switchport trunk allowed vlan 10,20       ! Allow specific VLANs on the trunk
  switchport trunk native vlan 999          ! Best practice: set native VLAN to an unused VLAN ID
  no negotiation auto                       ! Best practice: disable DTP (Dynamic Trunking Protocol)
!

! WARNING: Using 'switchport mode dynamic auto' or 'switchport mode dynamic desirable'
! can introduce security vulnerabilities like VLAN hopping. It's best practice
! to explicitly configure 'switchport mode access' or 'switchport mode trunk'
! and disable DTP using 'no negotiation auto'.

Verification Commands:

show vlan brief
show interfaces GigabitEthernet0/1 switchport
show interfaces GigabitEthernet0/2 trunk

Expected Output (Cisco):

! --- show vlan brief ---
VLAN Name                             Status    Ports
---- -------------------------------- --------- -------------------------------
1    default                          active    Gi0/0, Gi0/3, Gi0/4
10   Data_Users                       active    Gi0/1
20   Voice_Phones                     active    
999  unused_native                    active    

! --- show interfaces GigabitEthernet0/1 switchport ---
Name: GigabitEthernet0/1
Switchport: Enabled
Administrative Mode: static access
Operational Mode: static access
Administrative Trunking Encapsulation: dot1q
Operational Trunking Encapsulation: dot1q
Negotiation of Trunking: Off
Access Mode VLAN: 10 (Data_Users)
Trunking Native Mode VLAN: 1 (default)
... (further output related to port security, etc.)

! --- show interfaces GigabitEthernet0/2 trunk ---
Port        Mode             Encapsulation  Status        Native VLAN
Gi0/2       on               802.1q         trunking      999

Port        Vlans allowed on trunk
Gi0/2       10,20

Port        Vlans allowed and active in management domain
Gi0/2       10,20

Port        Vlans in spanning tree forwarding state and not pruned
Gi0/2       10,20

7.3.2 Juniper JunOS

VLAN Creation and Interface Assignment

# Juniper JunOS Configuration Example

# Create VLANs
set vlans Data_Users vlan-id 10
set vlans Voice_Phones vlan-id 20
set vlans Unused_Native vlan-id 999

# Configure an access port (e.g., ge-0/0/1) for VLAN 10
# Note: Juniper uses 'family ethernet-switching' for Layer 2 ports
set interfaces ge-0/0/1 unit 0 family ethernet-switching port-mode access
set interfaces ge-0/0/1 unit 0 family ethernet-switching vlan members Data_Users
# Optional: Enable port security features for access ports
set ethernet-switching-options secure-access-port interface ge-0/0/1.0 mac-limit 2
set ethernet-switching-options secure-access-port interface ge-0/0/1.0 mac-limit action drop

# Configure a trunk port (e.g., ge-0/0/2) for VLANs 10 and 20
set interfaces ge-0/0/2 unit 0 family ethernet-switching port-mode trunk
set interfaces ge-0/0/2 unit 0 family ethernet-switching vlan members [ Data_Users Voice_Phones ]
set interfaces ge-0/0/2 unit 0 family ethernet-switching native-vlan-id 999

# Apply and commit changes
commit and-quit

Verification Commands:

show vlans
show ethernet-switching interfaces ge-0/0/1
show ethernet-switching interfaces ge-0/0/2

Expected Output (Juniper):

# --- show vlans ---
Name             Tag     Interfaces
Data_Users       10      ge-0/0/1.0*, ge-0/0/2.0
Voice_Phones     20      ge-0/0/2.0
Unused_Native    999     ge-0/0/2.0

# --- show ethernet-switching interfaces ge-0/0/1 ---
Interface    State  VLAN members                  Blocking   Tagging
ge-0/0/1     up     Data_Users (10)               no         untagged

# --- show ethernet-switching interfaces ge-0/0/2 ---
Interface    State  VLAN members                  Blocking   Tagging
ge-0/0/2     up     Voice_Phones (20)             no         tagged
                    Data_Users (10)               no         tagged
                    Unused_Native (999)           no         untagged (native)

7.3.3 Arista EOS

VLAN Creation and Interface Assignment

# Arista EOS Configuration Example

# Create VLANs
vlan 10
  name Data_Users
!
vlan 20
  name Voice_Phones
!
vlan 999
  name Unused_Native
!

# Configure an access port (e.g., Ethernet1) for VLAN 10
interface Ethernet1
  description Access Port for Data Users
  switchport mode access
  switchport access vlan 10
  no spanning-tree portfast disable      ! Default is enabled, no-op usually.
  spanning-tree portfast bpduguard       ! Best practice: enable BPDU guard
  switchport port-security maximum 2
  switchport port-security violation restrict
  switchport port-security mac-address sticky
!

# Configure a trunk port (e.g., Ethernet2) for VLANs 10 and 20
interface Ethernet2
  description Trunk to Core Switch
  switchport mode trunk
  switchport trunk allowed vlan 10,20
  switchport trunk native vlan 999
!

Verification Commands:

show vlan
show interfaces Ethernet1 switchport
show interfaces Ethernet2 trunk

Expected Output (Arista):

# --- show vlan ---
VLAN  Name                             Status    Ports
----- -------------------------------- --------- -------------------------------
1     default                          active    Et3, Et4, Et5, Et6, Et7, Et8
10    Data_Users                       active    Et1
20    Voice_Phones                     active    
999   Unused_Native                    active    Et2

# --- show interfaces Ethernet1 switchport ---
Name: Ethernet1
Switchport: Enabled
Administrative Mode: access
Operational Mode: access
Access Mode VLAN: 10 (Data_Users)
Trunking Native Mode VLAN: 1 (default)
Trunking Allowed VLANs: 1-4094
...

# --- show interfaces Ethernet2 trunk ---
Port        Mode             Encapsulation  Status        Native VLAN
Et2         on               802.1q         trunking      999

Port        Vlans allowed on trunk
Et2         10,20

Port        Vlans allowed and active in management domain
Et2         10,20

Port        Vlans in spanning tree forwarding state and not pruned
Et2         10,20

7.4 Network Diagrams

Visualizing network configurations is crucial for understanding and validating automation scripts. We’ll use various diagramming tools to represent different aspects of VLAN management.

7.4.1 Topology Diagram (nwdiag)

This diagram shows a small network segment with a core switch and two access switches, highlighting trunk and access port connections and associated VLANs.

nwdiag {
  // Define networks/segments
  network "Core Link" {
    address = "192.168.100.0/30"
    color = "#F0F8FF";
    core_sw [label="Core-Switch", address="192.168.100.1"];
  }

  network "Access Link A" {
    address = "192.168.100.4/30"
    color = "#F5F5DC";
    core_sw; // Part of core
    access_sw_a [label="Access-Switch-A", address="192.168.100.5"];
  }

  network "Access Link B" {
    address = "192.168.100.8/30"
    color = "#E0FFFF";
    core_sw; // Part of core
    access_sw_b [label="Access-Switch-B", address="192.168.100.9"];
  }

  // Define logical connections and VLANs carried
  core_sw -- access_sw_a [label="Trunk (VLAN 10, 20)", style="dotted"];
  core_sw -- access_sw_b [label="Trunk (VLAN 10, 30)", style="dotted"];

  // End devices connected to Access Switches
  network "VLAN 10 Data" {
    color = "#ADD8E6";
    description = "Data User VLAN";
    access_sw_a;
    pc1 [label="PC-User1", address="10.0.10.10"];
  }

  network "VLAN 20 Voice" {
    color = "#90EE90";
    description = "Voice Phone VLAN";
    access_sw_a;
    phone1 [label="IP-Phone1", address="10.0.20.10"];
  }

  network "VLAN 30 Mgmt" {
    color = "#FFDAB9";
    description = "Management VLAN";
    access_sw_b;
    mgmt_server [label="Mgmt-Server", address="10.0.30.5"];
  }
}

Figure 7.3: Multi-VLAN Network Topology with Trunk and Access Ports

7.4.2 Automation Workflow Diagram (graphviz)

This diagram illustrates the flow of an automated VLAN configuration process using Nornir.

digraph VLAN_Automation_Flow {
  rankdir=LR;
  node [shape=box, style="rounded,filled", fillcolor="#F0F4FF", fontname="Arial", fontsize=11];
  edge [color="#555555", arrowsize=0.8];

  subgraph cluster_automation_system {
    label="Automation System";
    color=blue;
    style=dashed;

    SoT [label="Source of Truth\n(YAML Inventory, NetBox)"];
    NornirScript [label="Python Nornir Script"];
    JinjaTemplate [label="Jinja2 Configuration Template"];
  }

  subgraph cluster_network_devices {
    label="Network Devices";
    color=green;
    style=dashed;

    NetworkDevice1 [label="Switch 1"];
    NetworkDevice2 [label="Switch 2"];
    NetworkDeviceN [label="Switch N"];
  }

  SoT -> NornirScript [label="Provides VLAN Data"];
  JinjaTemplate -> NornirScript [label="Used by"];
  NornirScript -> NetworkDevice1 [label="Deploys Config", color="darkgreen"];
  NornirScript -> NetworkDevice2 [label="Deploys Config", color="darkgreen"];
  NornirScript -> NetworkDeviceN [label="Deploys Config", color="darkgreen"];

  NetworkDevice1 -> NornirScript [label="Sends Verification Output", color="darkred", style=dotted];
  NetworkDevice2 -> NornirScript [label="Sends Verification Output", color="darkred", style=dotted];
  NetworkDeviceN -> NornirScript [label="Sends Verification Output", color="darkred", style=dotted];

  NornirScript -> Report [label="Generates Report", shape=note, fillcolor="#FFFFCC"];
}

Figure 7.4: Automated VLAN Configuration Workflow

7.4.3 Nornir Deployment Architecture (PlantUML)

A more abstract view of Nornir’s role in a larger NetDevOps context.

@startuml
!theme mars

' Define elements first
cloud "External APIs / CMDB" as CMDB
rectangle "Git Repository\n(Source of Truth)" as GIT_SOT
component "CI/CD Pipeline\n(e.g., Jenkins, GitLab CI)" as CICD
rectangle "Nornir Automation Engine" as NORNIR_ENGINE
node "Cisco Switches" as CISCO
node "Juniper Routers" as JUNIPER
node "Arista Switches" as ARISTA
database "Monitoring / Logging" as MONITORING

' Then connect them
CMDB [label="> GIT_SOT : Syncs data
GIT_SOT"] CICD : Triggers pipeline (config change)
CICD [label="> NORNIR_ENGINE : Executes Nornir scripts
NORNIR_ENGINE"] CISCO : Deploys configuration
NORNIR_ENGINE [label="> JUNIPER : Deploys configuration
NORNIR_ENGINE"] ARISTA : Deploys configuration
NORNIR_ENGINE [label="> MONITORING : Sends logs/events
CISCO"] MONITORING : Sends telemetry
JUNIPER [label="> MONITORING : Sends telemetry
ARISTA"] MONITORING : Sends telemetry
MONITORING --> CMDB : Updates operational state
@enduml

Figure 7.5: Nornir in a NetDevOps Deployment Architecture

7.4.4 802.1Q Tag Structure (packetdiag)

Understanding the 802.1Q tag format is essential for grasping how VLANs work at Layer 2.

packetdiag {
  colwidth = 32
  node_height = 72

  // Ethernet Frame before 802.1Q
  0-47: Destination MAC
  48-95: Source MAC
  96-111: EtherType (e.g., 0x8100 for 802.1Q)

  // 802.1Q Tag (inserted after Source MAC)
  112-114: Priority Code Point (PCP) (3 bits)
  115-115: Drop Eligible Indicator (DEI) (1 bit)
  116-127: VLAN ID (VID) (12 bits)
  128-143: EtherType (original, e.g., 0x0800 for IPv4)

  // Original Ethernet Frame Payload and FCS
  144-x: Payload
  x-y: Frame Check Sequence (FCS)
}

Figure 7.6: IEEE 802.1Q Tag Structure in an Ethernet Frame

7.5 Automation Examples

This section provides a practical Nornir script to dynamically manage VLANs across multi-vendor devices. We will use Jinja2 templating for configuration consistency and napalm_configure for declarative deployment where possible, falling back to netmiko_send_config for specific commands.

Prerequisites:

  • Python 3.8+
  • pip install nornir nornir-utils nornir-napalm nornir-netmiko Jinja2

7.5.1 Nornir Configuration (config.yaml)

---
# config.yaml
inventory:
  plugin: SimpleInventory
  options:
    host_file: inventory/hosts.yaml
    group_file: inventory/groups.yaml
    defaults_file: inventory/defaults.yaml

runner:
  plugin: threaded
  options:
    num_workers: 20 # Adjust as needed

logging:
  enabled: True
  level: INFO
  to_console: True
  log_file: nornir.log

7.5.2 Nornir Inventory (hosts.yaml, groups.yaml, defaults.yaml)

inventory/defaults.yaml:

---
# inventory/defaults.yaml
username: admin
password: "" # Best practice: Use environment variables or Vault
# Add a global list of VLANs that should be present on all devices by default
# This could also be per-group or per-host
global_vlans:
  - id: 10
    name: Data_Users
  - id: 20
    name: Voice_Phones
  - id: 999
    name: Unused_Native

inventory/groups.yaml:

---
# inventory/groups.yaml
cisco_switches:
  platform: ios
  connection_options:
    netmiko:
      extras:
        global_delay_factor: 2 # Adjust for slower devices
    napalm:
      extras:
        optional_args:
          secret: "" # For 'enable' password

juniper_routers:
  platform: junos
  connection_options:
    netmiko:
      extras:
        global_delay_factor: 1
    napalm:
      extras:
        optional_args:
          port: 22

arista_switches:
  platform: eos
  connection_options:
    netmiko:
      extras:
        global_delay_factor: 1
    napalm:
      extras:
        optional_args:
          port: 22

inventory/hosts.yaml:

---
# inventory/hosts.yaml
cisco-core-01:
  hostname: 192.168.1.10
  groups:
    - cisco_switches
  data:
    interfaces:
      GigabitEthernet0/1:
        mode: trunk
        allowed_vlans: "10,20,999"
        native_vlan: 999
      GigabitEthernet0/2:
        mode: access
        access_vlan: 10
        port_security: True

juniper-access-01:
  hostname: 192.168.1.11
  groups:
    - juniper_routers
  data:
    interfaces:
      ge-0/0/1:
        mode: trunk
        allowed_vlans: "10,20,999"
        native_vlan: 999
      ge-0/0/2:
        mode: access
        access_vlan: 20

arista-access-01:
  hostname: 192.168.1.12
  groups:
    - arista_switches
  data:
    interfaces:
      Ethernet1:
        mode: trunk
        allowed_vlans: "10,20,999"
        native_vlan: 999
      Ethernet2:
        mode: access
        access_vlan: 10

7.5.3 Jinja2 Configuration Templates

We’ll use Jinja2 to render vendor-specific configurations. Create a templates/ directory.

templates/cisco_vlan_config.j2:

{% for vlan in global_vlans %}
vlan 
  name 
!
{% endfor %}

{% for if_name, if_data in interfaces.items() %}
interface 
  description Managed by Nornir Automation
  {% if if_data.mode == "access" %}
  switchport mode access
  switchport access vlan 
  spanning-tree portfast
  spanning-tree bpduguard enable
    {% if if_data.port_security %}
  switchport port-security
  switchport port-security maximum 2
  switchport port-security violation restrict
  switchport port-security mac-address sticky
    {% endif %}
  {% elif if_data.mode == "trunk" %}
  switchport mode trunk
  switchport trunk allowed vlan 
  switchport trunk native vlan 
  no negotiation auto
  {% endif %}
!
{% endfor %}

templates/juniper_vlan_config.j2:

# Juniper VLAN configuration
{% for vlan in global_vlans %}
set vlans  vlan-id 
{% endfor %}

{% for if_name, if_data in interfaces.items() %}
set interfaces  unit 0 family ethernet-switching port-mode 
  {% if if_data.mode == "access" %}
set interfaces  unit 0 family ethernet-switching vlan members 
  {% elif if_data.mode == "trunk" %}
set interfaces  unit 0 family ethernet-switching vlan members [  ]
set interfaces  unit 0 family ethernet-switching native-vlan-id 
  {% endif %}
{% endfor %}

templates/arista_vlan_config.j2:

{% for vlan in global_vlans %}
vlan 
  name 
!
{% endfor %}

{% for if_name, if_data in interfaces.items() %}
interface 
  description Managed by Nornir Automation
  {% if if_data.mode == "access" %}
  switchport mode access
  switchport access vlan 
  spanning-tree portfast bpduguard
    {% if if_data.port_security %}
  switchport port-security maximum 2
  switchport port-security violation restrict
  switchport port-security mac-address sticky
    {% endif %}
  {% elif if_data.mode == "trunk" %}
  switchport mode trunk
  switchport trunk allowed vlan 
  switchport trunk native vlan 
  {% endif %}
!
{% endfor %}

7.5.4 Python Nornir Script (deploy_vlans.py)

import os
from nornir import InitNornir
from nornir.core.filter import F
from nornir_utils.plugins.functions import print_result
from nornir_utils.plugins.tasks.data import load_yaml
from nornir_utils.plugins.tasks.files import write_file
from nornir_jinja2.plugins.tasks import template_file
from nornir_napalm.plugins.tasks import napalm_configure
from nornir_netmiko.plugins.tasks import netmiko_send_command, netmiko_send_config

# Ensure environment variables are set for credentials
# export NORNIR_PASSWORD="your_device_password"
# export NORNIR_ENABLE_PASSWORD="your_enable_password" (if applicable)

def get_vlan_config(task):
    """
    Generates the vendor-specific VLAN configuration using Jinja2 templates.
    """
    platform_map = {
        "ios": "cisco_vlan_config.j2",
        "eos": "arista_vlan_config.j2",
        "junos": "juniper_vlan_config.j2",
    }
    template_name = platform_map.get(task.host.platform)

    if not template_name:
        task.host.log_warning(f"No template found for platform: {task.host.platform}")
        return None

    # Retrieve global_vlans from host.defaults, group, or host data
    global_vlans = task.host.get('global_vlans', task.nornir.inventory.defaults.get('global_vlans', []))
    interfaces = task.host.get('interfaces', {})

    # Render the configuration template
    config_rendered = task.run(
        task=template_file,
        path="templates/",
        template=template_name,
        global_vlans=global_vlans,
        interfaces=interfaces,
    )
    return config_rendered[0].result # Return the rendered configuration string

def deploy_vlan_config(task):
    """
    Deploys the generated VLAN configuration to the device.
    Uses NAPALM for declarative configuration where possible,
    falls back to Netmiko for specific commands if needed.
    """
    task.host.log_info(f"Generating config for {task.host.name} ({task.host.platform})...")
    config_result = task.run(task=get_vlan_config)
    
    if not config_result.failed:
        config_to_deploy = config_result.result
        task.host.log_info(f"Generated config for {task.host.name}:\n{config_to_deploy}")

        # Optional: Write the generated config to a file for review/auditing
        task.run(
            task=write_file,
            filename=f"output/{task.host.name}_vlan_config.txt",
            content=config_to_deploy,
        )

        task.host.log_info(f"Deploying config to {task.host.name} ({task.host.platform})...")
        try:
            # Use NAPALM for declarative configuration where available
            result = task.run(
                task=napalm_configure,
                replace=False, # Merge configuration
                configuration=config_to_deploy,
            )
            if result.failed:
                task.host.log_error(f"NAPALM configuration failed for {task.host.name}: {result.exception}")
                return result # Propagate the failure

        except Exception as e:
            task.host.log_warning(f"NAPALM config failed for {task.host.name} ({e}). Falling back to Netmiko.")
            # Fallback to Netmiko send_config if NAPALM fails or is not preferred for platform
            result = task.run(
                task=netmiko_send_config,
                config_commands=config_to_deploy.splitlines(),
            )
            if result.failed:
                task.host.log_error(f"Netmiko configuration failed for {task.host.name}: {result.exception}")
                return result

        # Additional verification step (e.g., check VLANs)
        if not result.failed:
            task.host.log_info(f"Configuration deployed successfully to {task.host.name}. Verifying...")
            if task.host.platform == "ios":
                verify_cmd = "show vlan brief"
            elif task.host.platform == "junos":
                verify_cmd = "show vlans"
            elif task.host.platform == "eos":
                verify_cmd = "show vlan"
            else:
                verify_cmd = None

            if verify_cmd:
                verify_result = task.run(
                    task=netmiko_send_command,
                    command_string=verify_cmd,
                )
                if not verify_result.failed:
                    task.host.log_info(f"Verification for {task.host.name}:\n{verify_result.result}")
                else:
                    task.host.log_error(f"Verification command failed for {task.host.name}: {verify_result.exception}")
            else:
                task.host.log_warning(f"No specific verification command for platform {task.host.platform}")
        
        return result
    else:
        task.host.log_error(f"Failed to generate configuration for {task.host.name}.")
        return config_result


def main():
    nr = InitNornir(config_file="config.yaml")
    
    # Filter for all hosts for this example, you can filter by groups or specific hosts
    # hosts_to_manage = nr.filter(F(groups__contains="cisco_switches") | F(groups__contains="juniper_routers"))
    hosts_to_manage = nr.filter(F(platform__in=["ios", "junos", "eos"]))

    # Create an output directory if it doesn't exist
    os.makedirs("output", exist_ok=True)

    print(f"\n--- Starting VLAN deployment across {len(hosts_to_manage.inventory.hosts)} devices ---\n")
    
    results = hosts_to_manage.run(task=deploy_vlan_config)

    print("\n--- Deployment Results ---")
    print_result(results)

    if results.failed_hosts:
        print("\n--- Failed Hosts Summary ---")
        for host, result in results.failed_hosts.items():
            print(f"Host: {host}")
            for task_name, task_result in result.items():
                if task_result.failed:
                    print(f"  Task '{task_name}' failed: {task_result.exception}")
    else:
        print("\nAll VLAN configurations deployed successfully!")

if __name__ == "__main__":
    main()

7.6 Security Considerations

VLANs, while providing segmentation, are not a security panacea. Misconfigurations or vulnerabilities can expose critical assets.

7.6.1 Attack Vectors

  • VLAN Hopping: Attackers attempt to gain access to VLANs they are not authorized for.
    • Switch Spoofing (DTP Exploitation): By sending Dynamic Trunking Protocol (DTP) messages, an attacker’s device can convince a switch port to become a trunk, thereby gaining access to all VLANs traversing that trunk.
    • Double Tagging (VLAN Tag Stacking): An attacker crafts a frame with two 802.1Q tags. The outer tag matches the native VLAN of the trunk, allowing the frame to bypass the first switch. The inner tag specifies the target VLAN, which the second switch then processes, granting the attacker access.
  • MAC Address Flooding: Overwhelming the switch’s MAC address table can force it into hub-like behavior (unicast flooding), allowing an attacker to capture traffic from other devices in the same VLAN.
  • DHCP Snooping Exploitation: Malicious DHCP servers or clients can disrupt network services.
  • ARP Spoofing: Within a VLAN, an attacker can perform ARP spoofing to intercept traffic, impersonate devices, or launch man-in-the-middle attacks.

7.6.2 Mitigation Strategies

Effective VLAN security requires a multi-layered approach:

  • Disable DTP: Manually configure access ports as switchport mode access and trunk ports as switchport mode trunk with no negotiation auto (Cisco) or equivalent.
  • Change Native VLAN: Configure the native VLAN on trunks to an unused VLAN ID (e.g., VLAN 999) that does not carry any user or management traffic. Do not use VLAN 1 as the native VLAN.
  • VLAN Pruning: Limit the VLANs allowed on trunk links (switchport trunk allowed vlan ...) to only those required by the connected switch. This prevents unnecessary propagation of VLAN traffic.
  • Port Security: Configure port security on access ports to limit the number of MAC addresses allowed on a port and specify violation actions (e.g., restrict, shutdown).
  • BPDU Guard: Enable BPDU Guard on all access ports (spanning-tree bpduguard enable) to prevent rogue switches or devices from participating in Spanning Tree Protocol (STP) and potentially disrupting the network.
  • DHCP Snooping: Enable DHCP snooping to prevent rogue DHCP servers and enforce IP-to-MAC address bindings, mitigating DHCP starvation and rogue DHCP server attacks.
  • Dynamic ARP Inspection (DAI): Combine with DHCP snooping to validate ARP packets and prevent ARP spoofing attacks.
  • Private VLANs (PVLANs): Further isolate ports within the same VLAN, preventing direct Layer 2 communication between endpoints, useful for server farms or public access networks.
  • Unused Ports: Shutdown or place unused ports in an unused VLAN (e.g., a “quarantine” VLAN) and remove them from VLAN 1.
  • Control Plane Policing (CoPP): Protect the device’s CPU from malicious or excessive traffic by rate-limiting or dropping traffic destined for the control plane.
  • Regular Audits: Periodically audit VLAN configurations, port assignments, and security settings to ensure compliance and identify misconfigurations.

Security Configuration Example (Cisco - additional hardening)

! Configure a port to disable DTP and set native VLAN to an unused ID
interface GigabitEthernet0/2
  switchport mode trunk
  switchport trunk allowed vlan 10,20
  switchport trunk native vlan 999
  no negotiation auto
!

! Configure port security, BPDU guard on an access port
interface GigabitEthernet0/1
  switchport mode access
  switchport access vlan 10
  switchport port-security
  switchport port-security maximum 2
  switchport port-security violation restrict
  switchport port-security mac-address sticky
  spanning-tree portfast
  spanning-tree bpduguard enable
!

! Enable DHCP Snooping globally and per VLAN
ip dhcp snooping
ip dhcp snooping vlan 10,20
ip dhcp snooping database flash:dhcp-snooping-binding.txt
!
interface GigabitEthernet0/0      ! Trusted port connected to DHCP server
  ip dhcp snooping trust
!
interface GigabitEthernet0/1      ! Untrusted access port
  ip dhcp snooping limit rate 100
!

! Enable Dynamic ARP Inspection (DAI)
ip arp inspection vlan 10,20
!
interface GigabitEthernet0/0      ! Trusted port connected to DHCP server
  ip arp inspection trust
!

7.7 Verification & Troubleshooting

Even with automation, verification is key, and issues can still arise.

7.7.1 Verification Commands

After deploying VLAN configurations, always verify the intended state.

Cisco IOS-XE/NX-OS:

show vlan brief
show interfaces status
show interfaces GigabitEthernet0/1 switchport
show interfaces GigabitEthernet0/2 trunk
show mac address-table interface GigabitEthernet0/1
show ip dhcp snooping binding
show ip arp inspection

Juniper JunOS:

show vlans
show ethernet-switching interfaces
show ethernet-switching interfaces ge-0/0/1
show ethernet-switching interfaces ge-0/0/2
show bridge mac-table interface ge-0/0/1
show dhcp-security binding

Arista EOS:

show vlan
show interfaces status
show interfaces Ethernet1 switchport
show interfaces Ethernet2 trunk
show mac address-table interface Ethernet1

7.7.2 Common Issues and Troubleshooting

IssueSymptomsPossible Root CausesResolution Steps
VLAN Mismatch (Trunk)Inter-switch connectivity issues, STP flappingNative VLAN mismatch, allowed VLAN list mismatch, DTP negotiation failure1. Verify native VLANs are consistent on both ends of the trunk (show interfaces trunk).
2. Ensure switchport trunk allowed vlan lists are identical or at least contain all required VLANs on both sides.
3. Disable DTP (no negotiation auto) and manually set trunk mode on both sides.
Access Port No ConnectivityDevice unable to get IP, no network accessIncorrect access VLAN assignment, port disabled, port security violation1. Verify access VLAN (show interfaces <int> switchport) matches expected VLAN.
2. Check if interface is shutdown and bring it no shutdown.
3. Check show port-security interface <int> for violations. Clear violations if necessary (clear port-security all interface <int>).
4. Confirm switchport mode is access.
Trunk Not Passing All VLANsDevices in a specific VLAN cannot communicateVLAN not allowed on trunk, VLAN not active/created on switch, VLAN pruning enabled1. Check show interfaces trunk for allowed VLANs. Add missing VLANs.
2. Ensure VLANs are created and active (show vlan brief).
3. Verify VLAN pruning settings on adjacent switches.
IP Address Conflicts/No DHCPDevices fail to obtain IP addressesDHCP snooping blocking legitimate DHCP, incorrect IP helper address, VLAN routing issue1. Check DHCP snooping bindings (show ip dhcp snooping binding). If legitimate DHCP offers are being dropped, verify trusted interfaces.
2. Confirm IP helper addresses are configured on the VLAN’s SVI/interface for devices in that VLAN to reach the DHCP server.
3. Check Layer 3 routing configuration for the VLAN’s subnet.
VLAN Hopping AttackUnauthorized access to sensitive VLANsDTP enabled, default native VLAN 1, lack of port security/BPDU guard1. Disable DTP on all access and trunk ports (no negotiation auto).
2. Change native VLAN on all trunks to an unused, isolated VLAN.
3. Enable BPDU Guard on all access ports.
4. Implement Port Security on access ports.
5. Consider Private VLANs for tighter isolation in sensitive segments.

Debug Commands (Cisco - use with caution in production):

  • debug vlan
  • debug spanning-tree bpdu
  • debug dtp (if you must troubleshoot DTP, though disabling it is preferred)
  • debug ip dhcp snooping

7.8 Performance Optimization

Optimizing VLAN performance primarily involves reducing unnecessary broadcast traffic and ensuring efficient forwarding.

  • VLAN Pruning: Prevent VLAN traffic from being sent over trunk links where it’s not needed. This conserves bandwidth and reduces unnecessary processing by switches. Most switches support some form of VLAN pruning (e.g., Cisco VTP pruning, manual switchport trunk allowed vlan).
  • Reduce Broadcast Domains: Design VLANs to be appropriately sized. Overly large VLANs generate excessive broadcast traffic, impacting performance. Segmenting into smaller, more focused VLANs is generally better.
  • Efficient Spanning Tree Protocol (STP): Implement a fast and efficient STP variant (e.g., Rapid PVST+, MSTP) to ensure quick convergence in case of topology changes and prevent forwarding loops. Configure PortFast on all access ports and BPDU Guard to prevent unauthorized devices from influencing STP.
  • Jumbo Frames: If applications benefit from larger MTUs (e.g., storage, data transfer), ensure jumbo frames are enabled end-to-end across relevant VLANs and interfaces.
  • Hardware Capabilities: Leverage higher-speed interfaces (10G, 25G, 40G, 100G) and modern switching hardware with dedicated ASICs for efficient Layer 2 and Layer 3 forwarding.
  • Quality of Service (QoS): Implement QoS policies within and between VLANs to prioritize critical traffic (e.g., voice, video) over less time-sensitive data. The 802.1Q tag’s PCP field can be leveraged for this.

7.9 Hands-On Lab

This lab will guide you through using the Nornir script to deploy VLANs and interface configurations on a simulated multi-vendor network.

7.9.1 Lab Topology

We’ll use three virtual network devices (one Cisco, one Juniper, one Arista) accessible via SSH. For a real lab, these could be GNS3/EVE-NG VMs or physical devices.

nwdiag {
  // Define networks/segments
  network "Management Network" {
    address = "192.168.1.0/24"
    color = "#E6E6FA";
    description = "Out-of-band Management Network";

    automation_host [label="Automation Host\n(Nornir Script)", address="192.168.1.5"];
    cisco_sw [label="Cisco-Core-01", address="192.168.1.10"];
    juniper_sw [label="Juniper-Access-01", address="192.168.1.11"];
    arista_sw [label="Arista-Access-01", address="192.168.1.12"];
  }

  // Connections for management
  automation_host -- cisco_sw;
  automation_host -- juniper_sw;
  automation_host -- arista_sw;

  // Placeholder for data plane connections (not directly managed by script in this lab)
  cisco_sw -- juniper_sw [label="Trunk", style="dashed"];
  cisco_sw -- arista_sw [label="Trunk", style="dashed"];
}

Figure 7.7: Hands-On Lab Topology

7.9.2 Objectives

  1. Set up the Nornir environment, including config.yaml and inventory files.
  2. Deploy VLANs 10, 20, and 999 (native VLAN) and configure specific access and trunk ports on all three devices using the deploy_vlans.py script.
  3. Verify the configurations using manual commands and the Nornir script’s verification output.

7.9.3 Step-by-Step Configuration

  1. Prepare your Automation Host:

    • Install Python 3.8+ if not already present.
    • Create a dedicated directory for your lab: mkdir nornir_vlan_lab && cd nornir_vlan_lab.
    • Create a virtual environment: python3 -m venv venv && source venv/bin/activate.
    • Install Nornir and its plugins: pip install nornir nornir-utils nornir-napalm nornir-netmiko Jinja2.
    • Create config.yaml in the nornir_vlan_lab directory.
    • Create an inventory subdirectory: mkdir inventory.
    • Create inventory/hosts.yaml, inventory/groups.yaml, and inventory/defaults.yaml.
    • Create a templates subdirectory: mkdir templates.
    • Create templates/cisco_vlan_config.j2, templates/juniper_vlan_config.j2, and templates/arista_vlan_config.j2.
    • Create deploy_vlans.py in the root nornir_vlan_lab directory.
    • Populate all these files with the content from Section 7.5.
  2. Configure Network Devices:

    • Ensure your Cisco, Juniper, and Arista devices are reachable via SSH from your automation host.
    • Configure basic IP addresses and SSH access for the admin user on each device.
    • Crucially, ensure initial configuration allows Nornir/Netmiko/NAPALM to connect. For Cisco, this means line vty 0 4, login local, transport input ssh, and a local username/password. For Juniper, enable SSH. For Arista, enable SSH.
    • IMPORTANT: Clear any existing VLAN or interface configurations on the lab devices that might conflict with the script’s intended state for interfaces specified in hosts.yaml.
  3. Set Credentials:

    • Before running, set your device password as an environment variable:
      export NORNIR_PASSWORD="your_device_password"
      # If your Cisco devices require an enable password, also set:
      export NORNIR_ENABLE_PASSWORD="your_enable_password"
      
    • Replace your_device_password and your_enable_password with the actual credentials for your lab devices.
  4. Run the Nornir Script:

    • Execute the Python script: python deploy_vlans.py.
    • Observe the output. It should show Nornir connecting to each device, generating configurations, deploying them, and performing a basic verification.

7.9.4 Verification Steps

  1. Review Script Output: Check the print_result output from the script. Look for changed=True indicating successful configuration deployment and review the verification command output for each device.
  2. Manual Verification (SSH to devices):
    • Cisco-Core-01:
      show vlan brief
      show interfaces GigabitEthernet0/1 switchport
      show interfaces GigabitEthernet0/2 trunk
      
    • Juniper-Access-01:
      show vlans
      show ethernet-switching interfaces ge-0/0/1
      show ethernet-switching interfaces ge-0/0/2
      
    • Arista-Access-01:
      show vlan
      show interfaces Ethernet1 switchport
      show interfaces Ethernet2 trunk
      
    • Confirm that VLANs 10, 20, and 999 are created, and interfaces are configured as access or trunk ports with the correct VLAN assignments and security settings (where applicable).

7.9.5 Challenge Exercises

  1. Add a New VLAN: Modify inventory/defaults.yaml (or a specific host’s data) to add a new VLAN (e.g., VLAN 30, “Guest_WiFi”). Rerun the script and verify it’s deployed.
  2. Modify an Existing VLAN: Change the name of VLAN 10 from “Data_Users” to “Employee_Data”. Rerun the script. Observe if Nornir correctly identifies the change and applies it (Nornir with NAPALM’s merge is generally good for this).
  3. Change an Access Port VLAN: Modify cisco-core-01’s GigabitEthernet0/2 to be an access port for VLAN 20 instead of 10. Rerun and verify.
  4. Implement Vendor-Specific Security: Add BPDU guard configuration to the Juniper and Arista Jinja2 templates for access ports. Update the hosts.yaml data to enable a bpdu_guard: True flag on relevant interfaces and modify the template logic.

7.10 Best Practices Checklist

Adhering to best practices ensures robust, secure, and maintainable VLAN infrastructure, especially when automated.

  • Configuration Standards: Establish and enforce consistent VLAN IDs, naming conventions (e.g., VLAN ID prefix, descriptive names like VLAN_10_DATA_USERS), and subnet allocations across the network.
  • VLAN Numbering Scheme: Use a structured VLAN numbering scheme, leaving room for expansion (e.g., 10s or 100s increments). Avoid using sequential, tightly packed numbers.
  • Avoid VLAN 1: Never use VLAN 1 for production traffic, management, or as a native VLAN.
  • Dedicated Native VLAN: Assign an unused, isolated VLAN ID as the native VLAN on all 802.1Q trunks. Ensure this VLAN ID is consistent on both sides of a trunk.
  • Disable DTP: Explicitly configure access and trunk modes on interfaces and disable Dynamic Trunking Protocol (DTP) to prevent VLAN hopping attacks.
  • VLAN Pruning: Enable VLAN pruning on trunk links to restrict the propagation of unnecessary VLAN traffic, improving performance and security.
  • Port Security: Implement port security on access ports to limit MAC addresses and prevent unauthorized devices from connecting.
  • BPDU Guard/Root Guard: Enable BPDU Guard on all access ports and Root Guard on appropriate trunk ports to protect the Spanning Tree Protocol (STP) topology.
  • DHCP Snooping/DAI: Implement DHCP Snooping and Dynamic ARP Inspection (DAI) on switches to mitigate DHCP starvation and ARP spoofing attacks.
  • Private VLANs: Utilize Private VLANs for tighter isolation within a broadcast domain, especially in server farms or shared hosting environments.
  • Unused Ports: Shutdown unused ports and move them into a dedicated, isolated VLAN (not VLAN 1).
  • Layer 3 Boundaries: Place Layer 3 VLAN interfaces (SVIs) on core/distribution switches, not access switches, for optimal routing and security policy enforcement.
  • Source of Truth (SoT): Maintain a reliable SoT for all VLAN definitions and interface assignments, ideally integrated with a CMDB or network inventory tool like NetBox.
  • Version Control: Store all automation scripts, inventory, and Jinja2 templates in a version control system (e.g., Git).
  • Idempotent Automation: Design automation scripts to be idempotent, ensuring consistent results regardless of how many times they run.
  • Error Handling and Logging: Include robust error handling, logging, and reporting in your automation scripts to monitor deployment success and quickly identify failures.
  • Regular Audits: Schedule automated audits to compare desired state (from SoT) with operational state, identifying deviations and misconfigurations.

7.12 What’s Next

This chapter provided a comprehensive look at dynamic VLAN management using Python and Nornir. You’ve gained an understanding of VLAN fundamentals, multi-vendor configurations, and how to build robust automation scripts.

Key Learnings Recap:

  • VLANs are essential for network segmentation and efficiency, governed by IEEE 802.1Q and 802.1ad.
  • Nornir provides a flexible Python framework for managing network devices across various vendors.
  • Jinja2 templating is critical for generating dynamic and consistent configurations.
  • VLAN security requires proactive measures against attacks like VLAN hopping.
  • Thorough verification and adherence to best practices are paramount for stable VLAN deployments.

In the next chapter, we will delve into Chapter 8: Advanced Routing Protocols with Automation, exploring how to automate the deployment and management of OSPF, EIGRP, and BGP configurations using similar NetDevOps principles and tools, further expanding your network automation capabilities. We’ll also touch upon how VLANs integrate with these routing protocols at Layer 3.

Advanced topics to explore:

  • Integrating Nornir with a true Source of Truth like NetBox for dynamic inventory and desired state management.
  • Building CI/CD pipelines to automate the testing and deployment of VLAN changes.
  • Implementing pre- and post-checks in Nornir workflows for robust change validation.
  • Extending Nornir with custom plugins for unique device interactions or reporting.
  • Exploring private VLANs (PVLANs) and their automation for stricter segmentation.
  • Connecting on-premises VLANs to cloud network segmentation (AWS VPCs, Azure VNets) in hybrid cloud environments.