Last active
August 29, 2015 14:19
-
-
Save unicolet/1068dda960d9e549279d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.opennms.netmgt.correlation.drools; | |
import java.util.Date; | |
import java.util.Calendar; | |
import org.opennms.netmgt.correlation.drools.DroolsCorrelationEngine; | |
import org.opennms.netmgt.xml.event.Event; | |
import org.opennms.netmgt.xml.event.Parms; | |
import org.opennms.netmgt.xml.event.Parm; | |
import org.opennms.netmgt.xml.event.Value; | |
import org.opennms.netmgt.model.events.EventBuilder; | |
global org.opennms.netmgt.correlation.drools.DroolsCorrelationEngine engine; | |
global org.opennms.netmgt.correlation.drools.NodeService nodeService; | |
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.Calendar; | |
import java.util.Date; | |
import java.util.Iterator; | |
global java.lang.Integer REPEATING_INTERVAL; // in hours | |
declare Execution | |
nodeid : Long | |
uei : String | |
tag : String | |
interval : String | |
expireTimerId : Integer | |
// for passive status events | |
passiveIpAddr: String | |
passiveServiceName: String | |
passiveNodeLabel: String | |
end | |
/* | |
* Initial execution event for a node - send the initial translated event to generate notification | |
*/ | |
rule "initial event received" | |
when | |
$e : Event( $uei : uei, $nodeid : nodeid ) | |
eval( "every".equals($e.getParm("every").getValue().getContent()) ) // filter out internally generated 'missed' events | |
then | |
Execution execution = new Execution(); | |
execution.setNodeid( $nodeid ); | |
execution.setUei( $uei ); | |
execution.setTag( getTag($e) ); | |
execution.setInterval( $e.getParm("interval").getValue().getContent() ); | |
execution.setExpireTimerId( engine.setTimer( getInterval($e, REPEATING_INTERVAL) ) ); | |
// handle passive status events | |
if($uei.indexOf("passiveServiceStatus")!=-1) { | |
execution.setPassiveIpAddr($e.getParm("passiveIpAddr").getValue().getContent()); | |
execution.setPassiveServiceName($e.getParm("passiveServiceName").getValue().getContent()); | |
execution.setPassiveNodeLabel($e.getParm("passiveNodeLabel").getValue().getContent()); | |
} | |
insert( execution ); | |
// the event can be retracted, or the subsequent backup completed rule will fire | |
retract( $e ); | |
println( "Initial event tag="+getTag($e)+" event " + $uei + " for node " + $nodeid ); | |
end | |
/* | |
* Subsequent event completed | |
*/ | |
rule "subsequent event completed" | |
when | |
$e : Event( $uei : uei, $nodeid : nodeid ) | |
$execution : Execution( nodeid == $nodeid, $expireTimerId : expireTimerId ) | |
eval( $execution.getTag().equals( getTag($e) ) ) | |
eval( "every".equals($e.getParm("every").getValue().getContent()) ) // filter out internally generated 'missed' events | |
then | |
retract( $e ); | |
engine.cancelTimer($expireTimerId); | |
$execution.setExpireTimerId( engine.setTimer( getInterval($e, REPEATING_INTERVAL) ) ); | |
update( $execution ); | |
println( "Subsequent execution event " + $uei + " for node " + $nodeid +" supressed." ); | |
end | |
/* | |
* Expiration timer expires: warn user that another backup event was not received in the expected interval | |
*/ | |
rule "timer expired" | |
when | |
$execution : Execution( $tag: tag, $nodeid : nodeid, $expireTimerId : expireTimerId, $uei : uei, $interval: interval, $passiveNodeLabel: passiveNodeLabel, $passiveIpAddr: passiveIpAddr, $passiveServiceName: passiveServiceName) | |
$expire : TimerExpired( id == $expireTimerId ) | |
then | |
sendExecutionMissedEvent(engine, $nodeid, $uei, $tag , $interval, $passiveIpAddr, $passiveServiceName, $passiveNodeLabel); | |
retract( $execution ); | |
retract( $expire ); | |
println( "Event execution expiration for " + $uei + " for node " + $nodeid +"["+$tag+"]." ); | |
end | |
/* | |
* Utility to send a (failed) execution event. | |
*/ | |
function void sendExecutionMissedEvent( DroolsCorrelationEngine engine, Long nodeId, String uei, String tag, String interval, String passiveIpAddr, String passiveServiceName, String passiveNodeLabel) { | |
EventBuilder bldr = new EventBuilder(uei.replaceAll("Normal","Warning"), "Drools"); // clone current event | |
bldr.setNodeid(nodeId.intValue()); | |
bldr.addParam("correlationEngineName", "Drools"); | |
bldr.addParam("correlationRuleSetName", engine.getName()); | |
bldr.addParam("correlationComments", "RepeatingBackupRules"); | |
if(uei.indexOf("job")!=-1) { | |
bldr.addParam("job", tag); | |
} else { | |
bldr.addParam("backupset", tag); | |
} | |
if(uei.indexOf("passiveServiceStatus")!=-1) { | |
bldr.addParam("passiveStatus", "Down"); | |
bldr.addParam("passiveIpAddr", passiveIpAddr); | |
bldr.addParam("passiveServiceName", passiveServiceName); | |
bldr.addParam("passiveNodeLabel", passiveNodeLabel); | |
bldr.addParam("passiveReasonCode", "no events received and timer expired"); | |
} | |
bldr.addParam("tag", tag); | |
bldr.addParam("interval", interval); | |
bldr.addParam("every", "missed"); // this will be used to discriminate between normal failures (->"every") and missed executions (->"missed") | |
engine.sendEvent(bldr.getEvent()); | |
} | |
function String getTag(Event e) { | |
String tag=null; | |
Parm p=e.getParm("backupset"); | |
if(p!=null) { | |
tag=p.getValue().getContent(); | |
} | |
p=e.getParm("job"); | |
if(p!=null) { | |
tag=p.getValue().getContent(); | |
} | |
p=e.getParm("tag"); | |
if( p!=null && tag==null) { | |
tag=p.getValue().getContent(); | |
} | |
return tag; | |
} | |
function long getInterval(Event e, Integer defaultInterval) { | |
long interval = defaultInterval.intValue(); // default, in hours | |
Parm p=e.getParm("interval"); | |
if(p!=null) { | |
String value=p.getValue().getContent(); | |
if(value!=null && value.indexOf(":")!=-1) { | |
println("This event has an interval modifier: "+value); | |
// value contains a modifier, parse it | |
String[] values=value.split(":", 2); | |
try { | |
interval=new Integer(values[0]).intValue(); | |
} catch(Exception exc) { | |
println("Error parsing interval value="+value+" to integer. Using default REPEATING_INTERVAL"); | |
} | |
// now find out which modifier was used | |
if("weekdays".equals(values[1])) { | |
println("This event has a weekdays modifier"); | |
// the job is only meant to be run on weekdays: this means that any execution whose timer | |
// would expire on weekends (sat,sun) should be moved up to monday + interval | |
// example: on friday night at 23:00 a daily backup runs, interval is: 36:weekdays | |
// since the timer would expire on sunday at 11.00 it is moved up to tuesday at 11:00 (monday 23:00 + 36) | |
Calendar cal = Calendar.getInstance(); | |
cal.add(Calendar.HOUR_OF_DAY, (int)interval); | |
int dow = cal.get(Calendar.DAY_OF_WEEK); | |
if(dow == Calendar.SATURDAY || dow == Calendar.SUNDAY || dow == Calendar.FRIDAY) { | |
// timer would expire on saturday or sunday, move it up to monday then add interval again | |
println("Timer would expire on sat/sun, moving it up to monday"); | |
cal = Calendar.getInstance(); | |
cal.roll(Calendar.DAY_OF_YEAR, true); | |
while(cal.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) { | |
cal.roll(Calendar.DAY_OF_YEAR, true); | |
} | |
// now add interval | |
cal.add(Calendar.HOUR_OF_DAY, (int)interval); | |
} | |
println("Event timer has been moved up until: "+cal.getTime()); | |
interval = (cal.getTimeInMillis() - Calendar.getInstance().getTimeInMillis()); | |
println("Interval in ms: "+interval); | |
} | |
} else { | |
try { | |
interval = new Integer(value).intValue(); | |
interval = interval * 60 * 60 * 1000; // hours -> milliseconds | |
} catch(Exception exc) { | |
println("Error parsing interval value="+value+" to integer. Using default REPEATING_INTERVAL"); | |
} | |
} | |
} | |
return interval; | |
} | |
/* | |
* println utility | |
*/ | |
function void println(Object msg) { | |
System.err.println(new Date() + " RepeatingBackups : " + msg); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment