Page 1 of 1

Automating dynamic port VLAN changes on Cisco IOS

Posted: Fri Apr 17, 2020 2:59 pm
by Tomas
A small script that will automate access VLAN change on ports on Cisco IOS (including IOS-XE).

You set a source VLAN and a target VLAN.
This will find all access ports in the source VLAN, and change these to the desired target vlan.

Make sure to set "Require Enable mode" so Unimus switches the device to privileged exec before running the commands.

This uses the Cisco IOS tclsh to dynamically loop over all interfaces and make changes.
Unimus is used for script delivery and result validation network-wide.

More info on tclsh in IOS: https://www.cisco.com/c/en/us/td/docs/i ... t-tcl.html

Code: Select all

tclsh

set source_vlan 100
set target_vlan 200

set ifaces [split [exec "show interface status"] "\n"]
foreach if_line $ifaces {
  if [regexp {^([^ ]+) {2}.+ {2}.+ +([0-9]+) .+} $if_line match ifo vlan] {
    if {$vlan == $source_vlan} {
      ios_config "interface $ifo" "switchport access vlan $target_vlan"
    }
  }
}

Re: Automating dynamic port VLAN changes on Cisco IOS

Posted: Tue Apr 21, 2020 2:35 am
by zbiles
Thanks Tomas for your help on this! I took this one or two steps further, to also automate the deployment of the vlan on trunk links if that's something that needs to be done (i.e. this is a brand new vlan for your environment). Assuming you are specifying vlans on trunk links, this will be a huge time saver. Might not be the most elegant way to do it, but so far it seems to work as intended in my lab. It also creates the L2 vlan if it doesn't already exist. (There's a bunch of "puts" to show messages along the way that you can comment out or remove for prod). I'm using vlan 4000 to differentiate trunks to switches vs trunks to other things like servers, but you could use whatever vlan makes sense in your environment.

Code: Select all

tclsh

set show_trunks [exec "show interface trunk"]
set show_interfaces [exec "show interface status"]

set source_vlan 100
set target_vlan 200
set target_vlan_name TEST_VLAN
set trunking_vlan 4000

set vlan_db [split [exec "show vlan brief"] "\n"]
foreach vlan_line $vlan_db {
  if [regexp {^([^ ]+)} $vlan_line match vlan_var] {
    if {$vlan_var == $target_vlan} {
      set vlan_check "exists"
      puts "$vlan_check exists, no need to create"
      break
    } else {
      set vlan_check "not_exist"
      puts "vlan $target_vlan not found, need to create"
    }
  }
}

if {$vlan_check == "not_exist"} {
  puts "creating vlan $target_vlan"
  ios_config "vlan $target_vlan" "name $target_vlan_name" "exit"
}


set ifaces [split [exec "show interface status"] "\n"]
foreach if_line $ifaces {
  if [regexp {^([^ ]+) {2}.+ {2}.+ +([0-9]+) .+} $if_line match ifo vlan] {
    if {$vlan == $source_vlan} {
      ios_config "interface $ifo" "switchport access vlan $target_vlan"
    }
  }
  #if [regexp {^([^ ]+) {2}.+ {2}.+ +trunk .+} $if_line match ifo] {
  #  ios_config "interface $ifo" "switchport trunk allowed vlan add $target_vlan"
  #}
}

#build list of trunk ports to change
set temp_trunk_ifaces [split [exec "show spanning-tree vlan $trunking_vlan | begin Gi"] "\n"]
foreach tIface $temp_trunk_ifaces {
  if [regexp {^([^ ]+) {2}.+ {2}.+ {2}.+ {2}.+ +([A-Za-z]+) .+} $tIface match tIfo iType ] {
    puts "$tIfo is an uplink to another switch"
    if {$iType == "P2p"} {
      ios_config "interface $tIfo" "switchport trunk allowed vlan add $target_vlan"
    } elseif {$iType == "Edge"} {
      puts "$tIface is NOT a an uplink to another switch"
    }
  }
}


puts [exec "show interface trunk"]
puts [exec "show interface status"]

#exec "write memory"