diff --git a/modules/monitoring/library/Monitoring/Backend.php b/modules/monitoring/library/Monitoring/Backend.php index 3af728860..e3672dcd5 100644 --- a/modules/monitoring/library/Monitoring/Backend.php +++ b/modules/monitoring/library/Monitoring/Backend.php @@ -1,186 +1,11 @@ resource = $resource; - $this->type = $type; - } - - // Temporary workaround, we have no way to know our name - protected function setName($name) - { - $this->name = $name; - } - - public function getName() - { - return $this->name; - } - - /** - * Create a backend - * - * @param string $backendName Name of the backend or null for creating the default backend which is the first INI - * configuration entry not being disabled - * - * @return Backend - * @throws ConfigurationError When no backend has been configured or all backends are disabled or the - * configuration for the requested backend does either not exist or it's disabled - */ - public static function createBackend($backendName = null) - { - $config = Config::module('monitoring', 'backends'); - if ($config->count() === 0) { - throw new ConfigurationError(mt('monitoring', 'No backend has been configured')); - } - if ($backendName !== null) { - $backendConfig = $config->get($backendName); - if ($backendConfig === null) { - throw new ConfigurationError('No configuration for backend %s', $backendName); - } - if ((bool) $backendConfig->get('disabled', false) === true) { - throw new ConfigurationError( - mt('monitoring', 'Configuration for backend %s available but backend is disabled'), - $backendName - ); - } - } else { - foreach ($config as $name => $backendConfig) { - if ((bool) $backendConfig->get('disabled', false) === false) { - $backendName = $name; - break; - } - } - if ($backendName === null) { - throw new ConfigurationError(mt('monitoring', 'All backends are disabled')); - } - } - $resource = ResourceFactory::create($backendConfig->resource); - if ($backendConfig->type === 'ido' && $resource->getDbType() !== 'oracle') { - // TODO(el): The resource should set the table prefix - $resource->setTablePrefix('icinga_'); - } - $backend = new Backend($resource, $backendConfig->type); - $backend->setName($backendName); - return $backend; - } - -public function getResource() -{ - return $this->resource; -} - - /** - * Backend entry point - * - * @return self - */ - public function select() - { - return $this; - } - - /** - * Create a data view to fetch data from - * - * @param string $viewName - * @param array $columns - * - * @return DataView - */ - public function from($viewName, array $columns = null) - { - $viewClass = $this->resolveDataViewName($viewName); - return new $viewClass($this, $columns); - } - - /** - * View name to class name resolution - * - * @param string $viewName - * - * @return string - * @throws ProgrammingError When the view does not exist - */ - protected function resolveDataViewName($viewName) - { - $viewClass = '\\Icinga\\Module\\Monitoring\\DataView\\' . ucfirst($viewName); - if (!class_exists($viewClass)) { - throw new ProgrammingError( - 'DataView %s does not exist', - ucfirst($viewName) - ); - } - return $viewClass; - } - - public function getQueryClass($name) - { - return $this->resolveQueryName($name); - } - - /** - * Query name to class name resolution - * - * @param string $queryName - * - * @return string - * @throws ProgrammingError When the query does not exist for this backend - */ - protected function resolveQueryName($queryName) - { - $queryClass = '\\Icinga\\Module\\Monitoring\\Backend\\' - . ucfirst($this->type) - . '\\Query\\' - . ucfirst($queryName) - . 'Query'; - if (!class_exists($queryClass)) { - throw new ProgrammingError( - 'Query "%s" does not exist for backend %s', - ucfirst($queryName), - ucfirst($this->type) - ); - } - return $queryClass; - } } diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/IdoBackend.php b/modules/monitoring/library/Monitoring/Backend/Ido/IdoBackend.php new file mode 100644 index 000000000..17bfb9f6a --- /dev/null +++ b/modules/monitoring/library/Monitoring/Backend/Ido/IdoBackend.php @@ -0,0 +1,9 @@ +name = $name; + $this->config = $config; + } + + /** + * Get a backend instance + * + * You may ask for a specific backend name or get the default one otherwise + * + * @param string $name Backend name + * + * @return MonitoringBackend + */ + public static function instance($name = null) + { + if (! array_key_exists($name, self::$instances)) { + + list($foundName, $config) = static::loadConfig($name); + $type = $config->get('type'); + $class = implode( + '\\', + array( + __NAMESPACE__, + ucfirst($type), + ucfirst($type) . 'Backend' + ) + ); + + if (!class_exists($class)) { + throw new ConfigurationError( + mt('monitoring', 'There is no "%s" monitoring backend'), + $class + ); + } + + self::$instances[$name] = new $class($foundName, $config); + if ($name === null) { + self::$instances[$foundName] = self::$instances[$name]; + } + } + + return self::$instances[$name]; + } + + /** + * Clear all cached instances. Mostly for testing purposes. + */ + public static function clearInstances() + { + self::$instances = array(); + } + + /** + * Whether this backend is of a specific type + * + * @param string $type Backend type + * + * @return boolean + */ + public function is($type) + { + return $this->getType() === $type; + } + + /** + * Get the configured name of this backend + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * Get the backend type name + * + * @return string + */ + public function getType() + { + if ($this->type === null) { + $parts = preg_split('~\\\~', get_class($this)); + $class = array_pop($parts); + if (substr($class, -7) === 'Backend') { + $this->type = lcfirst(substr($class, 0, -7)); + } else { + throw new ProgrammingError( + '%s is not a valid monitoring backend class name', + $class + ); + } + } + return $this->type; + } + + /** + * Return the configuration for the first enabled or the given backend + */ + protected static function loadConfig($name = null) + { + $backends = Config::module('monitoring', 'backends'); + + if ($name === null) { + + $count = 0; + + foreach ($backends as $name => $config) { + $count++; + if ((bool) $config->get('disabled', false) === false) { + return array($name, $config); + } + } + + if ($count === 0) { + $message = mt('monitoring', 'No backend has been configured'); + } else { + $message = mt('monitoring', 'All backends are disabled'); + } + + throw new ConfigurationError($message); + + } else { + + $config = $backends->get($name); + + if ($config === null) { + throw new ConfigurationError( + mt('monitoring', 'No configuration for backend %s'), + $name + ); + } + + if ((bool) $config->get('disabled', false) === true) { + throw new ConfigurationError( + mt('monitoring', 'Configuration for backend %s is disabled'), + $name + ); + } + + return array($name, $config); + } + } + + /** + * Create a backend + * + * @deprecated + * + * @param string $backendName Name of the backend or null for creating the default backend which is the first INI + * configuration entry not being disabled + * + * @return Backend + * @throws ConfigurationError When no backend has been configured or all backends are disabled or the + * configuration for the requested backend does either not exist or it's disabled + */ + public static function createBackend($name = null) + { + return self::instance($name); + } + + /** + * Get this backend's internal resource + * + * @return mixed + */ + public function getResource() + { + if ($this->resource === null) { + $this->resource = ResourceFactory::create($this->config->get('resource')); + if ($this->is('ido') && $this->resource->getDbType() !== 'oracle') { + // TODO(el): The resource should set the table prefix + $this->resource->setTablePrefix('icinga_'); + } + } + return $this->resource; + } + + /** + * Backend entry point + * + * @return self + */ + public function select() + { + return $this; + } + + /** + * Create a data view to fetch data from + * + * @param string $name + * @param array $columns + * + * @return DataView + */ + public function from($name, array $columns = null) + { + $class = $this->buildViewClassName($name); + return new $class($this, $columns); + } + + /** + * View name to class name resolution + * + * @param string $viewName + * + * @return string + * @throws ProgrammingError When the view does not exist + */ + protected function buildViewClassName($view) + { + $class = '\\Icinga\\Module\\Monitoring\\DataView\\' . ucfirst($view); + if (!class_exists($class)) { + throw new ProgrammingError( + 'DataView %s does not exist', + ucfirst($view) + ); + } + return $class; + } + + /** + * Get a specific query class instance + * + * @param string $name Query name + * @param array $columns Optional column list + * + * @return Icinga\Data\QueryInterface + */ + public function query($name, $columns = null) + { + $class = $this->buildQueryClassName($name); + + if (!class_exists($class)) { + throw new ProgrammingError( + 'Query "%s" does not exist for backend %s', + $name, + $this->getType() + ); + } + + return new $class($this->getResource(), $columns); + } + + /** + * Whether this backend supports the given query + * + * @param string $name Query name to check for + * + * @return bool + */ + public function hasQuery($name) + { + return class_exists($this->buildQueryClassName($name)); + } + + /** + * Query name to class name resolution + * + * @param string $query + * + * @return string + * @throws ProgrammingError When the query does not exist for this backend + */ + protected function buildQueryClassName($query) + { + $parts = preg_split('~\\\~', get_class($this)); + array_pop($parts); + array_push($parts, 'Query', ucfirst($query) . 'Query'); + return implode('\\', $parts); + } +} diff --git a/modules/monitoring/library/Monitoring/DataView/DataView.php b/modules/monitoring/library/Monitoring/DataView/DataView.php index 2c4ec5380..f5d7dafe6 100644 --- a/modules/monitoring/library/Monitoring/DataView/DataView.php +++ b/modules/monitoring/library/Monitoring/DataView/DataView.php @@ -44,8 +44,7 @@ abstract class DataView implements Browsable, Countable, Filterable, Sortable public function __construct(ConnectionInterface $connection, array $columns = null) { $this->connection = $connection; - $queryClass = $connection->getQueryClass($this->getQueryName()); - $this->query = new $queryClass($this->connection->getResource(), $columns); + $this->query = $connection->query($this->getQueryName(), $columns); $this->filter = Filter::matchAll(); $this->init(); } diff --git a/modules/monitoring/library/Monitoring/Object/Host.php b/modules/monitoring/library/Monitoring/Object/Host.php index 483cb2bae..831579a57 100644 --- a/modules/monitoring/library/Monitoring/Object/Host.php +++ b/modules/monitoring/library/Monitoring/Object/Host.php @@ -5,7 +5,7 @@ namespace Icinga\Module\Monitoring\Object; use InvalidArgumentException; -use Icinga\Module\Monitoring\Backend; +use Icinga\Module\Monitoring\Backend\MonitoringBackend; /** * A Icinga host @@ -63,10 +63,10 @@ class Host extends MonitoredObject /** * Create a new host * - * @param Backend $backend Backend to fetch host information from + * @param MonitoringBackend $backend Backend to fetch host information from * @param string $host Host name */ - public function __construct(Backend $backend, $host) + public function __construct(MonitoringBackend $backend, $host) { parent::__construct($backend); $this->host = $host; diff --git a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php index ecd1a9cf6..8e88b861b 100644 --- a/modules/monitoring/library/Monitoring/Object/MonitoredObject.php +++ b/modules/monitoring/library/Monitoring/Object/MonitoredObject.php @@ -7,7 +7,7 @@ namespace Icinga\Module\Monitoring\Object; use InvalidArgumentException; use Icinga\Application\Config; use Icinga\Exception\InvalidPropertyException; -use Icinga\Module\Monitoring\Backend; +use Icinga\Module\Monitoring\Backend\MonitoringBackend; use Icinga\Web\UrlParams; /** @@ -28,7 +28,7 @@ abstract class MonitoredObject /** * Backend to fetch object information from * - * @var Backend + * @var MonitoringBackend */ protected $backend; @@ -119,9 +119,9 @@ abstract class MonitoredObject /** * Create a monitored object, i.e. host or service * - * @param Backend $backend Backend to fetch object information from + * @param MonitoringBackend $backend Backend to fetch object information from */ - public function __construct(Backend $backend) + public function __construct(MonitoringBackend $backend) { $this->backend = $backend; } @@ -480,9 +480,9 @@ abstract class MonitoredObject public static function fromParams(UrlParams $params) { if ($params->has('service') && $params->has('host')) { - return new Service(Backend::createBackend(), $params->get('host'), $params->get('service')); + return new Service(MonitoringBackend::instance(), $params->get('host'), $params->get('service')); } elseif ($params->has('host')) { - return new Host(Backend::createBackend(), $params->get('host')); + return new Host(MonitoringBackend::instance(), $params->get('host')); } return null; } diff --git a/modules/monitoring/library/Monitoring/Object/Service.php b/modules/monitoring/library/Monitoring/Object/Service.php index 28d0338f2..6d5245f0d 100644 --- a/modules/monitoring/library/Monitoring/Object/Service.php +++ b/modules/monitoring/library/Monitoring/Object/Service.php @@ -5,7 +5,7 @@ namespace Icinga\Module\Monitoring\Object; use InvalidArgumentException; -use Icinga\Module\Monitoring\Backend; +use Icinga\Module\Monitoring\Backend\MonitoringBackend; /** * A Icinga service @@ -68,11 +68,11 @@ class Service extends MonitoredObject /** * Create a new service * - * @param Backend $backend Backend to fetch service information from + * @param MonitoringBackend $backend Backend to fetch service information from * @param string $host Host name the service is running on * @param string $service Service name */ - public function __construct(Backend $backend, $host, $service) + public function __construct(MonitoringBackend $backend, $host, $service) { parent::__construct($backend); $this->host = new Host($backend, $host);