package com.intrbiz.bergamot.worker.engine.nagios; import java.io.IOException; import org.apache.log4j.Logger; import com.codahale.metrics.Timer; import com.intrbiz.Util; import com.intrbiz.bergamot.model.message.check.ExecuteCheck; import com.intrbiz.bergamot.model.message.reading.ReadingParcelMO; import com.intrbiz.bergamot.model.message.result.ActiveResultMO; import com.intrbiz.bergamot.nagios.NagiosPluginExecutor; import com.intrbiz.bergamot.nagios.model.NagiosPerfData; import com.intrbiz.bergamot.nagios.model.NagiosResult; import com.intrbiz.bergamot.queue.key.ReadingKey; import com.intrbiz.bergamot.worker.engine.AbstractExecutor; import com.intrbiz.gerald.polyakov.Reading; import com.intrbiz.gerald.source.IntelligenceSource; import com.intrbiz.gerald.witchcraft.Witchcraft; /** * Execute Nagios Plugins (CHecks) * * This CheckExecutor executes Nagios plugins (checks) by * forking the check, just like Nagios would. * * The exit code is read to determine the result status, * and stdOut/stdErr are read to determine the check output. * * Performance data is captured and stored as a parameter of * the result. * * Currently only the first line of the check output is read. * * To avoid polluting the core of Bergamot with Nagios specific * functionality, macro processing is pushed out to the edge. * As such the only component which needs to known about Nagios * macros is this Nagios specific CheckExecutor implementation. * */ public class NagiosExecutor extends AbstractExecutor<NagiosEngine> { private Logger logger = Logger.getLogger(NagiosExecutor.class); protected final Timer nagiosTimer; protected NagiosPluginExecutor executor; public NagiosExecutor() { super(); // setup the executor this.executor = new NagiosPluginExecutor(); // setup metrics IntelligenceSource source = Witchcraft.get().source("com.intrbiz.bergamot.nagios"); this.nagiosTimer = source.getRegistry().timer("all-nagios-plugin-executions"); } /** * Only execute Checks where the engine == "nagios" */ @Override public boolean accept(ExecuteCheck task) { return NagiosEngine.NAME.equalsIgnoreCase(task.getEngine()); } @Override public void execute(ExecuteCheck executeCheck) { logger.debug("Executing Nagios check : " + executeCheck.getEngine() + "::" + executeCheck.getName() + " for " + executeCheck.getCheckType() + " " + executeCheck.getCheckId()); ActiveResultMO resultMO = new ActiveResultMO().fromCheck(executeCheck); ReadingParcelMO readings = new ReadingParcelMO().fromCheck(executeCheck.getCheckId()); try { // validate the command line String commandLine = executeCheck.getParameter("command_line"); if (Util.isEmpty(commandLine)) throw new RuntimeException("The command_line must be defined!"); // execute Timer.Context tctx = this.nagiosTimer.time(); try { NagiosResult response = this.executor.execute(commandLine); resultMO.setOk(response.toOk()); resultMO.setStatus(response.toStatus()); resultMO.setOutput(response.getOutput()); resultMO.setRuntime(response.getRuntime()); // readings for (NagiosPerfData perfData : response.getPerfData()) { Reading reading = perfData.toReading(); if (reading != null) readings.reading(reading); } } finally { tctx.stop(); } } catch (IOException | InterruptedException e) { logger.error("Failed to execute nagios check command", e); resultMO.error(e); } this.publishActiveResult(executeCheck, resultMO); if (readings != null && readings.getReadings().size() > 0) this.publishReading(new ReadingKey(executeCheck.getCheckId(), executeCheck.getProcessingPool()), readings); } }