123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- ::cisco::eem::description "This policy bootstraps a device using the serial number and PID parameters"
- ::cisco::eem::event_register_appl tag timer sub_system 798 type 1 maxrun 7200
- ::cisco::eem::event_register_none tag none
- ::cisco::eem::trigger {
- ::cisco::eem::correlate event timer or event none
- }
- namespace import ::cisco::eem::*
- namespace import ::cisco::lib::*
- namespace import ::http::*
- # CHANGE ME!!!
- set ZTP_IP {ZTP_SERVER_IP}
- set URL "http://$ZTP_IP/swreg/swreg.php"
- set VERIFY_URL "http://$ZTP_IP/swreg/verify.php"
- set TFTP_URL "tftp://$ZTP_IP"
- proc init {} {
- variable map
- variable alphanumeric a-zA-Z0-9
- for {set i 0} {$i <= 256} {incr i} {
- set c [format %c $i]
- if { ! [string match \[$alphanumeric\] $c] } {
- set map($c) %[format %.2x $i]
- }
- }
- array set map { " " + \n %0d%0a }
- }
- init
- proc url_encode {str} {
- variable map
- variable alphanumeric
- regsub -all \[^$alphanumeric\] $str {$map(&)} str
- regsub -all {[][{})\\]\)} $str {\\&} str
- return [subst -nocommand $str]
- }
- if { [catch {cli_open} result] } {
- error $result $errorInfo
- }
- array set cli $result
- if { [catch {cli_exec $cli(fd) "enable"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "show inventory"} result] } {
- error $result $errorInfo
- }
- if { ! [regexp {PID: (\S+)} $result -> pid] } {
- puts "ERROR: Failed to find PID in '$result'"
- exit 1
- }
- if { ! [regexp {SN: (\S+)} $result -> sn] } {
- puts "ERROR: Failed to find SN in '$result'"
- exit 1
- }
- if { [catch {cli_exec $cli(fd) "show version"} result] } {
- error $result $errorInfo
- }
- if { ! [regexp {Version ([^,\s]+)[,\s]} $result -> vers] } {
- puts "ERROR: Failed to find version in '$result'"
- exit 1
- }
- if { ! [regexp {System image file is "([^:]+:[^"]+)"} $result -> imagepath] } { ;#"
- puts "ERROR: Failed to find system image file in '$result'"
- exit 1
- }
- set fstype {flash:}
- set rawimagef [file tail $imagepath]
- set imaged [string trimright [file dirname $imagepath] "/"]
- regexp {([^:]+:)} $imagepath -> fstype
- if { [catch {cli_exec $cli(fd) "show ip int brie | include Ethernet"} result] } {
- error $result $errorInfo
- }
- set intfs 0
- foreach line [split $result "\n"] {
- if { [regexp {Ethernet} $line] } {
- incr intfs
- }
- }
- set vers [url_encode $vers]
- set imagef [url_encode $rawimagef]
- ::http::config -useragent "tm_sw_autoconf.tcl/1.0"
- set tok [::http::geturl "$URL?pid=$pid&sn=$sn&version=$vers&num_ports=$intfs&imagef=$imagef"]
- if { [::http::error $tok] != "" } {
- puts "ERROR: Failed to retrieve device info: '[::http::error $tok]'"
- exit 1
- }
- set image {}
- set config {}
- set sdm {}
- set pnp 0
- foreach line [split [::http::data $tok] "\n"] {
- if { [regexp {^Image: (\S+)} $line -> res] } {
- set image $res
- }
- if { [regexp {^Config: (\S+)} $line -> res] } {
- set config $res
- }
- if { [regexp {^SDM: (\S+)} $line -> res] } {
- set sdm $res
- }
- if { [regexp {^PNP} $line] } {
- set pnp 1
- }
- }
- if { $image == {} && $config == {} && $pnp == 0 } {
- puts "Switch not registered; rebooting..."
- after 60000
- action_reload
- }
- if { $image != {} } {
- if { [catch {cli_exec $cli(fd) "del /force $imagepath"} result] } {
- error $result $errorInfo
- }
- if { $imaged != $fstype } {
- if { [catch {cli_exec $cli(fd) "del /force /recursive $imaged"} result] } {
- error $result $errorInfo
- }
- }
- if { [catch {cli_exec $cli(fd) "del /force $fstype$rawimagef"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "config t"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "ip tftp blocksize 8192"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "end"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "copy $TFTP_URL/$image $fstype"} result] } {
- error $result $errorInfo
- }
- # Log result in case this fails
- action_syslog msg "Output of copy command: '$result'"
- if { [catch {cli_exec $cli(fd) "config t"} result] } {
- error $result $errorInfo
- }
- # Workaround busted boot variable setting on 9300 switches.
- set fd [open "${fstype}boot_hack.txt" w]
- puts $fd "\nboot system $fstype$image\nend"
- close $fd
- if { [catch {cli_exec $cli(fd) "end"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "copy ${fstype}boot_hack.txt start"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "config t"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "boot system $fstype$image"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "no ip tftp blocksize 8192"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "end"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "write mem"} result] } {
- error $result $errorInfo
- }
- file delete -force ${fstype}boot_hack.txt
- if { [regexp {packages.conf} $imagepath] } {
- if { [catch {cli_exec $cli(fd) "del /force ${fstype}*.pkg"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "del /force ${fstype}packages.conf"} result] } {
- error $result $errorInfo
- }
- }
- if { [catch {cli_exec $cli(fd) "show boot | inc $image"} result] } {
- error $result $errorInfo
- }
- if { ! [regexp "$image" $result] } {
- action_syslog msg "FAILED BOOT: Failed to set boot variable: '$result'"
- exit 1
- }
- }
- if { $config != {} } {
- if { [catch {cli_exec $cli(fd) "copy $TFTP_URL/device-configs/$config start"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "show switch | inc ^\\*"} result] } {
- error $result $errorInfo
- }
- if { [regexp {\*([2-9])} $result -> swn] } {
- if { [catch {cli_exec $cli(fd) "config t"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_write $cli(fd) "switch $swn renumber 1"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_read_pattern $cli(fd) "(confirm|continue)"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "\r"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "end"} result] } {
- error $result $errorInfo
- }
- }
- if { [catch {cli_exec $cli(fd) "license right-to-use activate ipservices acceptEULA"} result] } {
- puts "WARNING: Failed to change license: '$result'"
- }
- if { [regexp {Invalid input} $result] } {
- if { [catch {cli_exec $cli(fd) "license right-to-use activate ipservices all acceptEULA"} result] } {
- puts "WARNING: Failed to change license: '$result'"
- }
- }
- }
- if { $sdm != {} } {
- if { [catch {cli_exec $cli(fd) "config t"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "sdm prefer $sdm"} result] } {
- error $result $errorInfo
- }
- if { [catch {cli_exec $cli(fd) "end"} result] } {
- error $result $errorInfo
- }
- }
- set md5 {}
- set verify_image {}
- if { $image != {} } {
- if { [catch {cli_exec $cli(fd) "verify /md5 $fstype$image"} result] } {
- error $result $errorInfo
- }
- if { ! [regexp {= ([A-Fa-f0-9]+)} $result -> md5] } {
- action_syslog msg "MD5 VALIDATION FAILED: '$result'"
- exit 1
- }
- set verify_image [url_encode $image]
- }
- if { $config != {} || $image != {} } {
- if { $config != {} } {
- if { [catch {cli_exec $cli(fd) "copy start ${TFTP_URL}/device-tmp/$config"} result] } {
- error $result $errorInfo
- }
- # Wait a max of five seconds for the tftp daemon to flush its write buffer.
- after 5000
- }
- ::http::config -useragent "tm_sw_autoconf.tcl/1.0"
- set tok [::http::geturl "$VERIFY_URL?config=$config&sn=$sn&md5=$md5&image=$verify_image"]
- if { [::http::error $tok] != "" } {
- puts "ERROR: Failed to verify device config: '[::http::error $tok]'"
- exit 1
- }
- foreach line [split [::http::data $tok] "\n"] {
- if { [regexp {ERROR:} $line] } {
- action_syslog msg "AUTOCONF FAILED: Bootstrap verification failed: '$line'"
- exit 1
- }
- }
- if { $config != {} } {
- # XXX: This seems weird, but it's required to make sure the VLAN database
- # is properly updated upon reboot. By loading the startup config into
- # running before rebooting, this reliable ensures the VLAN database is
- # consistent.
- if { [catch {cli_exec $cli(fd) "config mem"} result] } {
- error $result $errorInfo
- }
- }
- }
- if { $pnp == 1 } {
- if { [catch {cli_exec $cli(fd) "test pnpa discovery process"} result] } {
- error $result $errorInfo
- }
- # At this point, PnP takes over.
- # TODO Need to confirm that the PnP discovery is successful
- }
- catch {cli_close $cli(fd) $cli(tty_id)}
- action_syslog msg "AUTOCONF COMPLETE: Switch is ready."
- action_reload
|