About a year ago /u/packetsar shared FreeZTP on reddit, just in time for a project that required upgrade/configuration of 400+ IOS-XE switches (3650/3850, several stacks). Over the following months, he was extremely receptive and accommodating with feature updates and tweaks; so kudos, pal.
This is a sanitized example of a switch template that I built out with a strong focus on keeping the process as simple and unbreakable as possible for the intended end-users, at the cost of a self-imposed excessively large learning curve. My last three blog posts were a direct result of achieving this goal; something that a lot of docs, labbing, and scouring of community forums contributed to.
A Few Disclosures
- I do not have a background in development, this was my first venture into any kind of programming/templating. This was largely an exercise in figuring out what I could accomplish in the template, without having to manually intervene, whether it be via python, console, or otherwise. There are probably some development best-practices that I unwittingly spat in the face of, or more optimal ways to accomplish some of these functions.
Smart-install is deprecated as of IOS-XE 16.3.7+ (still works in 16.3.6).This does not impact AutoInstall.- /u/packetsar has done an excellent job detailing all facets of FreeZTP, so questions/concerns regarding its inner-workings are better answered by the project's GitHub readme.md.
FreeZTP config
I configured FreeZTP to use external keystore and template files. This kept the code and other sensitive template information somewhat concealed, for lack of a better term. This also kept ztp show config
outputs concise and easier to read when validating FreeZTP settings.
ztp set external-keystore SBS type csv && \
~ztp set external-keystore SBS file '/srv/ztp/keystore/ks_asw.csv' && \
~ztp set external-template SBS file '/srv/ztp/template/tmpl_asw.j2'
CSV
The CSV file has minimal headings; keystore_id
(hostname), association
(template), and idarray_1
- idarray_4
for the switch serial numbers (our defined stack limitation for this project).
keystore_id,association,idarray_1,idarray_2,idarray_3,idarray_4
ASW-TR04-02,ASW,FOC11111111,FOC22222222,FOC33333333,FOC44444444
Template
-
First section provides guidelines and outputs the variables that ZTP passed into the template.
-
Second section defines static variables that I didn't want to store in the CSV; e.g. protocol secrets/keys, syslog server addresses, and other things that the template will use.
-
Third section assigns dynamic values to variables.
Expand for
Dynamic Variable Example gi_ints
is a list of GigabitEthernet interfaces, which scales with the number of switches in the stack.Switch Count gi_ints
1 gi1/0/1-36
2 gi1/0/1-36,gi2/0/1-36
3 gi1/0/1-36,gi2/0/1-36,gi3/0/1-36
4 gi1/0/1-36,gi2/0/1-36,gi3/0/1-36,gi4/0/1-36
{%-set tmpl={"file":"tmpl_test.j2",
"rev":"8"}-%}
{%-set indent="\n!"~" "*23-%}
!-- --------------------------------------------------------------------------- --!
!-- ***IMPORTANT (Example)*** --!
!-- Hostname (keystore_id in CSV) has strict formatting rules. --!
!-- --!
!-- * TR and switch/stack numbers must each be two digits (use leading '0'). --!
!-- * TRs are numbered 1-9. --!
!-- * Any TR can only accommodate up to 9 switches/stacks; i.e. 01-09. --!
!-- * Any stack is only intended to have 4 switches; i.e. idarray_1-4. --!
!-- --!
!-- Example for TR-4, switch/stack 1... --!
!-- --!
!-- Access Switch | TR Number | Switch/Stack Number --!
!-- ----------------------|------------------------|---------------------- --!
!-- ASW | TR04 | 02 --!
!-- --!
!-- Example hostname: ASW-TR04-02 --!
!-- --------------------------------------------------------------------------- --!
!
!-- Variables (keys) parsed from CSV keystore.
!
!---- KEYSTORE_ID > {{keystore_id|default("N/A")}}{# Used to associate the switch to a template (serial number).#}
!---- ASSOCIATION > {{association|default("N/A")}}{# Switch template associated with KEYSTORE_ID.#}
!---- IDARRAY_1 > {{idarray_1|default("N/A")}}{# Switch 1 serial number.#}
!---- IDARRAY_2 > {{idarray_2|default("N/A")}}{# Switch 2 serial number.#}
!---- IDARRAY_3 > {{idarray_3|default("N/A")}}{# Switch 3 serial number.#}
!---- IDARRAY_4 > {{idarray_4|default("N/A")}}{# Switch 4 serial number.#}
!---- IDARRAY > {{idarray|default("N/A")}}{# All switch serial numbers.#}
!
!---------------------------------------------------------------- VARIABLES: STATIC
!
!-- Variables (keys) statically defined within the template.
!-- Variables with multiple values are JSON formatted.
!{# VARIABLE > {%set VARIABLE="VALUE"%} <<< set | print >>> {{VARIABLE}} #}
!---- TFTP_ADDR > {%set tftp_addr="172.17.251.251"%}{# #}{{tftp_addr}}
!---- DOMAIN > {%set domain="exmaple.local"%}{# #}{{domain}}
!---- STP_PRIORITY > {%set stp_priority="28672"%}{# #}{{stp_priority}}
!---- ENABLE_SEC > {%set enable_sec="enable-secret"%}{# #}{{enable_sec}}
!---- TACACS_KEY > {%set tacacs_key="tacacs-secret"%}{# #}{{tacacs_key}}
!---- RADIUS_KEY > {%set radius_key="radius-secret"%}{# #}{{radius_key}}
!---- NTP_KEY > {%set ntp_key="ntp-secret"%}{# #}{{ntp_key}}
!---- SYSLOG_ADDR > {%set syslog_addr="10.255.1.1"%}{# #}{{syslog_addr}}
!---- [IMAGE] > {%set image={"bin":"cat3k_caa-universalk9.16.03.07.SPA.bin",
"ver":"16.3.7"}%}{# #}{{image|dictsort(false)|join(indent)}}
!---- [CREDS] > {%set creds={"admin":"admin-secret",
"eem_svc":"eem-secret"}%}{# #}{{creds|dictsort(false)|join(indent)}}
!---- [NTP_ADDR] > {%set ntp_addr={"pri":{"addr":"10.255.1.11","pref":"prefer"},
"sec":{"addr":"10.255.1.12","pref":""}}%}{# #}{{ntp_addr|dictsort(false)|join(indent)}}
!---- [ISE_ADDR] > {%set ise_addr={"01":"10.255.1.21",
"02":"10.255.1.22",
"03":"10.255.1.23"}%}{# #}{{ise_addr|dictsort(false)|join(indent)}}
!---- [SNMPV3] > {%set snmpv3={"grp":"SNMP_ASW",
"user":"snmp_asw",
"auth":"snmp-auth",
"priv":"smp-priv"}%}{# #}{{snmpv3|dictsort(false)|join(indent)}}
!---- [VLAN] > {%set vlan={"native":{"id":"999","name":"NATIVE"},
"global":{"id":"998","name":"GLOBAL"}}%}{# #}{{vlan|dictsort(false,"value")|join(indent)}}
!
!---------------------------------------------------------------- VARIABLES: DYNAMIC
!
!-- Variables (keys) with dynamic values based on variables paresed from the CSV keystore.
!
!-- Copy HOSTNAME from KEYSTORE_ID, get SW_COUNT and SERIALS from IDARRAY.
!---- HOSTNAME > {%set hostname=keystore_id%}{# #}{{hostname}}
!---- SW_COUNT > {%set sw_count=idarray|count%}{# #}{{sw_count}}
!---- SERIALS > {%set serials=idarray%}{# #}{{serials}}
!
!-- Create range lists for all access interfaces and all provisioning interfaces based on IDARRAY.
{%set gi_ints,te_ints,prov_ints=[],[],[]-%}
{%for sw in idarray-%}
{% set i=loop.index-%}
{% set gi_ints,te_ints,prov_ints=
gi_ints.append("Gi%s/0/1-36"|format(i)),
te_ints.append("Te%s/0/37-47"|format(i)),
prov_ints.append("Te%s/0/48"|format(i))-%}
{%endfor-%}
!---- GI_INTS > {%set gi_ints=gi_ints|join(",")%}{# #}{{gi_ints}}
!---- TE_INTS > {%set te_ints=te_ints|join(",")%}{# #}{{te_ints}}
!---- PROV_INTS > {%set prov_ints=prov_ints|join(",")%}{# #}{{prov_ints}}
!
!-- Split hostname to get TR (numeric only) and SW.
!---- TR > {%set tr=(hostname.split("-")[1])[2:]%}{# #}{{tr}}
!---- TRN > {%set trn=tr[1:]%}{# #}{{trn}}
!---- SW > {%set sw=(hostname.split("-")[2])%}{# #}{{sw}}
!
!-- Determine PO_NUM from TR (second digit) and (int of) SW; also used as last octet of MGMT IP.
!---- PO_NUM > {%set po_num="1%s%s"|format(tr[1:],sw|int)%}{# #}{{po_num}}
!
!-- Determine MGMT subnet; IP from subnet and PO_NUM; append a name for the default route.
{%set mgmt={"net":"10.254.%s"|format(trn)}-%}
{%set x=mgmt.update({"mask":"255.255.255.0"})-%}
{%set x=mgmt.update({"ip":"%s.%s"|format(mgmt.net,po_num)})-%}
{%set x=mgmt.update({"rt_name":"Default>MGMT:DIST-01"})-%}
!---- [MGMT] > {# #}{{mgmt|dictsort(false,"value")|join(indent)}}
!
!-- Determine TR_VLS from TR, append them to the (static) [VLAN] dictionary.
{%set tr_vls={"grt_thin":{"id":"1%s01"|format(trn),"name":"GRT:TR%s/THIN-CLIENTS"|format(tr)},
"grt_thick":{"id":"1%s02"|format(trn),"name":"GRT:TR%s/THICK-CLIENTS"|format(tr)},
"grt_voice":{"id":"1%s03"|format(trn),"name":"GRT:TR%s/VOICE"|format(tr)},
"grt_crit":{"id":"1%s99"|format(trn),"name":"GRT:TR%s/CRIT-AUTH"|format(tr)},
"mgmt_sw":{"id":"2%s01"|format(trn),"name":"MGMT:TR%s/SW-WLC"|format(tr)},
"mgmt_ap":{"id":"2%s02"|format(trn),"name":"MGMT:TR%s/CAPWAP"|format(tr)}}-%}
!---- [TR_VLS] > {%set x=vlan.update(tr_vls)-%}{# #}{{tr_vls|dictsort(false)|join(indent)}}
!
!-- Create VLAN_LIST from [VLAN].
{%set vlan_list=[]-%}
{%for k,v in vlan|dictsort(false,"value")-%}
{% set vlan_list=vlan_list.append(v.id) -%}
{%endfor-%}
!---- VLAN_LIST > {%set vlan_list=vlan_list|join(",")%}{# #}{{vlan_list}}
!
...
Expand for Full Template Example
{%-set tmpl={"file":"tmpl_test.j2",
"rev":"8"}-%}
{%-set indent="\n!"~" "*23-%}
!-- --------------------------------------------------------------------------- --!
!-- ***IMPORTANT (Example)*** --!
!-- Hostname (keystore_id in CSV) has strict formatting rules. --!
!-- --!
!-- * TR and switch/stack numbers must each be two digits (use leading '0'). --!
!-- * TRs are numbered 1-9. --!
!-- * Any TR can only accommodate up to 9 switches/stacks; i.e. 01-09. --!
!-- * Any stack is only intended to have 4 switches; i.e. idarray_1-4. --!
!-- --!
!-- Example for TR-4, switch/stack 2... --!
!-- --!
!-- Access Switch | TR Number | Switch/Stack Number --!
!-- ----------------------|------------------------|---------------------- --!
!-- ASW | TR04 | 02 --!
!-- --!
!-- Example hostname: ASW-TR04-02 --!
!-- --------------------------------------------------------------------------- --!
!
!-- Variables (keys) parsed from CSV keystore.
!
!---- KEYSTORE_ID > {{keystore_id|default("N/A")}}{# Used to associate the switch to a template (serial number).#}
!---- ASSOCIATION > {{association|default("N/A")}}{# Switch template associated with KEYSTORE_ID.#}
!---- IDARRAY_1 > {{idarray_1|default("N/A")}}{# Switch 1 serial number.#}
!---- IDARRAY_2 > {{idarray_2|default("N/A")}}{# Switch 2 serial number.#}
!---- IDARRAY_3 > {{idarray_3|default("N/A")}}{# Switch 3 serial number.#}
!---- IDARRAY_4 > {{idarray_4|default("N/A")}}{# Switch 4 serial number.#}
!---- IDARRAY > {{idarray|default("N/A")}}{# All switch serial numbers.#}
!
!---------------------------------------------------------------- VARIABLES: STATIC
!
!-- Variables (keys) statically defined within the template.
!-- Variables with multiple values are JSON formatted.
!{# VARIABLE > {%set VARIABLE="VALUE"%} <<< set | print >>> {{VARIABLE}} #}
!---- TFTP_ADDR > {%set tftp_addr="172.17.251.251"%}{# #}{{tftp_addr}}
!---- DOMAIN > {%set domain="exmaple.local"%}{# #}{{domain}}
!---- STP_PRIORITY > {%set stp_priority="28672"%}{# #}{{stp_priority}}
!---- ENABLE_SEC > {%set enable_sec="enable-secret"%}{# #}{{enable_sec}}
!---- TACACS_KEY > {%set tacacs_key="tacacs-secret"%}{# #}{{tacacs_key}}
!---- RADIUS_KEY > {%set radius_key="radius-secret"%}{# #}{{radius_key}}
!---- NTP_KEY > {%set ntp_key="ntp-secret"%}{# #}{{ntp_key}}
!---- SYSLOG_ADDR > {%set syslog_addr="10.255.1.1"%}{# #}{{syslog_addr}}
!---- [IMAGE] > {%set image={"bin":"cat3k_caa-universalk9.16.03.07.SPA.bin",
"ver":"16.3.7"}%}{# #}{{image|dictsort(false)|join(indent)}}
!---- [CREDS] > {%set creds={"admin":"admin-secret",
"eem_svc":"eem-secret"}%}{# #}{{creds|dictsort(false)|join(indent)}}
!---- [NTP_ADDR] > {%set ntp_addr={"pri":{"addr":"10.255.1.11","pref":"prefer"},
"sec":{"addr":"10.255.1.12","pref":""}}%}{# #}{{ntp_addr|dictsort(false)|join(indent)}}
!---- [ISE_ADDR] > {%set ise_addr={"01":"10.255.1.21",
"02":"10.255.1.22",
"03":"10.255.1.23"}%}{# #}{{ise_addr|dictsort(false)|join(indent)}}
!---- [SNMPV3] > {%set snmpv3={"grp":"SNMP_ASW",
"user":"snmp_asw",
"auth":"snmp-auth",
"priv":"smp-priv"}%}{# #}{{snmpv3|dictsort(false)|join(indent)}}
!---- [VLAN] > {%set vlan={"native":{"id":"999","name":"NATIVE"},
"global":{"id":"998","name":"GLOBAL"}}%}{# #}{{vlan|dictsort(false,"value")|join(indent)}}
!
!---------------------------------------------------------------- VARIABLES: DYNAMIC
!
!-- Variables (keys) with dynamic values based on variables paresed from the CSV keystore.
!
!-- Copy HOSTNAME from KEYSTORE_ID, get SW_COUNT and SERIALS from IDARRAY.
!---- HOSTNAME > {%set hostname=keystore_id%}{# #}{{hostname}}
!---- SW_COUNT > {%set sw_count=idarray|count%}{# #}{{sw_count}}
!---- SERIALS > {%set serials=idarray%}{# #}{{serials}}
!
!-- Create range lists for all access interfaces and all provisioning interfaces based on IDARRAY.
{%set gi_ints,te_ints,prov_ints=[],[],[]-%}
{%for sw in idarray-%}
{% set i=loop.index-%}
{% set gi_ints,te_ints,prov_ints=
gi_ints.append("Gi%s/0/1-36"|format(i)),
te_ints.append("Te%s/0/37-47"|format(i)),
prov_ints.append("Te%s/0/48"|format(i))-%}
{%endfor-%}
!---- GI_INTS > {%set gi_ints=gi_ints|join(",")%}{# #}{{gi_ints}}
!---- TE_INTS > {%set te_ints=te_ints|join(",")%}{# #}{{te_ints}}
!---- PROV_INTS > {%set prov_ints=prov_ints|join(",")%}{# #}{{prov_ints}}
!
!-- Split hostname to get TR (numeric only) and SW.
!---- TR > {%set tr=(hostname.split("-")[1])[2:]%}{# #}{{tr}}
!---- TRN > {%set trn=tr[1:]%}{# #}{{trn}}
!---- SW > {%set sw=(hostname.split("-")[2])%}{# #}{{sw}}
!
!-- Determine PO_NUM from TR (second digit) and (int of) SW; also used as last octet of MGMT IP.
!---- PO_NUM > {%set po_num="1%s%s"|format(tr[1:],sw|int)%}{# #}{{po_num}}
!
!-- Determine MGMT subnet; IP from subnet and PO_NUM; append a name for the default route.
{%set mgmt={"net":"10.254.%s"|format(trn)}-%}
{%set x=mgmt.update({"mask":"255.255.255.0"})-%}
{%set x=mgmt.update({"ip":"%s.%s"|format(mgmt.net,po_num)})-%}
{%set x=mgmt.update({"rt_name":"Default>MGMT:DIST-01"})-%}
!---- [MGMT] > {# #}{{mgmt|dictsort(false,"value")|join(indent)}}
!
!-- Determine TR_VLS from TR, append them to the (static) [VLAN] dictionary.
{%set tr_vls={"grt_thin":{"id":"1%s01"|format(trn),"name":"GRT:TR%s/THIN-CLIENTS"|format(tr)},
"grt_thick":{"id":"1%s02"|format(trn),"name":"GRT:TR%s/THICK-CLIENTS"|format(tr)},
"grt_voice":{"id":"1%s03"|format(trn),"name":"GRT:TR%s/VOICE"|format(tr)},
"grt_crit":{"id":"1%s99"|format(trn),"name":"GRT:TR%s/CRIT-AUTH"|format(tr)},
"mgmt_sw":{"id":"2%s01"|format(trn),"name":"MGMT:TR%s/SW-WLC"|format(tr)},
"mgmt_ap":{"id":"2%s02"|format(trn),"name":"MGMT:TR%s/CAPWAP"|format(tr)}}-%}
!---- [TR_VLS] > {%set x=vlan.update(tr_vls)-%}{# #}{{tr_vls|dictsort(false)|join(indent)}}
!
!-- Create VLAN_LIST from [VLAN].
{%set vlan_list=[]-%}
{%for k,v in vlan|dictsort(false,"value")-%}
{% set vlan_list=vlan_list.append(v.id) -%}
{%endfor-%}
!---- VLAN_LIST > {%set vlan_list=vlan_list|join(",")%}{# #}{{vlan_list}}
!
!---------------------------------------------------------------- CONFIG: BASE
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
!
hostname {{hostname}}
!
clock timezone PST -8 0
clock summer-time PDT recurring
!
{%for sw in idarray-%}
{% set i=loop.index-%}
switch {{i}} provision ws-c3850-12x48u
{%endfor-%}
!
no ip domain lookup
ip domain-name {{domain}}
!
logging buffered 409600 debugging
logging console debug
!
!ip ssh logging events
ip ssh version 2
!
spanning-tree mode rapid-pvst
spanning-tree vlan 1-4094 priority {{stp_priority}}
!
vtp mode transparent
!
file prompt quiet
!
ip dhcp snooping vlan 1-4094
no ip dhcp snooping information option
ip dhcp snooping
!
udld aggressive
!
macro name int-auth
switchport
switchport mode access
switchport nonegotiate
switchport voice vlan {{vlan.grt_voice.id}}
device-tracking attach-policy IPDT
authentication event server dead action reinitialize vlan {{vlan.grt_crit.id}}
authentication event server dead action authorize voice
authentication event server alive action reinitialize
authentication host-mode multi-auth
authentication order mab dot1x
authentication priority dot1x mab
authentication port-control auto
authentication violation restrict
mab
dot1x pae authenticator
dot1x timeout tx-period 7
dot1x max-reauth-req 3
spanning-tree portfast
ip dhcp snooping limit rate 25
no shutdown
no downshift
no macro description
@
!
macro name int-noauth
# Unauthenticated interface macro, variables not mandatory.
# > Assign appropriate access vlan using $VL
#
# Example config for a thin client in VL-1201;
# (config)# interface gi#/#/#
# (config-if)# macro apply int-noauth $VL 1201
#
switchport
switchport access vlan $VL
switchport mode access
switchport nonegotiate
device-tracking attach-policy IPDT
spanning-tree portfast
ip dhcp snooping limit rate 25
no shutdown
no downshift
no macro description
@
!
banner login @
UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED
You must have explicit, authorized permission to access or configure this device.
Unauthorized attempts and actions to access or use this system may result in civil and/or
criminal penalties.
All activities performed on this device are logged and monitored.
-----------------------------------------------------------------------------------------
@
!
alias exec intstat show int status
alias exec ipint show ip int br | e una
alias exec ver show ver | i Soft|file
alias exec vlbr show vlan br | i active
alias exec rundiff show arch config diff
alias exec auth show auth sess int gi
alias exec radstat sh aaa server | i RADIUS|Platform State
alias exec int-auth event man run int-auth
alias exec int-noauth event man run int-noauth
!
!---------------------------------------------------------------- CONFIG: AUTH
!
enable secret 0 {{enable_sec}}
!
{%for k,v in creds|dictsort(false)-%}
username {{k}} privilege 15 secret 0 {{v}}
{%endfor-%}
!
aaa new-model
!
!-- TACACS servers and group config.
!
{%-for k,v in ise_addr|dictsort(false)%}
tacacs server ISE{{k}}-T
address ipv4 {{v}}
key 0 {{tacacs_key}}
single-connection
{%endfor-%}
!
aaa group server tacacs+ ISE-T
{%-for k,v in ise_addr|dictsort(false)%}
server name ISE{{k}}-T
{%-endfor%}
ip tacacs source-interface Vlan{{vlan.mgmt_sw.id}}
!
!-- RADIUS servers and group config.
!
{%-for k,v in ise_addr|dictsort(false)%}
radius server ISE{{k}}-R
address ipv4 {{v}} auth-port 1812 acct-port 1813
automate-tester username test-user ignore-acct-port probe-on
key 0 {{radius_key}}
{%endfor-%}
!
aaa group server radius ISE-R
{%-for k,v in ise_addr|dictsort(false)%}
server name ISE{{k}}-R
{%-endfor%}
ip radius source-interface Vlan{{vlan.mgmt_sw.id}}
load-balance method least-outstanding batch-size 5
!
radius-server attribute 6 on-for-login-auth
radius-server attribute 8 include-in-access-req
radius-server attribute 25 access-request include
radius-server attribute 31 mac format ietf upper-case
radius-server attribute 31 send nas-port-detail mac-only
radius-server dead-criteria time 10 tries 3
radius-server deadtime 5
!
aaa server radius dynamic-author
{%-for k,v in ise_addr|dictsort(false)%}
client {{v}} server-key 0 {{radius_key}}
{%-endfor%}
!
!-- Default authentication method list to use TACACS, fallback to local (ssh).
aaa authentication login default group ISE-T local
!
!-- Authentication method list to use local creds only (console).
aaa authentication login CONSOLE local
!
!-- Required to authorize console to exec mode (console).
aaa authorization console
!
!-- Default authorization exec and commands 15 method lists to use local or TACACS (console, ssh).
!-- 'local' must be defined here first for console authorization to work.
aaa authorization exec default local group ISE-T if-authenticated
aaa authorization commands 15 default local group ISE-T if-authenticated
!
!-- Accounting commands to send all exec start-stop, and priv 15 commands to TACACS (console, ssh).
aaa accounting exec default start-stop group ISE-T
aaa accounting commands 15 default start-stop group ISE-T
!
!-- AAA commands for dot1x/mab.
aaa authentication dot1x default group ISE-R
aaa authorization network default group ISE-R
aaa accounting dot1x default start-stop group ISE-R
aaa accounting update newinfo periodic 2880
!
!---------------------------------------------------------------- CONFIG: DOT1X/ISE-MISC
!
dot1x system-auth-control
dot1x critical eapol
!
authentication mac-move permit
!
device-sensor filter-list dhcp list DHCP-ISE
option name host-name
option name requested-address
option name parameter-request-list
option name class-identifier
option name client-identifier
!
device-sensor filter-list cdp list CDP-ISE
tlv name device-name
tlv name address-type
tlv name capabilities-type
tlv name version-type
tlv name platform-type
!
device-sensor filter-spec dhcp include list DHCP-ISE
device-sensor filter-spec cdp include list CDP-ISE
device-sensor accounting
device-sensor notify all-changes
!
!---------------------------------------------------------------- CONFIG: VLANS
!
{%-for k,v in vlan|dictsort(false,"value")%}
vlan {{v.id}}
name {{v.name}}
{%endfor-%}
!
!---------------------------------------------------------------- CONFIG: INTERFACES
!
interface GigabitEthernet0/0
shutdown
!
!-- Configure misc interfaces for all stack members.
!
interface range {{prov_ints}}
description TMP//PROVISION
switchport
switchport mode access
switchport nonegotiate
switchport access vlan 1
spanning-tree portfast
ip dhcp snooping trust
no shutdown
!
{%-for sw in idarray%}
{%-set i=loop.index%}
interface range Gi{{i}}/1/1-2
shutdown
!
interface range Te{{i}}/1/3-4
channel-group 1 mode active
no shutdown
!
interface range Gi{{i}}/1/3-4,Te{{i}}/1/1-2,Te{{i}}/1/5-8,Fo{{i}}/1/1-2
description ***NULL//DoNotConfigure
shutdown
{%endfor-%}
!
interface Port-channel1
description DIST-01:Po{{po_num}}
switchport trunk native vlan 999
switchport trunk allowed vlan {{vlan_list}}
switchport mode trunk
switchport nonegotiate
ip dhcp snooping trust
no shutdown
!
!---------------------------------------------------------------- CONFIG: IP/SOURCE/NMS
!
interface Vlan1
desc TMP//PROVISION
ip address dhcp
no shutdown
!
interface Vlan{{vlan.mgmt_sw.id}}
description {{vlan.mgmt_sw.name}}
no ip redirects
no ip proxy-arp
ip address {{mgmt.ip}} {{mgmt.mask}}
no shutdown
!
ip tftp source-interface Vlan{{vlan.mgmt_sw.id}}
ip tftp blocksize 8192
!
ip route 0.0.0.0 0.0.0.0 {{mgmt.net}}.1 name {{mgmt.rt_name}}
!
logging source-interface Vlan{{vlan.mgmt_sw.id}}
logging host {{syslog_addr}}
!
ntp authentication-key 1 md5 {{ntp_key}}
ntp authenticate
ntp trusted-key 1
{%-for k,v in ntp_addr|dictsort(false)%}
ntp server {{v.addr}} key 1 {{v.pref}} source vlan{{vlan.mgmt_sw.id}}
{%-endfor%}
!
snmp-server group {{snmpv3.grp}} v3 priv
snmp-server user {{snmpv3.user}} {{snmpv3.grp}} v3 auth sha {{snmpv3.auth}} priv aes 256 {{snmpv3.priv}}
snmp-server location Provisioned with switch template: {{"%s (rev: %s)"|format(tmpl.file,tmpl.rev)}}
snmp-server contact Provisioned hostname ({{hostname}}) and stack members: {{serials|join("-")}}
!
line console 0
login authentication CONSOLE
logging synchronous
exec-timeout 15 0
line vty 0 15
logging synchronous
exec-timeout 30 0
transport input ssh
!
!---------------------------------------------------------------- CONFIG: EEM
!
event manager session cli username {{creds.keys().1}}
!
event manager applet int-auth
event none maxrun 60
action 00.00 puts "## Enter interface to configure with authentication; e.g. gi1/0/1, te1/0/37"
action 00.01 gets intf
action 00.02 cli command "enable"
action 00.03 cli command "show int $intf status"
action 00.04 regexp "Invalid" "$_cli_result"
action 00.05 if $_regexp_result eq "1"
action 00.06 puts "## Invalid interface ($intf), verify prefix; i.e. 'gi' or 'te'."
action 00.07 exit
action 00.08 end
action 00.10 regexp "connected\ +([0-9]+)" "$_cli_result" match currvl
action 00.11 if $_regexp_result eq "1"
action 00.12 puts "## Interface $intf has a device connected in VLAN $currvl, continue (y|n)..."
action 00.13 gets cont
action 00.14 if $cont ne "y"
action 00.15 exit
action 00.16 end
action 00.17 end
action 01.00 cli command "conf t"
action 01.01 cli command "default int $intf"
action 01.02 cli command "int $intf"
action 01.03 cli command "macro apply int-auth"
action 01.04 cli command "end"
action 01.05 cli command "write mem" pattern "confirm|#"
action 01.06 cli command ""
action 01.10 puts "## Interface $intf configured with authentication."
!
event manager applet int-noauth
event none maxrun 60
action 00.00 puts "## Enter interface to configure without authentication; e.g. gi1/0/1, te1/0/37"
action 00.01 gets intf
action 00.02 cli command "enable"
action 00.03 cli command "show int $intf status"
action 00.04 regexp "Invalid" "$_cli_result"
action 00.05 if $_regexp_result eq "1"
action 00.06 puts "## Invalid interface ($intf), verify prefix; i.e. 'gi' or 'te'."
action 00.07 exit
action 00.08 end
action 00.10 regexp "connected\ +([0-9]+)" "$_cli_result" match currvl
action 00.11 if $_regexp_result eq "1"
action 00.12 puts "## Interface $intf has a device connected in VLAN $currvl, continue (y|n)..."
action 00.13 gets cont
action 00.14 if $cont ne "y"
action 00.15 exit
action 00.16 end
action 00.17 end
action 00.20 puts "## Enter access VLAN ID; e.g. 800"
action 00.21 gets vl
action 00.22 cli command "show vlan id $vl"
action 00.23 regexp "not found" "$_cli_result"
action 00.24 if $_regexp_result eq "1"
action 00.25 puts "## VLAN $vl is not configured on this switch."
action 00.26 exit
action 00.27 end
action 01.00 cli command "conf t"
action 01.01 cli command "default int $intf"
action 01.02 cli command "int $intf"
action 01.03 cli command "macro apply int-noauth \$VL $vl"
action 01.04 cli command "end"
action 01.05 cli command "write mem" pattern "confirm|#"
action 01.06 cli command ""
action 01.10 puts "## Interface $intf configured without authentication in VL-$vl, please describe accordingly."
!
!---------------------------------------------------------------- CONFIG: EEM-TEMP
!
event manager environment q "
!
event manager applet post_ztp_1
!-- Renumber/prioritize switches in stack, write mem, and then download->upgrade/reload (if needed).
event syslog occurs 1 pattern "Configured from tftp://{{tftp_addr}}" maxrun 960
action 00.00 syslog msg " ## Configuration received via TFTP, run 'post_ztp_1' EEM applet in 120s."
action 00.01 wait 120
action 00.03 cli command "enable"
action 00.05 cli command "show mod | i ^.[1-9]"
action 00.06 set stack "$_cli_result"
action 00.07 syslog msg " ## Checking all switches' version and stack membership, adjusting where necessary.\n ## Current order;\n$stack"
action 00.08 set error_list ""
action 00.09 set change_list ""
action 00.10 set upgrade_list ""
{%for sw in idarray%}
{%- set i=loop.index%}
action 0{{i}}.00 set sw_num "{{i}}"
action 0{{i}}.01 set pri "16"
action 0{{i}}.02 decrement pri {{i}}
action 0{{i}}.03 regexp "{{sw}}" "$stack"
action 0{{i}}.04 if $_regexp_result ne "1"
action 0{{i}}.05 syslog msg "\n ## {{sw}} (Sw-{{i}} serial) not found in the stack, check 'show mod' output."
action 0{{i}}.06 append error_list "\n ## {{sw}} is allocated (idarray_{{i}}) but was not found in the stack."
action 0{{i}}.07 else
action 0{{i}}.08 set i "0"
action 0{{i}}.09 foreach line "$stack" "\n"
action 0{{i}}.10 increment i
action 0{{i}}.11 if $i le "{{sw_count}}"
action 0{{i}}.12 string trim "$line"
action 0{{i}}.13 set line "$_string_result"
action 0{{i}}.14 regexp "{{sw}}" "$line"
action 0{{i}}.15 if $_regexp_result eq "1"
action 0{{i}}.16 regexp "([0-9\.A-Z]+$)" "$line" curr_ver
action 0{{i}}.17 if $curr_ver ne "{{image.ver}}"
action 0{{i}}.18 append upgrade_list "{{i}}"
action 0{{i}}.19 end
action 0{{i}}.20 cli command "switch $i priority $pri" pattern "continue|#"
action 0{{i}}.21 cli command "y"
action 0{{i}}.22 if $i eq $sw_num
action 0{{i}}.23 append change_list "\n ## {{sw}} (Priority: $pri // Numbered: $sw_num // Version: $curr_ver)"
action 0{{i}}.24 else
action 0{{i}}.25 cli command "switch $i renumber $sw_num" pattern "continue|#"
action 0{{i}}.26 cli command "y"
action 0{{i}}.27 append change_list "\n ## {{sw}} (Priority: $pri // Renumbered: $i > $sw_num* // Version: $curr_ver)"
action 0{{i}}.28 end
action 0{{i}}.29 break
action 0{{i}}.30 end
action 0{{i}}.31 end
action 0{{i}}.32 end
action 0{{i}}.33 end
{%endfor%}
action 10.00 wait 5
action 10.01 if $error_list ne ""
action 10.02 syslog msg "\n ## The following errors occurred; $error_list"
action 10.03 end
action 10.04 syslog msg "\n ## Switches below have been assigned a priority and renumbered* as needed; $change_list"
action 13.00 cli command "conf t"
action 13.01 cli command "no event man app post_ztp_1"
action 14.00 if $upgrade_list eq ""
action 14.01 syslog msg " ## All switches are running version {{image.ver}}, skipping download->upgrade/reload; finalizing config in 20s."
action 14.02 cli command "no event man env q"
action 14.03 cli command "event man env ztp_upgraded no"
action 14.04 cli command " event man app post_ztp_2"
action 14.05 cli command " event timer countdown time 20 maxrun 480"
action 14.06 cli command " no action 00.00"
action 14.07 cli command " no action 00.01"
action 14.08 cli command " end"
action 14.09 cli command "write mem" pattern "confirm|#"
action 14.10 cli command ""
action 14.11 else
action 14.12 syslog msg " ## One or more switches require an upgrade to version {{image.ver}} ($upgrade_list); proceeding with download->upgrade/reload."
action 14.13 cli command "event man env ztp_upgraded yes"
action 14.14 cli command "event man app post_ztp_2"
action 14.15 cli command " event syslog occurs 1 pattern $q%IOSXE_REDUNDANCY-6-PEER$q maxrun 630"
action 14.16 cli command " no event man env q"
action 14.17 cli command "end"
action 14.18 cli command "write mem" pattern "confirm|#"
action 14.19 cli command ""
action 14.20 syslog msg " ## (Standby) Downloading image..."
action 14.21 cli command "copy tftp://{{tftp_addr}}/{{image.bin}} flash:"
action 14.22 syslog msg " ## (Standby) Image downloaded, upgrading..."
action 14.23 cli command "software install file flash:{{image.bin}} new force" pattern "proceed|#"
action 14.24 syslog msg " ## Upgrade complete, rebooting."
action 14.25 cli command "y"
action 14.26 end
!
event manager applet post_ztp_2
!-- Apply final configs, push running config via TFTP, clean up VL-1 and Te#/0/48 configs, write mem, and then perform package clean.
event none
action 00.00 syslog msg " ## Switch reloaded on new image, running 'post_ztp_2' EEM applet in 150s."
action 00.01 wait 150
action 00.02 syslog msg " ## (Standby) Applying global configs ignored by smart-install and generating crypto key..."
action 00.03 cli command "enable"
action 00.04 set upgr "$ztp_upgraded"
action 01.00 cli command "conf t"
action 01.01 cli command "no event man env ztp_upgraded"
action 01.02 cli command "no event man app post_ztp_2"
action 01.04 cli command "no vstack"
action 01.05 cli command "no ip http ser"
action 01.06 cli command "no ip http secure-s"
action 01.07 cli command "no ip http authen"
action 01.08 cli command "no coap http enable"
action 01.09 cli command "device-tracking policy IPDT"
action 01.10 cli command " no protocol udp"
action 01.11 cli command " tracking enable"
action 01.12 cli command "cry key gen rsa mod 2048"
action 02.00 syslog msg " ## (Standby) Applying `int-auth` macro config to ports 1-48 on all stack members..."
action 02.01 cli command "int range {{gi_ints}}"
action 02.02 cli command " macro apply int-auth"
action 02.03 cli command " no macro desc"
action 02.04 cli command "int range {{te_ints}}"
action 02.05 cli command " macro apply int-auth"
action 02.06 cli command " no macro desc"
action 03.00 syslog msg " ## Pushing config to the following location: tftp://{{tftp_addr}}/provisioned/CAS/{{cfg_file}}"
action 03.01 cli command "do copy run tftp://{{tftp_addr}}/provisioned/CAS/{{cfg_file}}"
action 04.00 syslog msg " ## Disabling VL-1 SVI, updating Te#/0/48 configs, and writing startup config."
action 04.01 cli command "int vl 1"
action 04.02 cli command " no desc"
action 04.03 cli command " no ip addr"
action 04.04 cli command " shut"
action 04.05 cli command "default int range {{prov_ints}}"
action 04.06 cli command "int range {{prov_ints}}"
action 04.07 cli command " macro apply int-auth"
action 04.08 cli command " no macro desc"
action 04.09 cli command "end"
action 04.10 cli command "write mem" pattern "confirm|#"
action 04.11 cli command ""
action 05.00 if $upgr eq "yes"
action 05.01 syslog msg " ## (Standby) ZTP upgrade detected, performing software package clean..."
action 05.02 cli command "req plat soft pack clean sw all" pattern "proceed|#"
action 05.03 cli command "y"
action 05.04 syslog msg " ## Unused .bin or .pkg files from previous version(s) have been deleted."
action 05.05 else
action 05.06 syslog msg " ## ZTP upgrade not detected, skipping software package clean."
action 05.07 end
action 05.08 syslog msg " ## Start-up config written, ({{hostname}}) is ready for deployment, OK to power off."
!
end
Merged Config
##############################
!-- --------------------------------------------------------------------------- --!
!-- ***IMPORTANT (Example)*** --!
!-- Hostname (keystore_id in CSV) has strict formatting rules. --!
!-- --!
!-- * TR and switch/stack numbers must each be two digits (use leading '0'). --!
!-- * TRs are numbered 1-9. --!
!-- * Any TR can only accommodate up to 9 switches/stacks; i.e. 01-09. --!
!-- * Any stack is only intended to have 4 switches; i.e. idarray_1-4. --!
!-- --!
!-- Example for TR-4, switch/stack 2... --!
!-- --!
!-- Access Switch | TR Number | Switch/Stack Number --!
!-- ----------------------|------------------------|---------------------- --!
!-- ASW | TR04 | 02 --!
!-- --!
!-- Example hostname: ASW-TR04-02 --!
!-- --------------------------------------------------------------------------- --!
!
!-- Variables (keys) parsed from CSV keystore.
!
!---- KEYSTORE_ID > ASW-TR04-02
!---- ASSOCIATION > ASW
!---- IDARRAY_1 > FOC11111111
!---- IDARRAY_2 > FOC22222222
!---- IDARRAY_3 > FOC33333333
!---- IDARRAY_4 > FOC44444444
!---- IDARRAY > ['FOC11111111', 'FOC22222222', 'FOC33333333', 'FOC44444444']
!
!---------------------------------------------------------------- VARIABLES: STATIC
!
!-- Variables (keys) statically defined within the template.
!-- Variables with multiple values are JSON formatted.
!
!---- TFTP_ADDR > 172.17.251.251
!---- DOMAIN > exmaple.local
!---- STP_PRIORITY > 28672
!---- ENABLE_SEC > enable-secret
!---- TACACS_KEY > tacacs-secret
!---- RADIUS_KEY > radius-secret
!---- NTP_KEY > ntp-secret
!---- SYSLOG_ADDR > 10.255.1.1
!---- [IMAGE] > ('bin', 'cat3k_caa-universalk9.16.03.07.SPA.bin')
! ('ver', '16.3.7')
!---- [CREDS] > ('admin', 'admin-secret')
! ('eem_svc', 'eem-secret')
!---- [NTP_ADDR] > ('pri', {'pref': 'prefer', 'addr': '10.255.1.11'})
! ('sec', {'pref': '', 'addr': '10.255.1.12'})
!---- [ISE_ADDR] > ('01', '10.255.1.21')
! ('02', '10.255.1.22')
! ('03', '10.255.1.23')
!---- [SNMPV3] > ('auth', 'snmp-auth')
! ('grp', 'SNMP_ASW')
! ('priv', 'smp-priv')
! ('user', 'snmp_asw')
!---- [VLAN] > ('global', {'id': '998', 'name': 'GLOBAL'})
! ('native', {'id': '999', 'name': 'NATIVE'})
!
!---------------------------------------------------------------- VARIABLES: DYNAMIC
!
!-- Variables (keys) with dynamic values based on variables paresed from the CSV keystore.
!
!-- Copy HOSTNAME from KEYSTORE_ID, get SW_COUNT and SERIALS from IDARRAY.
!---- HOSTNAME > ASW-TR04-02
!---- SW_COUNT > 4
!---- SERIALS > ['FOC11111111', 'FOC22222222', 'FOC33333333', 'FOC44444444']
!
!-- Join HOSTNAME and SERIALS to make CFG_FILE; used by EEM applet for TFTP config push
!---- CFG_FILE > ASW-TR04-02_FOC11111111-FOC22222222-FOC33333333-FOC44444444.cfg
!
!-- Create range lists for all access interfaces and all provisioning interfaces based on IDARRAY.
!---- GI_INTS > Gi1/0/1-36,Gi2/0/1-36,Gi3/0/1-36,Gi4/0/1-36
!---- TE_INTS > Te1/0/37-47,Te2/0/37-47,Te3/0/37-47,Te4/0/37-47
!---- PROV_INTS > Te1/0/48,Te2/0/48,Te3/0/48,Te4/0/48
!
!-- Split hostname to get TR (numeric only) and SW.
!---- TR > 04
!---- TRN > 4
!---- SW > 02
!
!-- Determine PO_NUM from TR (second digit) and (int of) SW; also used as last octet of MGMT IP.
!---- PO_NUM > 142
!
!-- Determine MGMT subnet; IP from subnet and PO_NUM; append a name for the default route.
!---- [MGMT] > ('net', u'10.254.4')
! ('ip', u'10.254.4.142')
! ('mask', '255.255.255.0')
! ('rt_name', 'Default>MGMT:DIST-01')
!
!-- Determine TR_VLS from TR, append them to the (static) [VLAN] dictionary.
!---- [TR_VLS] > ('grt_crit', {'id': u'1499', 'name': u'GRT:TR04/CRIT-AUTH'})
! ('grt_thick', {'id': u'1402', 'name': u'GRT:TR04/THICK-CLIENTS'})
! ('grt_thin', {'id': u'1401', 'name': u'GRT:TR04/THIN-CLIENTS'})
! ('grt_voice', {'id': u'1403', 'name': u'GRT:TR04/VOICE'})
! ('mgmt_ap', {'id': u'2402', 'name': u'MGMT:TR04/CAPWAP'})
! ('mgmt_sw', {'id': u'2401', 'name': u'MGMT:TR04/SW-WLC'})
!
!-- Create VLAN_LIST from [VLAN].
!---- VLAN_LIST > 1401,1402,1403,1499,2401,2402,998,999
!
...
Expand for Full Merged Config Example
Expand for Merge Request & Resulting Logs
# ztp request merge-test ASW-TR04-02
2019-03-07 23:49:00: cfact.get_keystore_id: Checking Keystores and IDArrays for (ASW-TR04-02)
2019-03-07 23:49:00: cfact.get_keystore_id: ID (ASW-TR04-02) resolved directly to an external-keystore
2019-03-07 23:49:00: cfact.get_template: Looking up association for identity (ASW-TR04-02)
2019-03-07 23:49:00: cfact.get_template: Found associated template (ASW) in an external keystore
2019-03-07 23:49:00: cfact.get_template: Template (ASW) exists as an external-template. Returning
2019-03-07 23:49:00: cfact.pull_keystore_values: Inserting IDArray keys
2019-03-07 23:49:00: cfact.merge_final_config: Merging with values:
{
"idarray_1": "FOC11111111",
"idarray_4": "FOC44444444",
"idarray_2": "FOC22222222",
"idarray_3": "FOC33333333",
"keystore_id": "ASW-TR04-02",
"idarray": [
"FOC11111111",
"FOC22222222",
"FOC33333333",
"FOC44444444"
],
"association": "ASW"
}
##############################
!-- --------------------------------------------------------------------------- --!
!-- ***IMPORTANT (Example)*** --!
!-- Hostname (keystore_id in CSV) has strict formatting rules. --!
!-- --!
!-- * TR and switch/stack numbers must each be two digits (use leading '0'). --!
!-- * TRs are numbered 1-9. --!
!-- * Any TR can only accommodate up to 9 switches/stacks; i.e. 01-09. --!
!-- * Any stack is only intended to have 4 switches; i.e. idarray_1-4. --!
!-- --!
!-- Example for TR-4, switch/stack 2... --!
!-- --!
!-- Access Switch | TR Number | Switch/Stack Number --!
!-- ----------------------|------------------------|---------------------- --!
!-- ASW | TR04 | 02 --!
!-- --!
!-- Example hostname: ASW-TR04-02 --!
!-- --------------------------------------------------------------------------- --!
!
!-- Variables (keys) parsed from CSV keystore.
!
!---- KEYSTORE_ID > ASW-TR04-02
!---- ASSOCIATION > ASW
!---- IDARRAY_1 > FOC11111111
!---- IDARRAY_2 > FOC22222222
!---- IDARRAY_3 > FOC33333333
!---- IDARRAY_4 > FOC44444444
!---- IDARRAY > ['FOC11111111', 'FOC22222222', 'FOC33333333', 'FOC44444444']
!
!---------------------------------------------------------------- VARIABLES: STATIC
!
!-- Variables (keys) statically defined within the template.
!-- Variables with multiple values are JSON formatted.
!
!---- TFTP_ADDR > 172.17.251.251
!---- DOMAIN > exmaple.local
!---- STP_PRIORITY > 28672
!---- ENABLE_SEC > enable-secret
!---- TACACS_KEY > tacacs-secret
!---- RADIUS_KEY > radius-secret
!---- NTP_KEY > ntp-secret
!---- SYSLOG_ADDR > 10.255.1.1
!---- [IMAGE] > ('bin', 'cat3k_caa-universalk9.16.03.07.SPA.bin')
! ('ver', '16.3.7')
!---- [CREDS] > ('admin', 'admin-secret')
! ('eem_svc', 'eem-secret')
!---- [NTP_ADDR] > ('pri', {'pref': 'prefer', 'addr': '10.255.1.11'})
! ('sec', {'pref': '', 'addr': '10.255.1.12'})
!---- [ISE_ADDR] > ('01', '10.255.1.21')
! ('02', '10.255.1.22')
! ('03', '10.255.1.23')
!---- [SNMPV3] > ('auth', 'snmp-auth')
! ('grp', 'SNMP_ASW')
! ('priv', 'smp-priv')
! ('user', 'snmp_asw')
!---- [VLAN] > ('global', {'id': '998', 'name': 'GLOBAL'})
! ('native', {'id': '999', 'name': 'NATIVE'})
!
!---------------------------------------------------------------- VARIABLES: DYNAMIC
!
!-- Variables (keys) with dynamic values based on variables paresed from the CSV keystore.
!
!-- Copy HOSTNAME from KEYSTORE_ID, get SW_COUNT and SERIALS from IDARRAY.
!---- HOSTNAME > ASW-TR04-02
!---- SW_COUNT > 4
!---- SERIALS > ['FOC11111111', 'FOC22222222', 'FOC33333333', 'FOC44444444']
!
!-- Join HOSTNAME and SERIALS to make CFG_FILE; used by EEM applet for TFTP config push
!---- CFG_FILE > ASW-TR04-02_FOC11111111-FOC22222222-FOC33333333-FOC44444444.cfg
!
!-- Create range lists for all access interfaces and all provisioning interfaces based on IDARRAY.
!---- GI_INTS > Gi1/0/1-36,Gi2/0/1-36,Gi3/0/1-36,Gi4/0/1-36
!---- TE_INTS > Te1/0/37-47,Te2/0/37-47,Te3/0/37-47,Te4/0/37-47
!---- PROV_INTS > Te1/0/48,Te2/0/48,Te3/0/48,Te4/0/48
!
!-- Split hostname to get TR (numeric only) and SW.
!---- TR > 04
!---- TRN > 4
!---- SW > 02
!
!-- Determine PO_NUM from TR (second digit) and (int of) SW; also used as last octet of MGMT IP.
!---- PO_NUM > 142
!
!-- Determine MGMT subnet; IP from subnet and PO_NUM; append a name for the default route.
!---- [MGMT] > ('net', u'10.254.4')
! ('ip', u'10.254.4.142')
! ('mask', '255.255.255.0')
! ('rt_name', 'Default>MGMT:DIST-01')
!
!-- Determine TR_VLS from TR, append them to the (static) [VLAN] dictionary.
!---- [TR_VLS] > ('grt_crit', {'id': u'1499', 'name': u'GRT:TR04/CRIT-AUTH'})
! ('grt_thick', {'id': u'1402', 'name': u'GRT:TR04/THICK-CLIENTS'})
! ('grt_thin', {'id': u'1401', 'name': u'GRT:TR04/THIN-CLIENTS'})
! ('grt_voice', {'id': u'1403', 'name': u'GRT:TR04/VOICE'})
! ('mgmt_ap', {'id': u'2402', 'name': u'MGMT:TR04/CAPWAP'})
! ('mgmt_sw', {'id': u'2401', 'name': u'MGMT:TR04/SW-WLC'})
!
!-- Create VLAN_LIST from [VLAN].
!---- VLAN_LIST > 1401,1402,1403,1499,2401,2402,998,999
!
!---------------------------------------------------------------- CONFIG: BASE
!
service timestamps debug datetime msec localtime show-timezone year
service timestamps log datetime msec localtime show-timezone year
service password-encryption
!
hostname ASW-TR04-02
!
clock timezone PST -8 0
clock summer-time PDT recurring
!
switch 1 provision ws-c3850-12x48u
switch 2 provision ws-c3850-12x48u
switch 3 provision ws-c3850-12x48u
switch 4 provision ws-c3850-12x48u
!
no ip domain lookup
ip domain-name exmaple.local
!
logging buffered 409600 debugging
logging console debug
!
!ip ssh logging events
ip ssh version 2
!
spanning-tree mode rapid-pvst
spanning-tree vlan 1-4094 priority 28672
!
vtp mode transparent
!
file prompt quiet
!
ip dhcp snooping vlan 1-4094
no ip dhcp snooping information option
ip dhcp snooping
!
udld aggressive
!
macro name int-auth
switchport
switchport mode access
switchport nonegotiate
switchport voice vlan 1403
device-tracking attach-policy IPDT
authentication event server dead action reinitialize vlan 1499
authentication event server dead action authorize voice
authentication event server alive action reinitialize
authentication host-mode multi-auth
authentication order mab dot1x
authentication priority dot1x mab
authentication port-control auto
authentication violation restrict
mab
dot1x pae authenticator
dot1x timeout tx-period 7
dot1x max-reauth-req 3
spanning-tree portfast
ip dhcp snooping limit rate 25
no shutdown
no downshift
no macro description
@
!
macro name int-noauth
# Unauthenticated interface macro, variables not mandatory.
# > Assign appropriate access vlan using $VL
#
# Example config for a thin client in VL-1201;
# (config)# interface gi#/#/#
# (config-if)# macro apply int-noauth $VL 1201
#
switchport
switchport access vlan $VL
switchport mode access
switchport nonegotiate
device-tracking attach-policy IPDT
spanning-tree portfast
ip dhcp snooping limit rate 25
no shutdown
no downshift
no macro description
@
!
banner login @
UNAUTHORIZED ACCESS TO THIS DEVICE IS PROHIBITED
You must have explicit, authorized permission to access or configure this device.
Unauthorized attempts and actions to access or use this system may result in civil and/or
criminal penalties.
All activities performed on this device are logged and monitored.
-----------------------------------------------------------------------------------------
@
!
alias exec intstat show int status
alias exec ipint show ip int br | e una
alias exec ver show ver | i Soft|file
alias exec vlbr show vlan br | i active
alias exec rundiff show arch config diff
alias exec auth show auth sess int gi
alias exec radstat sh aaa server | i RADIUS|Platform State
alias exec int-auth event man run int-auth
alias exec int-noauth event man run int-noauth
!
!---------------------------------------------------------------- CONFIG: AUTH
!
enable secret 0 enable-secret
!
username admin privilege 15 secret 0 admin-secret
username eem_svc privilege 15 secret 0 eem-secret
!
aaa new-model
!
!-- TACACS servers and group config.
!
tacacs server ISE01-T
address ipv4 10.255.1.21
key 0 tacacs-secret
single-connection
tacacs server ISE02-T
address ipv4 10.255.1.22
key 0 tacacs-secret
single-connection
tacacs server ISE03-T
address ipv4 10.255.1.23
key 0 tacacs-secret
single-connection
!
aaa group server tacacs+ ISE-T
server name ISE01-T
server name ISE02-T
server name ISE03-T
ip tacacs source-interface Vlan2401
!
!-- RADIUS servers and group config.
!
radius server ISE01-R
address ipv4 10.255.1.21 auth-port 1812 acct-port 1813
automate-tester username test-user ignore-acct-port probe-on
key 0 radius-secret
radius server ISE02-R
address ipv4 10.255.1.22 auth-port 1812 acct-port 1813
automate-tester username test-user ignore-acct-port probe-on
key 0 radius-secret
radius server ISE03-R
address ipv4 10.255.1.23 auth-port 1812 acct-port 1813
automate-tester username test-user ignore-acct-port probe-on
key 0 radius-secret
!
aaa group server radius ISE-R
server name ISE01-R
server name ISE02-R
server name ISE03-R
ip radius source-interface Vlan2401
load-balance method least-outstanding batch-size 5
!
radius-server attribute 6 on-for-login-auth
radius-server attribute 8 include-in-access-req
radius-server attribute 25 access-request include
radius-server attribute 31 mac format ietf upper-case
radius-server attribute 31 send nas-port-detail mac-only
radius-server dead-criteria time 10 tries 3
radius-server deadtime 5
!
aaa server radius dynamic-author
client 10.255.1.21 server-key 0 radius-secret
client 10.255.1.22 server-key 0 radius-secret
client 10.255.1.23 server-key 0 radius-secret
!
!-- Default authentication method list to use TACACS, fallback to local (ssh).
aaa authentication login default group ISE-T local
!
!-- Authentication method list to use local creds only (console).
aaa authentication login CONSOLE local
!
!-- Required to authorize console to exec mode (console).
aaa authorization console
!
!-- Default authorization exec and commands 15 method lists to use local or TACACS (console, ssh).
!-- 'local' must be defined here first for console authorization to work.
aaa authorization exec default local group ISE-T if-authenticated
aaa authorization commands 15 default local group ISE-T if-authenticated
!
!-- Accounting commands to send all exec start-stop, and priv 15 commands to TACACS (console, ssh).
aaa accounting exec default start-stop group ISE-T
aaa accounting commands 15 default start-stop group ISE-T
!
!-- AAA commands for dot1x/mab.
aaa authentication dot1x default group ISE-R
aaa authorization network default group ISE-R
aaa accounting dot1x default start-stop group ISE-R
aaa accounting update newinfo periodic 2880
!
!---------------------------------------------------------------- CONFIG: DOT1X/ISE-MISC
!
dot1x system-auth-control
dot1x critical eapol
!
authentication mac-move permit
!
device-sensor filter-list dhcp list DHCP-ISE
option name host-name
option name requested-address
option name parameter-request-list
option name class-identifier
option name client-identifier
!
device-sensor filter-list cdp list CDP-ISE
tlv name device-name
tlv name address-type
tlv name capabilities-type
tlv name version-type
tlv name platform-type
!
device-sensor filter-spec dhcp include list DHCP-ISE
device-sensor filter-spec cdp include list CDP-ISE
device-sensor accounting
device-sensor notify all-changes
!
!---------------------------------------------------------------- CONFIG: VLANS
!
vlan 1401
name GRT:TR04/THIN-CLIENTS
vlan 1402
name GRT:TR04/THICK-CLIENTS
vlan 1403
name GRT:TR04/VOICE
vlan 1499
name GRT:TR04/CRIT-AUTH
vlan 2401
name MGMT:TR04/SW-WLC
vlan 2402
name MGMT:TR04/CAPWAP
vlan 998
name GLOBAL
vlan 999
name NATIVE
!
!---------------------------------------------------------------- CONFIG: INTERFACES
!
interface GigabitEthernet0/0
shutdown
!
!-- Configure misc interfaces for all stack members.
!
interface range Te1/0/48,Te2/0/48,Te3/0/48,Te4/0/48
description TMP//PROVISION
switchport
switchport mode access
switchport nonegotiate
switchport access vlan 1
spanning-tree portfast
ip dhcp snooping trust
no shutdown
!
interface range Gi1/1/1-2
shutdown
!
interface range Te1/1/3-4
channel-group 1 mode active
no shutdown
!
interface range Gi1/1/3-4,Te1/1/1-2,Te1/1/5-8,Fo1/1/1-2
description ***NULL//DoNotConfigure
shutdown
interface range Gi2/1/1-2
shutdown
!
interface range Te2/1/3-4
channel-group 1 mode active
no shutdown
!
interface range Gi2/1/3-4,Te2/1/1-2,Te2/1/5-8,Fo2/1/1-2
description ***NULL//DoNotConfigure
shutdown
interface range Gi3/1/1-2
shutdown
!
interface range Te3/1/3-4
channel-group 1 mode active
no shutdown
!
interface range Gi3/1/3-4,Te3/1/1-2,Te3/1/5-8,Fo3/1/1-2
description ***NULL//DoNotConfigure
shutdown
interface range Gi4/1/1-2
shutdown
!
interface range Te4/1/3-4
channel-group 1 mode active
no shutdown
!
interface range Gi4/1/3-4,Te4/1/1-2,Te4/1/5-8,Fo4/1/1-2
description ***NULL//DoNotConfigure
shutdown
!
interface Port-channel1
description DIST-01:Po142
switchport trunk native vlan 999
switchport trunk allowed vlan 1401,1402,1403,1499,2401,2402,998,999
switchport mode trunk
switchport nonegotiate
ip dhcp snooping trust
no shutdown
!
!---------------------------------------------------------------- CONFIG: IP/SOURCE/NMS
!
interface Vlan1
desc TMP//PROVISION
ip address dhcp
no shutdown
!
interface Vlan2401
description MGMT:TR04/SW-WLC
no ip redirects
no ip proxy-arp
ip address 10.254.4.142 255.255.255.0
no shutdown
!
ip tftp source-interface Vlan2401
ip tftp blocksize 8192
!
ip route 0.0.0.0 0.0.0.0 10.254.4.1 name Default>MGMT:DIST-01
!
logging source-interface Vlan2401
logging host 10.255.1.1
!
ntp authentication-key 1 md5 ntp-secret
ntp authenticate
ntp trusted-key 1
ntp server 10.255.1.11 key 1 prefer source vlan2401
ntp server 10.255.1.12 key 1 source vlan2401
!
snmp-server group SNMP_ASW v3 priv
snmp-server user snmp_asw SNMP_ASW v3 auth sha snmp-auth priv aes 256 smp-priv
snmp-server location Provisioned with switch template: tmpl_test.j2 (rev: 8)
snmp-server contact Provisioned hostname (ASW-TR04-02) and stack members: FOC11111111-FOC22222222-FOC33333333-FOC44444444
!
line console 0
login authentication CONSOLE
logging synchronous
exec-timeout 15 0
line vty 0 15
logging synchronous
exec-timeout 30 0
transport input ssh
!
!---------------------------------------------------------------- CONFIG: EEM
!
event manager session cli username eem_svc
!
event manager applet int-auth
event none maxrun 60
action 00.00 puts "## Enter interface to configure with authentication; e.g. gi1/0/1, te1/0/37"
action 00.01 gets intf
action 00.02 cli command "enable"
action 00.03 cli command "show int $intf status"
action 00.04 regexp "Invalid" "$_cli_result"
action 00.05 if $_regexp_result eq "1"
action 00.06 puts "## Invalid interface ($intf), verify prefix; i.e. 'gi' or 'te'."
action 00.07 exit
action 00.08 end
action 00.10 regexp "connected\ +([0-9]+)" "$_cli_result" match currvl
action 00.11 if $_regexp_result eq "1"
action 00.12 puts "## Interface $intf has a device connected in VLAN $currvl, continue (y|n)..."
action 00.13 gets cont
action 00.14 if $cont ne "y"
action 00.15 exit
action 00.16 end
action 00.17 end
action 01.00 cli command "conf t"
action 01.01 cli command "default int $intf"
action 01.02 cli command "int $intf"
action 01.03 cli command "macro apply int-auth"
action 01.04 cli command "end"
action 01.05 cli command "write mem" pattern "confirm|#"
action 01.06 cli command ""
action 01.10 puts "## Interface $intf configured with authentication."
!
event manager applet int-noauth
event none maxrun 60
action 00.00 puts "## Enter interface to configure without authentication; e.g. gi1/0/1, te1/0/37"
action 00.01 gets intf
action 00.02 cli command "enable"
action 00.03 cli command "show int $intf status"
action 00.04 regexp "Invalid" "$_cli_result"
action 00.05 if $_regexp_result eq "1"
action 00.06 puts "## Invalid interface ($intf), verify prefix; i.e. 'gi' or 'te'."
action 00.07 exit
action 00.08 end
action 00.10 regexp "connected\ +([0-9]+)" "$_cli_result" match currvl
action 00.11 if $_regexp_result eq "1"
action 00.12 puts "## Interface $intf has a device connected in VLAN $currvl, continue (y|n)..."
action 00.13 gets cont
action 00.14 if $cont ne "y"
action 00.15 exit
action 00.16 end
action 00.17 end
action 00.20 puts "## Enter access VLAN ID; e.g. 800"
action 00.21 gets vl
action 00.22 cli command "show vlan id $vl"
action 00.23 regexp "not found" "$_cli_result"
action 00.24 if $_regexp_result eq "1"
action 00.25 puts "## VLAN $vl is not configured on this switch."
action 00.26 exit
action 00.27 end
action 01.00 cli command "conf t"
action 01.01 cli command "default int $intf"
action 01.02 cli command "int $intf"
action 01.03 cli command "macro apply int-noauth \$VL $vl"
action 01.04 cli command "end"
action 01.05 cli command "write mem" pattern "confirm|#"
action 01.06 cli command ""
action 01.10 puts "## Interface $intf configured without authentication in VL-$vl, please describe accordingly."
!
!---------------------------------------------------------------- CONFIG: EEM-TEMP
!
event manager environment q "
!
event manager applet post_ztp_1
!-- Renumber/prioritize switches in stack, write mem, and then download->upgrade/reload (if needed).
event syslog occurs 1 pattern "Configured from tftp://172.17.251.251" maxrun 960
action 00.00 syslog msg " ## Configuration received via TFTP, run 'post_ztp_1' EEM applet in 120s."
action 00.01 wait 120
action 00.03 cli command "enable"
action 00.05 cli command "show mod | i ^.[1-9]"
action 00.06 set stack "$_cli_result"
action 00.07 syslog msg " ## Checking all switches' version and stack membership, adjusting where necessary.\n ## Current order;\n$stack"
action 00.08 set error_list ""
action 00.09 set change_list ""
action 00.10 set upgrade_list ""
action 01.00 set sw_num "1"
action 01.01 set pri "16"
action 01.02 decrement pri 1
action 01.03 regexp "FOC11111111" "$stack"
action 01.04 if $_regexp_result ne "1"
action 01.05 syslog msg "\n ## FOC11111111 (Sw-1 serial) not found in the stack, check 'show mod' output."
action 01.06 append error_list "\n ## FOC11111111 is allocated (idarray_1) but was not found in the stack."
action 01.07 else
action 01.08 set i "0"
action 01.09 foreach line "$stack" "\n"
action 01.10 increment i
action 01.11 if $i le "4"
action 01.12 string trim "$line"
action 01.13 set line "$_string_result"
action 01.14 regexp "FOC11111111" "$line"
action 01.15 if $_regexp_result eq "1"
action 01.16 regexp "([0-9\.A-Z]+$)" "$line" curr_ver
action 01.17 if $curr_ver ne "16.3.7"
action 01.18 append upgrade_list "1"
action 01.19 end
action 01.20 cli command "switch $i priority $pri" pattern "continue|#"
action 01.21 cli command "y"
action 01.22 if $i eq $sw_num
action 01.23 append change_list "\n ## FOC11111111 (Priority: $pri // Numbered: $sw_num // Version: $curr_ver)"
action 01.24 else
action 01.25 cli command "switch $i renumber $sw_num" pattern "continue|#"
action 01.26 cli command "y"
action 01.27 append change_list "\n ## FOC11111111 (Priority: $pri // Renumbered: $i > $sw_num* // Version: $curr_ver)"
action 01.28 end
action 01.29 break
action 01.30 end
action 01.31 end
action 01.32 end
action 01.33 end
action 02.00 set sw_num "2"
action 02.01 set pri "16"
action 02.02 decrement pri 2
action 02.03 regexp "FOC22222222" "$stack"
action 02.04 if $_regexp_result ne "1"
action 02.05 syslog msg "\n ## FOC22222222 (Sw-2 serial) not found in the stack, check 'show mod' output."
action 02.06 append error_list "\n ## FOC22222222 is allocated (idarray_2) but was not found in the stack."
action 02.07 else
action 02.08 set i "0"
action 02.09 foreach line "$stack" "\n"
action 02.10 increment i
action 02.11 if $i le "4"
action 02.12 string trim "$line"
action 02.13 set line "$_string_result"
action 02.14 regexp "FOC22222222" "$line"
action 02.15 if $_regexp_result eq "1"
action 02.16 regexp "([0-9\.A-Z]+$)" "$line" curr_ver
action 02.17 if $curr_ver ne "16.3.7"
action 02.18 append upgrade_list "2"
action 02.19 end
action 02.20 cli command "switch $i priority $pri" pattern "continue|#"
action 02.21 cli command "y"
action 02.22 if $i eq $sw_num
action 02.23 append change_list "\n ## FOC22222222 (Priority: $pri // Numbered: $sw_num // Version: $curr_ver)"
action 02.24 else
action 02.25 cli command "switch $i renumber $sw_num" pattern "continue|#"
action 02.26 cli command "y"
action 02.27 append change_list "\n ## FOC22222222 (Priority: $pri // Renumbered: $i > $sw_num* // Version: $curr_ver)"
action 02.28 end
action 02.29 break
action 02.30 end
action 02.31 end
action 02.32 end
action 02.33 end
action 03.00 set sw_num "3"
action 03.01 set pri "16"
action 03.02 decrement pri 3
action 03.03 regexp "FOC33333333" "$stack"
action 03.04 if $_regexp_result ne "1"
action 03.05 syslog msg "\n ## FOC33333333 (Sw-3 serial) not found in the stack, check 'show mod' output."
action 03.06 append error_list "\n ## FOC33333333 is allocated (idarray_3) but was not found in the stack."
action 03.07 else
action 03.08 set i "0"
action 03.09 foreach line "$stack" "\n"
action 03.10 increment i
action 03.11 if $i le "4"
action 03.12 string trim "$line"
action 03.13 set line "$_string_result"
action 03.14 regexp "FOC33333333" "$line"
action 03.15 if $_regexp_result eq "1"
action 03.16 regexp "([0-9\.A-Z]+$)" "$line" curr_ver
action 03.17 if $curr_ver ne "16.3.7"
action 03.18 append upgrade_list "3"
action 03.19 end
action 03.20 cli command "switch $i priority $pri" pattern "continue|#"
action 03.21 cli command "y"
action 03.22 if $i eq $sw_num
action 03.23 append change_list "\n ## FOC33333333 (Priority: $pri // Numbered: $sw_num // Version: $curr_ver)"
action 03.24 else
action 03.25 cli command "switch $i renumber $sw_num" pattern "continue|#"
action 03.26 cli command "y"
action 03.27 append change_list "\n ## FOC33333333 (Priority: $pri // Renumbered: $i > $sw_num* // Version: $curr_ver)"
action 03.28 end
action 03.29 break
action 03.30 end
action 03.31 end
action 03.32 end
action 03.33 end
action 04.00 set sw_num "4"
action 04.01 set pri "16"
action 04.02 decrement pri 4
action 04.03 regexp "FOC44444444" "$stack"
action 04.04 if $_regexp_result ne "1"
action 04.05 syslog msg "\n ## FOC44444444 (Sw-4 serial) not found in the stack, check 'show mod' output."
action 04.06 append error_list "\n ## FOC44444444 is allocated (idarray_4) but was not found in the stack."
action 04.07 else
action 04.08 set i "0"
action 04.09 foreach line "$stack" "\n"
action 04.10 increment i
action 04.11 if $i le "4"
action 04.12 string trim "$line"
action 04.13 set line "$_string_result"
action 04.14 regexp "FOC44444444" "$line"
action 04.15 if $_regexp_result eq "1"
action 04.16 regexp "([0-9\.A-Z]+$)" "$line" curr_ver
action 04.17 if $curr_ver ne "16.3.7"
action 04.18 append upgrade_list "4"
action 04.19 end
action 04.20 cli command "switch $i priority $pri" pattern "continue|#"
action 04.21 cli command "y"
action 04.22 if $i eq $sw_num
action 04.23 append change_list "\n ## FOC44444444 (Priority: $pri // Numbered: $sw_num // Version: $curr_ver)"
action 04.24 else
action 04.25 cli command "switch $i renumber $sw_num" pattern "continue|#"
action 04.26 cli command "y"
action 04.27 append change_list "\n ## FOC44444444 (Priority: $pri // Renumbered: $i > $sw_num* // Version: $curr_ver)"
action 04.28 end
action 04.29 break
action 04.30 end
action 04.31 end
action 04.32 end
action 04.33 end
action 10.00 wait 5
action 10.01 if $error_list ne ""
action 10.02 syslog msg "\n ## The following errors occurred; $error_list"
action 10.03 end
action 10.04 syslog msg "\n ## Switches below have been assigned a priority and renumbered* as needed; $change_list"
action 13.00 cli command "conf t"
action 13.01 cli command "no event man app post_ztp_1"
action 14.00 if $upgrade_list eq ""
action 14.01 syslog msg " ## All switches are running version 16.3.7, skipping download->upgrade/reload; finalizing config in 20s."
action 14.02 cli command "no event man env q"
action 14.03 cli command "event man env ztp_upgraded no"
action 14.04 cli command " event man app post_ztp_2"
action 14.05 cli command " event timer countdown time 20 maxrun 480"
action 14.06 cli command " no action 00.00"
action 14.07 cli command " no action 00.01"
action 14.08 cli command " end"
action 14.09 cli command "write mem" pattern "confirm|#"
action 14.10 cli command ""
action 14.11 else
action 14.12 syslog msg " ## One or more switches require an upgrade to version 16.3.7 ($upgrade_list); proceeding with download->upgrade/reload."
action 14.13 cli command "event man env ztp_upgraded yes"
action 14.14 cli command "event man app post_ztp_2"
action 14.15 cli command " event syslog occurs 1 pattern $q%IOSXE_REDUNDANCY-6-PEER$q maxrun 630"
action 14.16 cli command " no event man env q"
action 14.17 cli command "end"
action 14.18 cli command "write mem" pattern "confirm|#"
action 14.19 cli command ""
action 14.20 syslog msg " ## (Standby) Downloading image..."
action 14.21 cli command "copy tftp://172.17.251.251/cat3k_caa-universalk9.16.03.07.SPA.bin flash:"
action 14.22 syslog msg " ## (Standby) Image downloaded, upgrading..."
action 14.23 cli command "software install file flash:cat3k_caa-universalk9.16.03.07.SPA.bin new force" pattern "proceed|#"
action 14.24 syslog msg " ## Upgrade complete, rebooting."
action 14.25 cli command "y"
action 14.26 end
!
event manager applet post_ztp_2
!-- Apply final configs, push running config via TFTP, clean up VL-1 and Te#/0/48 configs, write mem, and then perform package clean.
event none
action 00.00 syslog msg " ## Switch reloaded on new image, running 'post_ztp_2' EEM applet in 150s."
action 00.01 wait 150
action 00.02 syslog msg " ## (Standby) Applying global configs ignored by smart-install and generating crypto key..."
action 00.03 cli command "enable"
action 00.04 set upgr "$ztp_upgraded"
action 01.00 cli command "conf t"
action 01.01 cli command "no event man env ztp_upgraded"
action 01.02 cli command "no event man app post_ztp_2"
action 01.04 cli command "no vstack"
action 01.05 cli command "no ip http ser"
action 01.06 cli command "no ip http secure-s"
action 01.07 cli command "no ip http authen"
action 01.08 cli command "no coap http enable"
action 01.09 cli command "device-tracking policy IPDT"
action 01.10 cli command " no protocol udp"
action 01.11 cli command " tracking enable"
action 01.12 cli command "cry key gen rsa mod 2048"
action 02.00 syslog msg " ## (Standby) Applying `int-auth` macro config to ports 1-48 on all stack members..."
action 02.01 cli command "int range Gi1/0/1-36,Gi2/0/1-36,Gi3/0/1-36,Gi4/0/1-36"
action 02.02 cli command " macro apply int-auth"
action 02.03 cli command " no macro desc"
action 02.04 cli command "int range Te1/0/37-47,Te2/0/37-47,Te3/0/37-47,Te4/0/37-47"
action 02.05 cli command " macro apply int-auth"
action 02.06 cli command " no macro desc"
action 03.00 syslog msg " ## Pushing config to the following location: tftp://172.17.251.251/provisioned/CAS/ASW-TR04-02_FOC11111111-FOC22222222-FOC33333333-FOC44444444.cfg"
action 03.01 cli command "do copy run tftp://172.17.251.251/provisioned/CAS/ASW-TR04-02_FOC11111111-FOC22222222-FOC33333333-FOC44444444.cfg"
action 04.00 syslog msg " ## Disabling VL-1 SVI, updating Te#/0/48 configs, and writing startup config."
action 04.01 cli command "int vl 1"
action 04.02 cli command " no desc"
action 04.03 cli command " no ip addr"
action 04.04 cli command " shut"
action 04.05 cli command "default int range Te1/0/48,Te2/0/48,Te3/0/48,Te4/0/48"
action 04.06 cli command "int range Te1/0/48,Te2/0/48,Te3/0/48,Te4/0/48"
action 04.07 cli command " macro apply int-auth"
action 04.08 cli command " no macro desc"
action 04.09 cli command "end"
action 04.10 cli command "write mem" pattern "confirm|#"
action 04.11 cli command ""
action 05.00 if $upgr eq "yes"
action 05.01 syslog msg " ## (Standby) ZTP upgrade detected, performing software package clean..."
action 05.02 cli command "req plat soft pack clean sw all" pattern "proceed|#"
action 05.03 cli command "y"
action 05.04 syslog msg " ## Unused .bin or .pkg files from previous version(s) have been deleted."
action 05.05 else
action 05.06 syslog msg " ## ZTP upgrade not detected, skipping software package clean."
action 05.07 end
action 05.08 syslog msg " ## Start-up config written, (ASW-TR04-02) is ready for deployment, OK to power off."
!
end
##############################