CommandTransport: Add fallback mechanism

refs #8981
refs #9651
This commit is contained in:
Johannes Meyer 2015-08-31 09:21:59 +02:00
parent 660540ee1a
commit fcbd24e28e
1 changed files with 54 additions and 35 deletions

View File

@ -4,15 +4,18 @@
namespace Icinga\Module\Monitoring\Command\Transport; namespace Icinga\Module\Monitoring\Command\Transport;
use Icinga\Application\Config; use Icinga\Application\Config;
use Icinga\Application\Logger;
use Icinga\Data\ConfigObject; use Icinga\Data\ConfigObject;
use Icinga\Exception\ConfigurationError; 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). * This class is subject to change as we do not have environments yet (#4471).
*/ */
abstract class CommandTransport class CommandTransport implements CommandTransportInterface
{ {
/** /**
* Transport configuration * Transport configuration
@ -25,20 +28,24 @@ abstract class CommandTransport
* Get transport configuration * Get transport configuration
* *
* @return Config * @return Config
*
* @throws ConfigurationError * @throws ConfigurationError
*/ */
public static function getConfig() public static function getConfig()
{ {
if (! isset(self::$config)) { if (static::$config === null) {
self::$config = Config::module('monitoring', 'commandtransports'); $config = Config::module('monitoring', 'commandtransports');
if (self::$config->isEmpty()) { if ($config->isEmpty()) {
throw new ConfigurationError( throw new ConfigurationError(
'No command transports have been configured in \'%s\'.', mt('monitoring', 'No command transports have been configured in "%s".'),
self::$config->getConfigFile() $config->getConfigFile()
); );
} }
static::$config = $config;
} }
return self::$config;
return static::$config;
} }
/** /**
@ -47,9 +54,10 @@ abstract class CommandTransport
* @param ConfigObject $config * @param ConfigObject $config
* *
* @return LocalCommandFile|RemoteCommandFile * @return LocalCommandFile|RemoteCommandFile
*
* @throws ConfigurationError * @throws ConfigurationError
*/ */
public static function fromConfig(ConfigObject $config) public static function createTransport(ConfigObject $config)
{ {
$config = clone $config; $config = clone $config;
switch (strtolower($config->transport)) { switch (strtolower($config->transport)) {
@ -62,14 +70,18 @@ abstract class CommandTransport
break; break;
default: default:
throw new ConfigurationError( throw new ConfigurationError(
'Can\'t create command transport \'%s\'. Invalid transport defined in \'%s\'.' mt(
. ' Use one of \'%s\' or \'%s\'.', 'monitoring',
'Cannot create command transport "%s". Invalid transport'
. ' defined in "%s". Use one of "%s" or "%s".'
),
$config->transport, $config->transport,
self::$config->getConfigFile(), static::getConfig()->getConfigFile(),
LocalCommandFile::TRANSPORT, LocalCommandFile::TRANSPORT,
RemoteCommandFile::TRANSPORT RemoteCommandFile::TRANSPORT
); );
} }
unset($config->transport); unset($config->transport);
foreach ($config as $key => $value) { foreach ($config as $key => $value) {
$method = 'set' . ucfirst($key); $method = 'set' . ucfirst($key);
@ -79,37 +91,44 @@ abstract class CommandTransport
// when being about to send a command // when being about to send a command
continue; continue;
} }
$transport->$method($value); $transport->$method($value);
} }
return $transport; 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 * @param IcingaCommand $command The command to send
* @throws ConfigurationError * @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); foreach (static::getConfig() as $transportConfig) {
if ($config->isEmpty()) { $transport = static::createTransport($transportConfig);
throw new ConfigurationError();
} try {
return self::fromConfig($config); $transport->send($command, $now);
} catch (CommandTransportException $e) {
Logger::error($e);
continue; // Try the next transport
} }
/** return; // The command was successfully sent
* Create a transport by the first section of the configuration }
*
* @return LocalCommandFile|RemoteCommandFile throw new CommandTransportException(
*/ mt(
public static function first() 'monitoring',
{ 'Failed to send external Icinga command. None of the configured transports'
$config = self::getConfig(); . ' was able to transfer the command. Please see the log for more details.'
$config->rewind(); )
return self::fromConfig($config->current()); );
} }
} }