From fcbd24e28ece81a7dbb5728837ba7a1aec403cad Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Mon, 31 Aug 2015 09:21:59 +0200 Subject: [PATCH] CommandTransport: Add fallback mechanism refs #8981 refs #9651 --- .../Command/Transport/CommandTransport.php | 89 +++++++++++-------- 1 file changed, 54 insertions(+), 35 deletions(-) diff --git a/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php b/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php index 73f66da02..822318e6f 100644 --- a/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php +++ b/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php @@ -4,15 +4,18 @@ namespace Icinga\Module\Monitoring\Command\Transport; use Icinga\Application\Config; +use Icinga\Application\Logger; use Icinga\Data\ConfigObject; use Icinga\Exception\ConfigurationError; +use Icinga\Module\Monitoring\Command\IcingaCommand; +use Icinga\Module\Monitoring\Exception\CommandTransportException; /** - * Command transport factory + * Command transport * * This class is subject to change as we do not have environments yet (#4471). */ -abstract class CommandTransport +class CommandTransport implements CommandTransportInterface { /** * Transport configuration @@ -24,21 +27,25 @@ abstract class CommandTransport /** * Get transport configuration * - * @return Config - * @throws ConfigurationError + * @return Config + * + * @throws ConfigurationError */ public static function getConfig() { - if (! isset(self::$config)) { - self::$config = Config::module('monitoring', 'commandtransports'); - if (self::$config->isEmpty()) { + if (static::$config === null) { + $config = Config::module('monitoring', 'commandtransports'); + if ($config->isEmpty()) { throw new ConfigurationError( - 'No command transports have been configured in \'%s\'.', - self::$config->getConfigFile() + mt('monitoring', 'No command transports have been configured in "%s".'), + $config->getConfigFile() ); } + + static::$config = $config; } - return self::$config; + + return static::$config; } /** @@ -47,9 +54,10 @@ abstract class CommandTransport * @param ConfigObject $config * * @return LocalCommandFile|RemoteCommandFile + * * @throws ConfigurationError */ - public static function fromConfig(ConfigObject $config) + public static function createTransport(ConfigObject $config) { $config = clone $config; switch (strtolower($config->transport)) { @@ -62,14 +70,18 @@ abstract class CommandTransport break; default: throw new ConfigurationError( - 'Can\'t create command transport \'%s\'. Invalid transport defined in \'%s\'.' - . ' Use one of \'%s\' or \'%s\'.', + mt( + 'monitoring', + 'Cannot create command transport "%s". Invalid transport' + . ' defined in "%s". Use one of "%s" or "%s".' + ), $config->transport, - self::$config->getConfigFile(), + static::getConfig()->getConfigFile(), LocalCommandFile::TRANSPORT, RemoteCommandFile::TRANSPORT ); } + unset($config->transport); foreach ($config as $key => $value) { $method = 'set' . ucfirst($key); @@ -79,37 +91,44 @@ abstract class CommandTransport // when being about to send a command continue; } + $transport->$method($value); } + return $transport; } /** - * Create a transport by name + * Send the given command over an appropriate Icinga command transport * - * @param string $name + * This will try one configured transport after another until the command has been successfully sent. * - * @return LocalCommandFile|RemoteCommandFile - * @throws ConfigurationError + * @param IcingaCommand $command The command to send + * @param int|null $now Timestamp of the command or null for now + * + * @throws CommandTransportException If sending the Icinga command failed */ - public static function create($name) + public function send(IcingaCommand $command, $now = null) { - $config = self::getConfig()->getSection($name); - if ($config->isEmpty()) { - throw new ConfigurationError(); - } - return self::fromConfig($config); - } + foreach (static::getConfig() as $transportConfig) { + $transport = static::createTransport($transportConfig); - /** - * Create a transport by the first section of the configuration - * - * @return LocalCommandFile|RemoteCommandFile - */ - public static function first() - { - $config = self::getConfig(); - $config->rewind(); - return self::fromConfig($config->current()); + try { + $transport->send($command, $now); + } catch (CommandTransportException $e) { + Logger::error($e); + continue; // Try the next transport + } + + return; // The command was successfully sent + } + + throw new CommandTransportException( + mt( + 'monitoring', + 'Failed to send external Icinga command. None of the configured transports' + . ' was able to transfer the command. Please see the log for more details.' + ) + ); } }