test snmpnetwork_check {
    # these are defaults describing some test parameters
    static set features remote;
    static set name network;

    # re-discover every 60 minutes
    set discover_refresh 60;
    # after a discover failure retry every 10 minutes
    set discover_retry 10;
    # monitor every 5 minutes by default
    set frequency 5;
    # report as item "net"
    pernode set report_item "net";
    set host "set by uxmon";
    set alias "set by uxmon";
    # do not send perf variables by default
    set perf_frequency 0;

    # the module we get our configuration from
    static set domain snmp;

    # if interface contains a list of interfaces we will only monitor those
    set interface;
    # report yellow if errors go above this rate
    set error_warnrate 1;
    # report red if errors go above this rate
    set error_failrate 4;
    set maxload "60%";
    set warnload "30%";
    # the snmp community
    set community "public";
    # interfac names which are not reported
    static set avoid_interfaces;

    # just declare a few variables here
    set thismonitor;

    pernode set optional_info;

    pernode set monitored;
    pernode set formerly_monitored;
    pernode set former_description;

    static set description
	"Monitor per interface network load and error rates";

    static set arguments
	"maxerror:rate:Test fails if error rate goes above this value (default:4)"
	"warnerror:rate:Test shows yellow if error rate goes above this value (default: 1)"
	"maxload:kbsize|percentage:Fail if interface load goes above this percentage (default:60%)"
	"warnload:kbsize|percentage:Warn if interface load goes above this percentage (default:30%)"
	"interface:@pattern:A list of interface names"
	"speed:kbitrate:Override speed reported by the interface with this value"
	"community:string:The SNMP get community"
	"item:string:column name we should report the results under (default: cpu)"
	"perf:int:time in minutes between sending performance data (0 for no performance data)";

    # import configuration from uxmon-net
    init {
	debug 3 "network test starting";
	instance import interface;
	instance import maxerror error_warnrate;
	instance import warnerror error_failrate;
	instance import maxload;
	instance import warnload;
	instance import community;
	instance import perf perf_frequency;
	instance import speed override_speed;
	pernode import item report_item;

	set maxload input_kbsize( ${maxload} );
	set warnload input_kbsize( ${warnload} );
	set override_speed input_kbsize( ${override_speed} );
    }

    # walk the relevant data structures and do some pre-processing
    pernode discover {
	debug 3 "discovering network interfaces";
	get @${domain}.ifType @${domain}.ifSpeed
	    @${domain}.ifAdminStatus @${domain}.ifDescr
	    ${optional_data};
	pernode set iface.description ${${domain}.ifDescr};
	pernode set iface.type ${${domain}.ifType};
	pernode set iface.orgspeed ${${domain}.ifSpeed};
	pernode set iface.adminstatus ${${domain}.ifAdminStatus};

    }

    # select the entities this instance will monitor
    discover {
	set oldmonitor ${thismonitor};
	set monitored remove( ${monitored}, ${oldmonitor} );

	set index ${iface.description};
	select thismonitor index
	    ( null( ${interface} ) || contains_pattern( ${interface}, ${iface.description[${i}]} ) )
	   && not( contains( ${monitored}, ${i} ) )
	   && ( ${iface.adminstatus[${i}]} == 1 );

	set monitored ${monitored} ${thismonitor};

	instance set iface.speed;
	for iface.speed thismonitor if( ${override_speed}, 1000 * ${override_speed}, ${iface.orgspeed[${i}]} );

    };

    pernode postdiscover {
	debug 3 "currently monitored:" ${monitored};
	set notmonitored_anymore unmonitored( ${formerly_monitored}, ${monitored}, ${former_description} );
	set newly_monitored nowmonitored( ${formerly_monitored}, ${monitored}, ${iface.description} );
	event "notice" ${notmonitored_anymore};
	event "notice" ${newly_monitored};
	pernode set formerly_monitored ${monitored};
	pernode set former_description ${iface.description};
    }

    pernode monitor {
	# clear variables
        pernode set iface.inoctets;
	pernode set iface.outoctets;
	pernode set iface.inrate;
	pernode set iface.outrate;
	pernode set iface.inload;
	pernode set iface.outload;
	pernode set iface.inerrors;
	pernode set iface.outerrors;
	pernode set iface.operstatus;
    }

    monitor {
	debug 3 getting ${thismonitor} for domain ${domain};
	get ${domain}.ifInErrors[${thismonitor}]
	    ${domain}.ifOutErrors[${thismonitor}]
	    ${domain}.ifInOctets[${thismonitor}]
	    ${domain}.ifOutOctets[${thismonitor}]
	    ${domain}.ifOperStatus[${thismonitor}];

	for iface.inoctets thismonitor ${${domain}.ifInOctets[${i}]} - ${old.inoctets[${i}]};
	for iface.inoctets thismonitor if( ${iface.inoctets[${i}]} < 0 , 0 , ${iface.inoctets[${i}]} );
	for iface.outoctets thismonitor ${${domain}.ifOutOctets[${i}]} - ${old.outoctets[${i}]};
	for iface.outoctets thismonitor if( ${iface.outoctets[${i}]} < 0 , 0 , ${iface.outoctets[${i}]} );
	for iface.inerrors thismonitor ( ${${domain}.ifInErrors[${i}]} - ${old.inerrors[${i}]} ) / ( when( ${${domain}.ifInErrors[${i}]} ) - when( ${old.inerrors[${i}]} ) );
	for iface.inerrors thismonitor if( ${iface.inerrors[${i}]} < 0 , 0 , ${iface.inerrors[${i}]} );
	for iface.outerrors thismonitor ( ${${domain}.ifOutErrors[${i}]} - ${old.outerrors[${i}]} ) / ( when( ${${domain}.ifOutErrors[${i}]} ) - when( ${old.outerrors[${i}]} ) );
	for iface.outerrors thismonitor if( ${iface.outerrors[${i}]} < 0 , 0 , ${iface.outerrors[${i}]} );

	for iface.inrate thismonitor ${iface.inoctets[${i}]} / ( when( ${${domain}.ifInOctets[${i}]} ) - when( ${old.inoctets[${i}]} ) );
	for iface.outrate thismonitor ${iface.outoctets[${i}]} / ( when( ${${domain}.ifOutOctets[${i}]} ) - when( ${old.outoctets[${i}]} ) );
	for iface.inload thismonitor percentage( ${iface.inrate[${i}]} * 8, ${iface.speed[${i}]} );
	for iface.outload thismonitor percentage( ${iface.outrate[${i}]} * 8, ${iface.speed[${i}]} );

	for iface.operstatus thismonitor ${${domain}.ifOperStatus[${i}]};

	instance set old.inerrors ${${domain}.ifInErrors};
	instance set old.outerrors ${${domain}.ifOutErrors};
	instance set old.inoctets ${${domain}.ifInOctets};
	instance set old.outoctets ${${domain}.ifOutOctets};
    };

    pernode report {
	debug 3 monitored items are ${monitored};
	set text;
	set head pad( "Iface", 20, "l" )
		pad( "InErr", 12, "r" )
		pad( "OutErr", 12, "r" )
		pad( "InRate", 12, "r" )
		pad( "OutRate", 12, "r" )
		pad( "InLoad", 10, "r" )
		pad( "OutLoad", 10, "r" )
		" \n\n";
	for text monitored pad( ${iface.description[${i}]}, 20, "l" )
		pad( ${iface.inerrors[${i}]}, 10, "r" ) "/s"
		pad( ${iface.outerrors[${i}]}, 10, "r" ) "/s"
		pad( format_kbsize( ${iface.inrate[${i}]} / 1024 ), 10, "r" ) "/s"
		pad( format_kbsize( ${iface.outrate[${i}]} / 1024 ), 10, "r" ) "/s"
		pad( format_percentage( ${iface.inload[${i}]} ), 9, "r" ) 
		pad( format_percentage( ${iface.outload[${i}]} ), 9, "r" )
		" \n";
	status purple null( ${monitored} ) "no interfaces monitored";
	comment "html" "<HR></HR><PRE><strong>" ${head} </strong> ${text} "</PRE>";
    };

    report for thismonitor {
	status red not( null( ${iface.operstatus[${p}]} ) ) && not( ${iface.operstatus[${p}]} == 1 )
	    "&red " ${iface.description[${p}]} " is down";

	status red not( null( ${maxload} ) ) && in_range( ${maxload}, "200%", ${iface.inrate[${p}]} / 1024, ${iface.inload[${p}]} )
	    "&red" " " "${iface.description[${p}]} input overload";
	status red not( null( ${maxload} ) ) && in_range( ${maxload}, "200%", ${iface.outrate[${p}]} / 1024, ${iface.outload[${p}]} )
	    "&red" " " "${iface.description[${p}]} output overload";
	status yellow not( null( ${warnload} ) ) && in_range( ${warnload}, ${maxload}, ${iface.inrate[${p}]} / 1024, ${iface.inload[${p}]} )
	    "&yellow" " " "${iface.description[${p}]} input overload";
	status yellow not( null( ${warnload} ) ) && in_range( ${warnload}, ${maxload}, ${iface.outrate[${p}]} / 1024, ${iface.outload[${p}]} )
	    "&yellow" " " "${iface.description[${p}]} output overload";

	status red not( null( ${maxerror} ) ) && in_range( ${maxerror}, 2000000, ${iface.inerrors[${p}]} )
	    "&red" " " "${iface.description[${p}]} input errors";
	status red not( null( ${maxerror} ) ) && in_range( ${maxerror}, 2000000, ${iface.outerrors[${p}]} )
	    "&red" " " "${iface.description[${p}]} output errors";
	status yellow not( null( ${warnerror} ) ) && in_range( ${warnerror}, ${maxerror}, ${iface.inerrors[${p}]} )
	    "&yellow " " "${iface.description[${p}]} input errors";
	status yellow not( null( ${warnerror} ) ) && in_range( ${warnerror}, ${maxerror}, ${iface.outerrors[${p}]} )
	    "&yellow " " "${iface.description[${p}]} output errors";

	status purple null( ${iface.inrate[${p}]} )
	    "&purple " ${iface.description[${p}]} " no info available";
	status green 1
	    "&green" " " ${iface.description[${p}]} " ok";
    };

    perf {
        export always iface.inerrors, ${iface.inerrors[${thismonitor}]};
        export always iface.outerrors, ${iface.outerrors[${thismonitor}]};
        export always iface.inrate, ${iface.inrate[${thismonitor}]};
        export always iface.outrate, ${iface.outrate[${thismonitor}]};
        export always iface.inload, ${iface.inload[${thismonitor}]};
        export always iface.outload, ${iface.outload[${thismonitor}]};

	export sometimes iface.description, ${iface.description[${thismonitor}]};
	export sometimes iface.speed, ${iface.speed[${thismonitor}]};
    };

    pernode unconfigure {
	pernode set monitored;
	pernode set iface.description;
	pernode set iface.speed;
	pernode set iface.type;
	pernode set iface.adminstatus;
	pernode set monitored;
    }
}



