::cisco::eem::event_register_timer cron cron_entry "0 0 * * *" queue_priority normal maxrun 600 #- # Copyright (c) 2009 Joe Marcus Clarke # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY # # This policy runs at a configured time, then checks to see if inactive ports # have been inactive for a configured amount of time. If so, then the ports # will be shutdown. # # This policy uses the following environment variables: # # suspend_ports_days : Number of days before a port is suspended. # # suspend_ports_config : Path to configuration file. # if { ![info exists suspend_ports_days] } { set result "ERROR: Policy cannot be run: variable suspend_ports_days has not been set" error $result $errorInfo } if { ![info exists suspend_ports_config] } { set result "ERROR: Policy cannot be run: variable suspend_ports_config has not been set" error $result $errorInfo } namespace import ::cisco::eem::* namespace import ::cisco::lib::* proc run_cli { clist } { set rbuf "" if {[llength $clist] < 1} { return -code ok $rbuf } if {[catch {cli_open} result]} { return -code error $result } else { array set cliarr $result } if {[catch {cli_exec $cliarr(fd) "enable"} result]} { return -code error $result } foreach cmd $clist { if {[catch {cli_exec $cliarr(fd) $cmd} result]} { return -code error $result } append rbuf $result } if {[catch {cli_close $cliarr(fd) $cliarr(tty_id)} result]} { puts "WARNING: $result" } return -code ok $rbuf } set SECS_IN_DAYS 1209600 set DOWN 0 set UP 1 set ADMIN_DOWN 2 set now [clock seconds] set susp_time [expr $suspend_ports_days * $SECS_IN_DAYS] array set suspend_ports [list] if { [catch {open $suspend_ports_config "r"} result] } { array set ports [list] } else { set fd $result set contents [read $fd] close $fd set contents [string trim $contents] array set ports [split $contents] } set result [run_cli [list "show ip interface brief | include Ethernet"]] foreach line [split $result "\n"] { set line [string trim $line] regsub -all {\s+} $line " " line set elems [split $line] set iface [lindex $elems 0] if { ! [regexp {Ethernet} $iface] || [llength $elems] < 6 } { continue } if { [lindex $elems 4] == "administratively" && [lindex $elems 5] == "down" } { set status $ADMIN_DOWN } elseif { [lindex $elems 4] == "down" } { set status $DOWN } elseif { [lindex $elems 4] == "up" && [lindex $elems 5] == "up" } { set status $UP } else { set status $DOWN } if { [info exists ports($iface)] } { if { $status == $UP || $status == $ADMIN_DOWN } { array unset ports $iface } else { if { [expr $now - $ports($iface)] >= $susp_time } { set suspend_ports($iface) $ports($iface) } } } else { if { $status == $DOWN } { set ports($iface) $now } } } set fd [open $suspend_ports_config "w"] puts -nonewline $fd [array get ports] close $fd set cli [list "config t"] foreach port [array name suspend_ports] { lappend cli "interface $port" lappend cli "shut" lappend cli "description shutdown due to inactivity - last used on [clock format $suspend_ports($port)]" action_syslog msg "Shutting down port $port since it was last used on [clock format $suspend_ports($port)]" } lappend cli "end" if { [catch {run_cli $cli} result] } { action_syslog priority err msg "Failed to shutdown ports: '$result'" } }