diff --git a/library/Icinga/Protocol/Commandpipe/Acknowledgement.php b/library/Icinga/Protocol/Commandpipe/Acknowledgement.php new file mode 100644 index 000000000..851221f94 --- /dev/null +++ b/library/Icinga/Protocol/Commandpipe/Acknowledgement.php @@ -0,0 +1,58 @@ +expireTime = intval($time); + } + + public function setNotify($bool) + { + $this->notify = (bool) $bool; + } + + public function __construct(Comment $comment, $notify = false, $expire = -1, $sticky=false) + { + $this->comment = $comment; + $this->setNotify($notify); + $this->setExpireTime($expire); + $this->sticky = $sticky; + } + + public function getFormatString($type) + { + $params = ';'.($this->sticky ? '2' : '0').';'.($this->notify ? '1 ': '0').';'.($this->comment->persistent ? '1' : '0'); + $params .= ($this->expireTime > -1 ? ';'.$this->expireTime.';' : ';').$this->comment->author.';'.$this->comment->comment; + + switch($type) { + case CommandPipe::TYPE_HOST: + $typeVar = "HOST"; + $params = ";%s".$params; + break; + case CommandPipe::TYPE_SERVICE: + $typeVar = "SVC"; + $params = ";%s;%s".$params; + break; + default: + throw new InvalidCommandException("Acknowledgements can only apply on hosts and services "); + } + + $base = "ACKNOWLEDGE_{$typeVar}_PROBLEM".($this->expireTime > -1 ? '_EXPIRE' : '' ); + return $base.$params; + + + + } + + +} \ No newline at end of file diff --git a/library/Icinga/Protocol/Commandpipe/CommandPipe.php b/library/Icinga/Protocol/Commandpipe/CommandPipe.php new file mode 100644 index 000000000..34501717a --- /dev/null +++ b/library/Icinga/Protocol/Commandpipe/CommandPipe.php @@ -0,0 +1,320 @@ +path = $config->path; + $this->name = $config->name; + if(isset($config->host)) { + $this->host = $config->host; + } + if(isset($config->port)) { + $this->port = $config->port; + } + if(isset($config->user)) { + $this->user = $config->user; + } + } + + public function send($command) + { + if(!$this->host) { + IcingaLogger::debug("Attempting to send external icinga command $command to local command file {$this->path}"); + $file = @fopen($this->path, $this->fopen_mode); + if (!$file) + throw new \RuntimeException("Could not open icinga pipe at $file : ".print_r(error_get_last(), true)); + fwrite($file,"[".time()."] ".$command.PHP_EOL); + IcingaLogger::debug('Writing ['.time().'] '.$command.PHP_EOL); + fclose($file); + } else { + // send over ssh + $retCode = 0; + $output = array(); + IcingaLogger::debug('Icinga instance is on different host, attempting to send command %s via ssh to %s:%s/%s', $command, $this->host, $this->port, $this->path); + $hostConnector = $this->user ? $this->user."@".$this->host : $this->host; + exec("ssh $hostConnector -p{$this->port} \"echo '[".time()."] ".escapeshellcmd($command)."' > {$this->path}\"", $output, $retCode); + IcingaLogger::debug("$:ssh $hostConnector -p{$this->port} \"echo '[".time()."] ".escapeshellcmd($command)."' > {$this->path}\""); + IcingaLogger::debug("Code code %s: %s ", $retCode, $output); + + if($retCode != 0) { + throw new \RuntimeException('Could not send command to remote icinga host: '.implode("\n", $output)." (returncode $retCode)"); + } + } + } + + public function acknowledge($objects,IComment $acknowledgementOrComment) { + if (is_a($acknowledgementOrComment,'Icinga\Protocol\Commandpipe\Comment')) + $acknowledgementOrComment = new Acknowledgement($acknowledgementOrComment); + + foreach ($objects as $object) { + if (isset($object->service_description)) { + $format = $acknowledgementOrComment->getFormatString(self::TYPE_SERVICE); + $this->send(sprintf($format,$object->host_name,$object->service_description)); + } else { + $format = $acknowledgementOrComment->getFormatString(self::TYPE_HOST); + $this->send(sprintf($format,$object->host_name)); + } + } + } + + public function removeAcknowledge($objects) + { + foreach ($objects as $object) { + if (isset($object->service_description)) { + $this->send("REMOVE_SVC_ACKNOWLEDGEMENT;$object->host_name;$object->service_description"); + } else { + $this->send("REMOVE_HOST_ACKNOWLEDGEMENT;$object->host_name"); + } + } + } + + public function submitCheckResult($objects, $state, $output) + { + foreach ($objects as $object) { + if (isset($object->service_description)) { + $this->send("PROCESS_SVC_CHECK_RESULT;$object->host_name;$object->service_description;$state;$output"); + } else { + $this->send("PROCESS_HOST_CHECK_RESULT;$object->host_name;$state;$output"); + } + } + } + + public function scheduleForcedCheck($objects,$time=false,$withChilds=false) { + if (!$time) + $time = time(); + $base = "SCHEDULE_FORCED_"; + foreach ($objects as $object) { + if (isset($object->service_description)) { + $this->send($base."SVC_CHECK;$object->host_name;$object->service_description;$time"); + } else { + $this->send($base.'HOST_'.($withChilds ? 'SVC_CHECKS' : 'CHECK' ).";$object->host_name;$time"); + } + } + } + + public function scheduleCheck($objects,$time=false,$withChilds=false) { + if (!$time) + $time = time(); + $base = "SCHEDULE_"; + foreach ($objects as $object) { + if (isset($object->service_description)) { + $this->send($base."SVC_CHECK;$object->host_name;$object->service_description;$time"); + } else { + $this->send($base.'HOST_'.($withChilds ? 'SVC_CHECKS' : 'CHECK' ).";$object->host_name;$time"); + } + } + } + + public function addComment(array $objects, Comment $comment) + { + foreach ($objects as $object) { + if (isset($object->service_description)) { + $format = $comment->getFormatString(self::TYPE_SERVICE); + $this->send(sprintf($format,$object->host_name,$object->service_description)); + } else { + $format = $comment->getFormatString(self::TYPE_HOST); + $this->send(sprintf($format,$object->host_name)); + } + } + + } + + public function removeComment($objectsOrComments) + { + foreach ($objectsOrComments as $object) { + if (isset($object->comment_id)) { + if (isset($object->service_description)) { + $type = "SERVICE_COMMENT"; + } else { + $type = "HOST_COMMENT"; + } + $this->send("DEL_{$type};".intval($object->comment_id)); + } else { + if (isset($object->service_description)) { + $type = "SERVICE_COMMENT"; + } else { + $type = "HOST_COMMENT"; + } + $cmd = "DEL_ALL_{$type}S;".$object->host_name; + if ($type == "SERVICE_COMMENT") + $cmd .= ";".$object->service_description; + $this->send($cmd); + } + } + } + + public function enableGlobalNotifications() + { + $this->send("ENABLE_NOTIFICATIONS"); + } + + public function disableGlobalNotifications() + { + $this->send("DISABLE_NOTIFICATIONS"); + } + + private function getObjectType($object) + { + //@TODO: This must be refactored once more commands are supported + if (isset($object->service_description)) + return self::TYPE_SERVICE; + return self::TYPE_HOST; + } + + public function scheduleDowntime($objects, Downtime $downtime) + { + foreach ($objects as $object) { + $type = $this->getObjectType($object); + if($type == self::TYPE_SERVICE) + $this->send(sprintf($downtime->getFormatString($type),$object->host_name,$object->service_description)); + else + $this->send(sprintf($downtime->getFormatString($type),$object->host_name)); + } + } + + public function removeDowntime($objects,$starttime = 0) + { + foreach ($objects as $object) { + $type = $this->getObjectType($object); + if (isset($object->downtime_id)) { + $this->send("DEL_".$type."_DOWNTIME;".$object->downtime_id); + continue; + } + $cmd = "DEL_DOWNTIME_BY_HOST_NAME;".$object->host_name; + if($type == self::TYPE_SERVICE) + $cmd .= ";".$object->service_description; + if($starttime != 0) + $cmd .= ";".$starttime; + $this->send($cmd); + } + } + + public function restartIcinga() + { + $this->send("RESTART_PROCESS"); + } + + public function setMonitoringProperties($objects, PropertyModifier $flags) + { + foreach ($objects as $object) { + $type = $this->getObjectType($object); + $formatArray = $flags->getFormatString($type); + foreach ($formatArray as $format) { + $format .= ";".$object->host_name.($type == self::TYPE_SERVICE ? ";".$object->service_description : ""); + $this->send($format); + } + } + } + + public function enableActiveChecks($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::ACTIVE => PropertyModifier::STATE_ENABLE + ))); + } + + public function disableActiveChecks($objects) + { + $this->modifyMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::ACTIVE => PropertyModifier::STATE_DISABLE + ))); + } + + public function enablePassiveChecks($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::PASSIVE => PropertyModifier::STATE_ENABLE + ))); + } + + public function disablePassiveChecks($objects) + { + $this->modifyMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::PASSIVE => PropertyModifier::STATE_DISABLE + ))); + } + + public function enableFlappingDetection($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::FLAPPING => PropertyModifier::STATE_ENABLE + ))); + } + + public function disableFlappingDetection($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::FLAPPING => PropertyModifier::STATE_DISABLE + ))); + } + + public function enableNotifications($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::NOTIFICATIONS => PropertyModifier::STATE_ENABLE + ))); + } + + public function disableNotifications($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::NOTIFICATIONS => PropertyModifier::STATE_DISABLE + ))); + } + + public function enableFreshnessChecks($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::FRESHNESS => PropertyModifier::STATE_ENABLE + ))); + } + + public function disableFreshnessChecks($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::FRESHNESS => PropertyModifier::STATE_DISABLE + ))); + } + public function enableEventHandler($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::EVENTHANDLER => PropertyModifier::STATE_ENABLE + ))); + } + + public function disableEventHandler($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::EVENTHANDLER => PropertyModifier::STATE_DISABLE + ))); + } + + public function enablePerfdata($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::PERFDATA => PropertyModifier::STATE_ENABLE + ))); + } + + public function disablePerfdata($objects) + { + $this->setMonitoringProperties($objects,new PropertyModifier(array( + PropertyModifier::PERFDATA => PropertyModifier::STATE_DISABLE + ))); + } +} \ No newline at end of file diff --git a/library/Icinga/Protocol/Commandpipe/Comment.php b/library/Icinga/Protocol/Commandpipe/Comment.php new file mode 100644 index 000000000..b50459a87 --- /dev/null +++ b/library/Icinga/Protocol/Commandpipe/Comment.php @@ -0,0 +1,37 @@ +author = $author; + $this->comment = $comment; + $this->persistent = $persistent; + } + + public function getFormatString($type) { + $params = ';'.($this->persistent ? '1' : '0').';'.$this->author.';'.$this->comment; + + switch($type) { + case CommandPipe::TYPE_HOST: + $typeVar = "HOST"; + $params = ";%s".$params; + break; + case CommandPipe::TYPE_SERVICE: + $typeVar = "SVC"; + $params = ";%s;%s".$params; + break; + default: + throw new InvalidCommandException("Acknowledgements can only apply on hosts and services "); + } + return "ADD_{$typeVar}_COMMENT$params"; + } + + +} \ No newline at end of file diff --git a/library/Icinga/Protocol/Commandpipe/Downtime.php b/library/Icinga/Protocol/Commandpipe/Downtime.php new file mode 100644 index 000000000..25fcbece5 --- /dev/null +++ b/library/Icinga/Protocol/Commandpipe/Downtime.php @@ -0,0 +1,29 @@ +startTime = $start; + $this->endTime = $end; + $this->comment = $comment; + if($duration != 0) + $this->fixed = true; + $this->duration = intval($duration); + } + + public function getFormatString($type) { + return 'SCHEDULE_'.$type.'_DOWNTIME;%s' + .($type == CommandPipe::TYPE_SERVICE ? ';%s;' : ';') + .$this->startTime.';'.$this->endTime + .';'.($this->fixed ? '1' : '0').';'.$this->duration.';0;' + .$this->comment->author.';'.$this->comment->comment; + } +} diff --git a/library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php b/library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php new file mode 100644 index 000000000..ebd813925 --- /dev/null +++ b/library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php @@ -0,0 +1,7 @@ + self::STATE_KEEP, + self::ACTIVE => self::STATE_KEEP, + self::PASSIVE => self::STATE_KEEP, + self::NOTIFICATIONS => self::STATE_KEEP, + self::FRESHNESS => self::STATE_KEEP, + self::EVENTHANDLER => self::STATE_KEEP + ); + + public function __construct(array $flags) + { + foreach ($flags as $type=>$value) { + if (isset($this->flags[$type])) { + $this->flags[$type] = $value; + } + } + } + + public function getFormatString($type) { + $cmd = array(); + foreach($this->flags as $cmdTemplate=>$setting) { + if($setting == self::STATE_KEEP) + continue; + $commandString = ($setting == self::STATE_ENABLE ? "ENABLE_" : "DISABLE_"); + $targetString = $type; + if($type == CommandPipe::TYPE_SERVICE && $cmdTemplate == self::FRESHNESS) { + // the external command definition is inconsistent here.. + $targetString = "SERVICE"; + } + $commandString .= sprintf($cmdTemplate,$targetString); + $cmd[] = $commandString; + } + return $cmd; + } +} + + diff --git a/tests/php/bin/extcmd_test b/tests/php/bin/extcmd_test deleted file mode 100755 index aae501bfd..000000000 Binary files a/tests/php/bin/extcmd_test and /dev/null differ diff --git a/tests/php/library/Icinga/Protocol/Commandpipe/.CommandPipeTest.php.swp b/tests/php/library/Icinga/Protocol/Commandpipe/.CommandPipeTest.php.swp new file mode 100644 index 000000000..5031f8b77 Binary files /dev/null and b/tests/php/library/Icinga/Protocol/Commandpipe/.CommandPipeTest.php.swp differ diff --git a/tests/php/library/Icinga/Protocol/Commandpipe/AcknowledgementTest.php b/tests/php/library/Icinga/Protocol/Commandpipe/AcknowledgementTest.php index 5c754d801..9575af1a7 100644 --- a/tests/php/library/Icinga/Protocol/Commandpipe/AcknowledgementTest.php +++ b/tests/php/library/Icinga/Protocol/Commandpipe/AcknowledgementTest.php @@ -5,11 +5,11 @@ namespace Tests\Icinga\Protocol\Commandpipe; use Icinga\Protocol\Commandpipe\Comment as Comment; use Icinga\Protocol\Commandpipe\Commandpipe as Commandpipe; -require_once("../library/Icinga/Protocol/Commandpipe/IComment.php"); -require_once("../library/Icinga/Protocol/Commandpipe/Comment.php"); -require_once("../library/Icinga/Protocol/Commandpipe/CommandPipe.php"); -require_once("../library/Icinga/Protocol/Commandpipe/Acknowledgement.php"); -require_once("../library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/IComment.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/Comment.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/CommandPipe.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/Acknowledgement.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php"); class AcknowledgementTest extends \PHPUnit_Framework_TestCase { diff --git a/tests/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php b/tests/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php index 9595fc854..56a0e27fc 100644 --- a/tests/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php +++ b/tests/php/library/Icinga/Protocol/Commandpipe/CommandPipeTest.php @@ -8,13 +8,16 @@ use Icinga\Protocol\Commandpipe\Commandpipe as Commandpipe; use \Icinga\Protocol\Commandpipe\PropertyModifier as MONFLAG; require_once("Zend/Config.php"); -require_once("../library/Icinga/Protocol/Commandpipe/IComment.php"); -require_once("../library/Icinga/Protocol/Commandpipe/Comment.php"); -require_once("../library/Icinga/Protocol/Commandpipe/CommandPipe.php"); -require_once("../library/Icinga/Protocol/Commandpipe/Acknowledgement.php"); -require_once("../library/Icinga/Protocol/Commandpipe/Downtime.php"); -require_once("../library/Icinga/Protocol/Commandpipe/PropertyModifier.php"); -require_once("../library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php"); +require_once("Zend/Log.php"); +require_once("../../library/Icinga/Application/Logger.php"); + +require_once("../../library/Icinga/Protocol/Commandpipe/IComment.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/Comment.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/CommandPipe.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/Acknowledgement.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/Downtime.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/PropertyModifier.php"); +require_once("../../library/Icinga/Protocol/Commandpipe/Exception/InvalidCommandException.php"); if(!defined("EXTCMD_TEST_BIN")) define("EXTCMD_TEST_BIN", "./bin/extcmd_test"); diff --git a/tests/php/library/Icinga/Protocol/Ldap/QueryTest.php b/tests/php/library/Icinga/Protocol/Ldap/QueryTest.php index 793700900..d516fd6de 100644 --- a/tests/php/library/Icinga/Protocol/Ldap/QueryTest.php +++ b/tests/php/library/Icinga/Protocol/Ldap/QueryTest.php @@ -1,8 +1,8 @@