diff options
Diffstat (limited to 'modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php')
-rw-r--r-- | modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php b/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php new file mode 100644 index 0000000..aa47547 --- /dev/null +++ b/modules/monitoring/library/Monitoring/Command/Transport/CommandTransport.php @@ -0,0 +1,170 @@ +<?php +/* Icinga Web 2 | (c) 2014 Icinga Development Team | GPLv2+ */ + +namespace Icinga\Module\Monitoring\Command\Transport; + +use Exception; +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\Command\Object\ObjectCommand; +use Icinga\Module\Monitoring\Exception\CommandTransportException; + +/** + * Command transport + * + * This class is subject to change as we do not have environments yet (#4471). + */ +class CommandTransport implements CommandTransportInterface +{ + /** + * Transport configuration + * + * @var Config + */ + protected static $config; + + /** + * Get transport configuration + * + * @return Config + * + * @throws ConfigurationError + */ + public static function getConfig() + { + if (static::$config === null) { + $config = Config::module('monitoring', 'commandtransports'); + if ($config->isEmpty()) { + throw new ConfigurationError( + mt('monitoring', 'No command transports have been configured in "%s".'), + $config->getConfigFile() + ); + } + + static::$config = $config; + } + + return static::$config; + } + + /** + * Create a transport from config + * + * @param ConfigObject $config + * + * @return LocalCommandFile|RemoteCommandFile + * + * @throws ConfigurationError + */ + public static function createTransport(ConfigObject $config) + { + $config = clone $config; + switch (strtolower($config->transport)) { + case RemoteCommandFile::TRANSPORT: + $transport = new RemoteCommandFile(); + break; + case ApiCommandTransport::TRANSPORT: + $transport = new ApiCommandTransport(); + break; + case LocalCommandFile::TRANSPORT: + case '': // Casting null to string is the empty string + $transport = new LocalCommandFile(); + break; + default: + throw new ConfigurationError( + mt( + 'monitoring', + 'Cannot create command transport "%s". Invalid transport' + . ' defined in "%s". Use one of "%s", "%s" or "%s".' + ), + $config->transport, + static::getConfig()->getConfigFile(), + LocalCommandFile::TRANSPORT, + RemoteCommandFile::TRANSPORT, + ApiCommandTransport::TRANSPORT + ); + } + + unset($config->transport); + foreach ($config as $key => $value) { + $method = 'set' . ucfirst($key); + if (! method_exists($transport, $method)) { + // Ignore settings from config that don't have a setter on the transport instead of throwing an + // exception here because the transport should throw an exception if it's not fully set up + // when being about to send a command + continue; + } + + $transport->$method($value); + } + + return $transport; + } + + /** + * Send the given command over an appropriate Icinga command transport + * + * This will try one configured transport after another until the command has been successfully sent. + * + * @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 function send(IcingaCommand $command, $now = null) + { + $errors = array(); + + foreach (static::getConfig() as $name => $transportConfig) { + $transport = static::createTransport($transportConfig); + if ($this->transferPossible($command, $transport)) { + try { + $transport->send($command, $now); + } catch (Exception $e) { + Logger::error($e); + $errors[] = sprintf('%s: %s.', $name, rtrim($e->getMessage(), '.')); + continue; // Try the next transport + } + + return; // The command was successfully sent + } + } + + if (! empty($errors)) { + throw new CommandTransportException(implode("\n", $errors)); + } + + throw new CommandTransportException( + mt( + 'monitoring', + 'Failed to send external Icinga command. No transport has been configured' + . ' for this instance. Please contact your Icinga Web administrator.' + ) + ); + } + + /** + * Return whether it is possible to send the given command using the given transport + * + * @param IcingaCommand $command + * @param CommandTransportInterface $transport + * + * @return bool + */ + protected function transferPossible($command, $transport) + { + if (! method_exists($transport, 'getInstance') || !$command instanceof ObjectCommand) { + return true; + } + + $transportInstance = $transport->getInstance(); + if (! $transportInstance || $transportInstance === 'none') { + return true; + } + + return strtolower($transportInstance) === strtolower($command->getObject()->instance_name); + } +} |