Monitoring: Refactor data views (WIP)

refs #4663
This commit is contained in:
Eric Lippmann 2013-09-24 15:26:10 +02:00
parent b47a4d7864
commit b89d61add3
40 changed files with 910 additions and 1044 deletions

View File

@ -38,6 +38,7 @@ use \Icinga\Exception\ProgrammingError;
use \Icinga\Application\DbAdapterFactory; use \Icinga\Application\DbAdapterFactory;
use \Icinga\Exception\ConfigurationError; use \Icinga\Exception\ConfigurationError;
use \Icinga\Util\DateTimeFactory; use \Icinga\Util\DateTimeFactory;
use Icinga\Data\ResourceFactory;
/** /**
* This class bootstraps a thin Icinga application layer * This class bootstraps a thin Icinga application layer
@ -388,10 +389,11 @@ abstract class ApplicationBootstrap
* *
* @return self * @return self
*/ */
protected function setupResourceFactories() protected function setupResourceFactory()
{ {
$config = Config::app('resources'); $config = Config::app('resources');
DbAdapterFactory::setConfig($config); DbAdapterFactory::setConfig($config);
ResourceFactory::setConfig($config);
return $this; return $this;
} }

View File

@ -28,14 +28,14 @@
namespace Icinga\Application\Modules; namespace Icinga\Application\Modules;
use \Icinga\Application\ApplicationBootstrap; use Icinga\Application\ApplicationBootstrap;
use \Icinga\Application\Icinga; use Icinga\Application\Icinga;
use \Icinga\Application\Logger; use Icinga\Application\Logger;
use \Icinga\Data\ArrayDatasource; use Icinga\Data\DataArray\Datasource as ArrayDatasource;
use \Icinga\Data\ArrayQuery; use Icinga\Data\DataArray\Query as ArrayQuery;
use \Icinga\Exception\ConfigurationError; use Icinga\Exception\ConfigurationError;
use \Icinga\Exception\SystemPermissionException; use Icinga\Exception\SystemPermissionException;
use \Icinga\Exception\ProgrammingError; use Icinga\Exception\ProgrammingError;
/** /**
* Module manager that handles detecting, enabling and disabling of modules * Module manager that handles detecting, enabling and disabling of modules

View File

@ -103,7 +103,7 @@ class Web extends ApplicationBootstrap
{ {
return $this->setupConfig() return $this->setupConfig()
->setupErrorHandling() ->setupErrorHandling()
->setupResourceFactories() ->setupResourceFactory()
->setupUser() ->setupUser()
->setupTimezone() ->setupTimezone()
->setupRequest() ->setupRequest()

View File

@ -175,7 +175,6 @@ abstract class AbstractQuery implements QueryInterface
$dir = self::SORT_ASC; $dir = self::SORT_ASC;
} }
} }
$this->order_columns[] = array($col, $dir); $this->order_columns[] = array($col, $dir);
return $this; return $this;
} }

View File

@ -28,14 +28,11 @@
namespace Icinga\Data\Db; namespace Icinga\Data\Db;
use \PDO; use PDO;
use \Zend_Config; use Zend_Config;
use \Zend_Db; use Zend_Db;
use \Zend_Db_Adapter_Abstract; use Icinga\Data\DatasourceInterface;
use \Icinga\Application\DbAdapterFactory; use Icinga\Exception\ConfigurationError;
use \Icinga\Data\DatasourceInterface;
use \Icinga\Exception\ConfigurationError;
use \Icinga\Application\Logger;
/** /**
* Encapsulate database connections and query creation * Encapsulate database connections and query creation
@ -43,25 +40,33 @@ use \Icinga\Application\Logger;
class Connection implements DatasourceInterface class Connection implements DatasourceInterface
{ {
/** /**
* Database connection * Connection config
*
* @var Zend_Db_Adapter_Abstract
*/
protected $db;
/**
* Backend configuration
* *
* @var Zend_Config * @var Zend_Config
*/ */
protected $config; private $config;
/** /**
* Database type * Database type
* *
* @var string * @var string
*/ */
protected $dbType; private $dbType;
private $conn;
private $tablePrefix = '';
private static $genericAdapterOptions = array(
Zend_Db::AUTO_QUOTE_IDENTIFIERS => false,
Zend_Db::CASE_FOLDING => Zend_Db::CASE_LOWER
);
private static $driverOptions = array(
PDO::ATTR_TIMEOUT => 2,
PDO::ATTR_CASE => PDO::CASE_LOWER,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
);
/** /**
* Create a new connection object * Create a new connection object
@ -109,22 +114,69 @@ class Connection implements DatasourceInterface
*/ */
private function connect() private function connect()
{ {
$resourceName = $this->config->get('resource'); $genericAdapterOptions = self::$genericAdapterOptions;
$this->db = DbAdapterFactory::getDbAdapter($resourceName); $driverOptions = self::$driverOptions;
$adapterParamaters = array(
if ($this->db->getConnection() instanceof PDO) { 'host' => $this->config->host,
$this->dbType = $this->db->getConnection()->getAttribute(PDO::ATTR_DRIVER_NAME); 'username' => $this->config->username,
} else { 'password' => $this->config->password,
$this->dbType = strtolower(get_class($this->db->getConnection())); 'dbname' => $this->config->dbname,
'options' => & $genericAdapterOptions,
'driver_options' => & $driverOptions
);
$this->dbType = strtolower($this->config->get('db', 'mysql'));
switch ($this->dbType) {
case 'mysql':
$adapter = 'Pdo_Mysql';
/*
* Set MySQL server SQL modes to behave as closely as possible to Oracle and PostgreSQL. Note that the
* ONLY_FULL_GROUP_BY mode is left on purpose because MySQL requires you to specify all non-aggregate columns
* in the group by list even if the query is grouped by the master table's primary key which is valid
* ANSI SQL though. Further in that case the query plan would suffer if you add more columns to the group by
* list.
*/
$driverOptions[PDO::MYSQL_ATTR_INIT_COMMAND] =
'SET SESSION SQL_MODE=\'STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,'
. 'NO_AUTO_CREATE_USER,ANSI_QUOTES,PIPES_AS_CONCAT,NO_ENGINE_SUBSTITUTION\';';
$adapterParamaters['port'] = $this->config->get('port', 3306);
break;
case 'pgsql':
$adapter = 'Pdo_Pgsql';
$adapterParamaters['port'] = $this->config->get('port', 5432);
break;
// case 'oracle':
// if ($this->dbtype === 'oracle') {
// $attributes['persistent'] = true;
// }
// $this->db = ZfDb::factory($adapter, $attributes);
// if ($adapter === 'Oracle') {
// $this->db->setLobAsString(false);
// }
// break;
default:
throw new ConfigurationError(
sprintf(
'Backend "%s" is not supported', $this->dbType
)
);
} }
$this->db->setFetchMode(Zend_Db::FETCH_OBJ); $this->conn = Zend_Db::factory($adapter, $adapterParamaters);
$this->conn->setFetchMode(Zend_Db::FETCH_OBJ);
if ($this->dbType === null) {
Logger::warn('Could not determine database type');
} }
if ($this->dbType === 'oci') { public function getConnection()
$this->dbType = 'oracle'; {
} return $this->conn;
}
public function getTablePrefix()
{
return $this->tablePrefix;
}
public function setTablePrefix($prefix)
{
$this->tablePrefix = $prefix;
return $this;
} }
} }

View File

@ -40,7 +40,7 @@ class Query extends AbstractQuery
protected function init() protected function init()
{ {
$this->db = $this->ds->getConnection()->getDb(); $this->db = $this->ds->getConnection();
$this->baseQuery = $this->db->select(); $this->baseQuery = $this->db->select();
} }

View File

@ -0,0 +1,38 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Data;
use Icinga\Util\ConfigAwareFactory;
use Icinga\Exception\ConfigurationError;
use Icinga\Data\Db\Connection as DbConnection;
class ResourceFactory implements ConfigAwareFactory
{
/**
* @var Zend_Config
*/
private static $resources;
public static function setConfig($config)
{
self::$resources = $config;
}
public static function createResource($resourceName)
{
if (($resourceConfig = self::$resources->get($resourceName)) === null) {
throw new ConfigurationError('BLUBB?!');
}
switch (strtolower($resourceConfig->type)) {
case 'db':
$resource = new DbConnection($resourceConfig);
break;
default:
throw new ConfigurationError('BLUBB2?!');
}
return $resource;
}
}

View File

@ -18,6 +18,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
*
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* *
@ -39,9 +40,10 @@ use \Icinga\Module\Monitoring\Backend;
use \Icinga\Web\Widget\SortBox; use \Icinga\Web\Widget\SortBox;
use \Icinga\Application\Config as IcingaConfig; use \Icinga\Application\Config as IcingaConfig;
/** use Icinga\Module\Monitoring\DataView\Notification as NotificationView;
* Controller for listing views use Icinga\Module\Monitoring\DataView\Downtime as DowntimeView;
*/ use Icinga\Module\Monitoring\DataView\HostAndServiceStatus as HostAndServiceStatusView;
class Monitoring_ListController extends ActionController class Monitoring_ListController extends ActionController
{ {
/** /**
@ -67,7 +69,7 @@ class Monitoring_ListController extends ActionController
*/ */
public function init() public function init()
{ {
$this->backend = Backend::getInstance($this->_getParam('backend')); $this->backend = Backend::createBackend($this->_getParam('backend'));
$this->view->grapher = Hook::get('grapher'); $this->view->grapher = Hook::get('grapher');
$this->createTabs(); $this->createTabs();
$this->view->activeRowHref = $this->getParam('detail'); $this->view->activeRowHref = $this->getParam('detail');
@ -88,10 +90,9 @@ class Monitoring_ListController extends ActionController
*/ */
public function hostsAction() public function hostsAction()
{ {
Benchmark::measure("hostsAction::query()"); $this->compactView = 'hosts-compact';
$this->compactView = "hosts-compact"; $query = HostAndServiceStatusView::fromRequest(
$this->view->hosts = $this->query( $this->_request,
'status',
array( array(
'host_icon_image', 'host_icon_image',
'host_name', 'host_name',
@ -112,7 +113,8 @@ class Monitoring_ListController extends ActionController
'host_notes_url', 'host_notes_url',
'host_last_comment' 'host_last_comment'
) )
); )->getQuery();
$this->view->hosts = $query->paginate();
$this->setupSortControl(array( $this->setupSortControl(array(
'host_last_check' => 'Last Host Check', 'host_last_check' => 'Last Host Check',
'host_severity' => 'Host Severity', 'host_severity' => 'Host Severity',
@ -121,6 +123,7 @@ class Monitoring_ListController extends ActionController
'host_address' => 'Address', 'host_address' => 'Address',
'host_state' => 'Hard State' 'host_state' => 'Hard State'
)); ));
$this->handleFormatRequest($query);
} }
/** /**
@ -128,9 +131,10 @@ class Monitoring_ListController extends ActionController
*/ */
public function servicesAction() public function servicesAction()
{ {
$this->compactView = "services-compact"; $this->compactView = 'services-compact';
$query = HostAndServiceStatusView::fromRequest(
$this->view->services = $this->query('status', array( $this->_request,
array(
'host_name', 'host_name',
'host_state', 'host_state',
'host_state_type', 'host_state_type',
@ -156,8 +160,9 @@ class Monitoring_ListController extends ActionController
'service_action_url', 'service_action_url',
'service_notes_url', 'service_notes_url',
'service_last_comment' 'service_last_comment'
)); )
)->getQuery();
$this->view->services = $query->paginate();
$this->setupSortControl(array( $this->setupSortControl(array(
'service_last_check' => 'Last Service Check', 'service_last_check' => 'Last Service Check',
'service_severity' => 'Severity', 'service_severity' => 'Severity',
@ -170,6 +175,7 @@ class Monitoring_ListController extends ActionController
'host_address' => 'Host Address', 'host_address' => 'Host Address',
'host_last_check' => 'Last Host Check' 'host_last_check' => 'Last Host Check'
)); ));
$this->handleFormatRequest($query);
} }
/** /**
@ -177,8 +183,9 @@ class Monitoring_ListController extends ActionController
*/ */
public function downtimesAction() public function downtimesAction()
{ {
$this->setDefaultSortColumn('downtime_is_in_effect'); $query = DowntimeView::fromRequest(
$this->view->downtimes = $this->query('downtime', array( $this->_request,
array(
'host_name', 'host_name',
'object_type', 'object_type',
'service_description', 'service_description',
@ -193,8 +200,9 @@ class Monitoring_ListController extends ActionController
'downtime_is_in_effect', 'downtime_is_in_effect',
'downtime_triggered_by_id', 'downtime_triggered_by_id',
'downtime_trigger_time' 'downtime_trigger_time'
)); )
)->getQuery();
$this->view->downtimes = $query->paginate();
$this->setupSortControl(array( $this->setupSortControl(array(
'downtime_is_in_effect' => 'Is In Effect', 'downtime_is_in_effect' => 'Is In Effect',
'object_type' => 'Service/Host', 'object_type' => 'Service/Host',
@ -209,6 +217,7 @@ class Monitoring_ListController extends ActionController
'downtime_internal_downtime_id' => 'Downtime ID', 'downtime_internal_downtime_id' => 'Downtime ID',
'downtime_duration' => 'Duration', 'downtime_duration' => 'Duration',
)); ));
$this->handleFormatRequest($query);
} }
/** /**
@ -216,9 +225,8 @@ class Monitoring_ListController extends ActionController
*/ */
public function notificationsAction() public function notificationsAction()
{ {
$this->setDefaultSortColumn('notification_start_time', 'DESC'); $query = NotificationView::fromRequest(
$this->view->notifications = $this->query( $this->_request,
'notification',
array( array(
'host_name', 'host_name',
'service_description', 'service_description',
@ -229,39 +237,12 @@ class Monitoring_ListController extends ActionController
'notification_information', 'notification_information',
'notification_command' 'notification_command'
) )
); )->getQuery();
$this->view->notifications = $query->paginate();
$this->setupSortControl(array( $this->setupSortControl(array(
'notification_start_time' => 'Notification Start' 'notification_start_time' => 'Notification Start'
)); ));
}
/**
* Create query
*
* @param string $view
* @param array $columns
*
* @return Query
*/
private function query($view, $columns)
{
$extra = preg_split(
'~,~',
$this->_getParam('extracolumns', ''),
-1,
PREG_SPLIT_NO_EMPTY
);
if (empty($extra)) {
$cols = $columns;
} else {
$cols = array_merge($columns, $extra);
}
$this->view->extraColumns = $extra;
$query = $this->backend->select()
->from($view, $cols)
->applyRequest($this->_request);
$this->handleFormatRequest($query); $this->handleFormatRequest($query);
return $query->paginate();
} }
/** /**
@ -278,7 +259,7 @@ class Monitoring_ListController extends ActionController
if ($this->_getParam('format') === 'sql' if ($this->_getParam('format') === 'sql'
&& IcingaConfig::app()->global->get('environment', 'production') === 'development') { && IcingaConfig::app()->global->get('environment', 'production') === 'development') {
echo '<pre>' echo '<pre>'
. htmlspecialchars(wordwrap($query->getQuery()->dump())) . htmlspecialchars(wordwrap($query->dump()))
. '</pre>'; . '</pre>';
exit; exit;
} }
@ -296,19 +277,6 @@ class Monitoring_ListController extends ActionController
} }
} }
/**
* Set the default sort column for this action if none is provided
*
* @param string $column The column to use for sorting
* @param string $dir The direction ('ASC' or 'DESC')
*/
private function setDefaultSortColumn($column, $dir = 'DESC')
{
$this->setParam('sort', $this->getParam('sort', $column));
$this->setParam('dir', $this->getParam('dir', $dir));
}
/** /**
* Create a sort control box at the 'sortControl' view parameter * Create a sort control box at the 'sortControl' view parameter
* *

View File

@ -57,7 +57,7 @@ class Monitoring_ShowController extends ActionController
{ {
$host = $this->_getParam('host'); $host = $this->_getParam('host');
$service = $this->_getParam('service'); $service = $this->_getParam('service');
$this->backend = Backend::getInstance($this->_getParam('backend')); $this->backend = Backend::createBackend($this->_getParam('backend'));
$object = null; $object = null;
// TODO: Do not allow wildcards in names! // TODO: Do not allow wildcards in names!
if ($host !== null) { if ($host !== null) {
@ -70,13 +70,6 @@ class Monitoring_ShowController extends ActionController
} }
} }
$this->backend = Backend::getInstance($this->_getParam('backend'));
if ($service !== null && $service !== '*') {
$this->view->service = $this->backend->fetchService($host, $service, true);
}
if ($host !== null) {
$this->view->host = $this->backend->fetchHost($host, true);
}
$this->view->compact = $this->_getParam('view') === 'compact'; $this->view->compact = $this->_getParam('view') === 'compact';
if ($object === null) { if ($object === null) {
// TODO: Notification, not found // TODO: Notification, not found
@ -92,114 +85,7 @@ class Monitoring_ShowController extends ActionController
*/ */
public function serviceAction() public function serviceAction()
{ {
Benchmark::measure('Entered service action'); $this->view->object->prefetch();
$this->view->active = 'service';
if ($grapher = Hook::get('grapher')) {
if ($grapher->hasGraph(
$this->view->service->host_name,
$this->view->service->service_description
)
) {
$this->view->preview_image = $grapher->getPreviewImage(
$this->view->service->host_name,
$this->view->service->service_description
);
}
}
$this->view->servicegroups = $this->backend->select()
->from(
'servicegroup',
array(
'servicegroup_name',
'servicegroup_alias'
)
)
->where('host_name', $this->view->host->host_name)
->where('service_description', $this->view->service->service_description)
->fetchPairs();
$this->view->contacts = $this->backend->select()
->from(
'contact',
array(
'contact_name',
'contact_alias',
'contact_email',
'contact_pager',
)
)
->where('service_host_name', $this->view->host->host_name)
->where('service_description', $this->view->service->service_description)
->fetchAll();
$this->view->contactgroups = $this->backend->select()
->from(
'contactgroup',
array(
'contactgroup_name',
'contactgroup_alias',
)
)
->where('service_host_name', $this->view->host->host_name)
->where('service_description', $this->view->service->service_description)
->fetchAll();
$this->view->comments = $this->backend->select()
->from(
'comment',
array(
'comment_timestamp',
'comment_author',
'comment_data',
'comment_type',
)
)
->where('service_host_name', $this->view->host->host_name)
->where('service_description', $this->view->service->service_description)
->fetchAll();
$this->view->downtimes = $this->backend->select()
->from(
'downtime',
array(
'host_name',
'service_description',
'downtime_type',
'downtime_author_name',
'downtime_comment_data',
'downtime_is_fixed',
'downtime_duration',
'downtime_scheduled_start_time',
'downtime_scheduled_end_time',
'downtime_actual_start_time',
'downtime_was_started',
'downtime_is_in_effect',
'downtime_internal_downtime_id'
)
)
->where('host_name', $this->view->host->host_name)
->where('service_description', $this->view->service->service_description)
->where('object_type','service')
->fetchAll();
$this->view->customvars = $this->backend->select()
->from(
'customvar',
array(
'varname',
'varvalue'
)
)
->where('varname', '-*PW*,-*PASS*')
->where('host_name', $this->view->host->host_name)
->where('service_description', $this->view->service->service_description)
->where('object_type', 'service')
->fetchPairs();
Benchmark::measure('Service action done');
$object = $this->view->object->prefetch();
} }
/** /**
@ -207,97 +93,6 @@ class Monitoring_ShowController extends ActionController
*/ */
public function hostAction() public function hostAction()
{ {
$this->view->active = 'host';
if ($grapher = Hook::get('grapher')) {
if ($grapher->hasGraph($this->view->host->host_name)) {
$this->view->preview_image = $grapher->getPreviewImage(
$this->view->host->host_name
);
}
}
$this->view->hostgroups = $this->backend->select()
->from(
'hostgroup',
array(
'hostgroup_name',
'hostgroup_alias'
)
)
->where('host_name', $this->view->host->host_name)
->fetchPairs();
$this->view->contacts = $this->backend->select()
->from(
'contact',
array(
'contact_name',
'contact_alias',
'contact_email',
'contact_pager',
)
)
->where('host_name', $this->view->host->host_name)
->fetchAll();
$this->view->contactgroups = $this->backend->select()
->from(
'contactgroup',
array(
'contactgroup_name',
'contactgroup_alias',
)
)
->where('host_name', $this->view->host->host_name)
->fetchAll();
$this->view->comments = $this->backend->select()
->from(
'comment',
array(
'comment_timestamp',
'comment_author',
'comment_data',
'comment_type',
)
)
->where('host_name', $this->view->host->host_name)
->fetchAll();
$this->view->downtimes = $this->backend->select()
->from(
'downtime',
array(
'host_name',
'downtime_type',
'downtime_author_name',
'downtime_comment_data',
'downtime_is_fixed',
'downtime_duration',
'downtime_scheduled_start_time',
'downtime_scheduled_end_time',
'downtime_actual_start_time',
'downtime_was_started',
'downtime_is_in_effect',
'downtime_internal_downtime_id'
)
)
->where('host_name', $this->view->host->host_name)
->where('object_type','host')
->fetchAll();
$this->view->customvars = $this->backend->select()
->from(
'customvar',
array(
'varname',
'varvalue'
)
)
->where('varname', '-*PW*,-*PASS*')
->where('host_name', $this->view->host->host_name)
->where('object_type', 'host')
->fetchPairs();
$this->view->object->prefetch(); $this->view->object->prefetch();
} }
@ -333,27 +128,6 @@ class Monitoring_ShowController extends ActionController
$this->view->preserve = $this->view->history->getAppliedFilter()->toParams(); $this->view->preserve = $this->view->history->getAppliedFilter()->toParams();
} }
/**
* Service overview
*/
public function servicesAction()
{
$this->_setParam('service', null);
// Ugly and slow:
$this->view->services = $this->view->action(
'services',
'list',
'monitoring',
array(
'host_name' => $this->view->host->host_name,
//'sort', 'service_description'
)
);
$this->view->services = $this->view->action('services', 'list', 'monitoring', array(
'view' => 'compact'
));
}
/** /**
* Creating tabs for this controller * Creating tabs for this controller
* @return Tabs * @return Tabs

View File

@ -25,6 +25,8 @@
*/ */
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Module\Monitoring\Object\AbstractObject;
/** /**
* Class Zend_View_Helper_MonitoringFlags * Class Zend_View_Helper_MonitoringFlags
* *
@ -64,7 +66,7 @@ class Zend_View_Helper_MonitoringFlags extends Zend_View_Helper_Abstract
* @param stdClass $object * @param stdClass $object
* @return array * @return array
*/ */
public function monitoringFlags(\stdClass $object) public function monitoringFlags(AbstractObject $object)
{ {
$vars = (array)$object; $vars = (array)$object;
$type = $this->getObjectType($vars); $type = $this->getObjectType($vars);

View File

@ -3,6 +3,8 @@
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
use Icinga\Module\Monitoring\Object\AbstractObject;
/** /**
* Class Zend_View_Helper_MonitoringProperties * Class Zend_View_Helper_MonitoringProperties
*/ */
@ -76,7 +78,7 @@ class Zend_View_Helper_MonitoringProperties extends Zend_View_Helper_Abstract
* @param stdClass $object * @param stdClass $object
* @return mixed * @return mixed
*/ */
private function getObjectType(stdClass $object) private function getObjectType(AbstractObject $object)
{ {
$keys = array_keys(get_object_vars($object)); $keys = array_keys(get_object_vars($object));
$keyParts = explode('_', array_shift($keys), 2); $keyParts = explode('_', array_shift($keys), 2);
@ -89,7 +91,7 @@ class Zend_View_Helper_MonitoringProperties extends Zend_View_Helper_Abstract
* @param $type * @param $type
* @return object * @return object
*/ */
private function dropObjectType(stdClass $object, $type) private function dropObjectType(AbstractObject $object, $type)
{ {
$vars = get_object_vars($object); $vars = get_object_vars($object);
$out = array(); $out = array();
@ -248,7 +250,7 @@ class Zend_View_Helper_MonitoringProperties extends Zend_View_Helper_Abstract
* @param stdClass $object * @param stdClass $object
* @return array * @return array
*/ */
public function monitoringProperties(stdClass $object) public function monitoringProperties(AbstractObject $object)
{ {
$type = $this->getObjectType($object); $type = $this->getObjectType($object);
$object = $this->dropObjectType($object, $type); $object = $this->dropObjectType($object, $type);

View File

@ -22,7 +22,7 @@ function formatDateString($self,$dateString){
</div> </div>
<div> <div>
<?= $this->paginationControl( <?= $this->paginationControl(
$downtimes, $this->downtimes,
null, null,
array( array(
'mixedPagination.phtml', 'mixedPagination.phtml',

View File

@ -1,7 +1,13 @@
<?php <div class="panel panel-default">
$commandParts = preg_split('|!|', $object->check_command); <div class="panel-heading">
$commandName = array_shift($commandParts); {{CHECK_ICON}} <span>Check Command</span>
?> </div>
{{COMMAND_ICON}} <b>Command:</b> <?= $commandName; ?> <div class="panel-body">
<?= $this->commandArguments($object->check_command); ?> <?php
$explodedCommand = explode('!', $this->object->check_command, 2);
array_shift($explodedCommand);
?>
<?= $this->commandArguments($this->object->check_command); ?>
</div>
</div>

View File

@ -1,18 +1,9 @@
<?php if (!empty($object->comments)): ?>
<?php if (! empty($this->comments)): ?>
<? <?
$list = array(); $commets = array();
foreach ($this->comments as $comment) { foreach ($object->comments as $comment) {
if ($this->ticket_pattern) {
$text = preg_replace(
$this->ticket_pattern,
$this->ticket_link,
$this->escape($comment->comment_data)
);
} else {
$text = $this->escape($comment->comment_data); $text = $this->escape($comment->comment_data);
} $commets[] = sprintf(
$list[] = sprintf(
'[%s] %s (%s): %s', '[%s] %s (%s): %s',
$this->escape($comment->comment_author), $this->escape($comment->comment_author),
$this->format()->timeSince($comment->comment_timestamp), $this->format()->timeSince($comment->comment_timestamp),
@ -21,13 +12,12 @@ foreach ($this->comments as $comment) {
); );
} }
?> ?>
<div class="panel"> <div class="panel panel-default ">
<div class="panel-heading"> <div class="panel-heading">
<span>{{COMMENT_ICON}} Comments</span> <span>{{COMMENT_ICON}} Comments</span>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<blockquote> <?= implode('<br />', $list) ?></blockquote> <blockquote> <?= implode('<br />', $commets); ?></blockquote>
</div> </div>
</div> </div>
<?php endif; ?> <?php endif; ?>

View File

@ -1,31 +1,51 @@
<?php if (!empty($object->contacts)): ?>
<?php <?php
if (!empty($this->contacts)) { $contacts = array();
$contactList = array(); foreach ($object->contacts as $contact) {
foreach ($this->contacts as $contact) { $contacts[] = '<a href="'
$contactList[] = '<a href="' . $this->href( . $this->href(
'monitoring/show/contact', 'monitoring/show/contact',
array( array(
'contact_name' => $contact->contact_name 'contact_name' => $contact->contact_name
) )
) . '">' . $contact->contact_alias . '</a>'; )
. '">'
. $contact->contact_alias
. '</a>';
} }
?>
<div class="panel panel-default">
<div class="panel-heading">
{{CONTACT_ICON}} <span>Contacts</span>
</div>
<div class="panel-body">
<?= implode(', ', $contacts); ?>
</div>
</div>
<?php endif; ?>
<?php if (!empty($object->contactgroups)): ?>
echo '<strong>{{CONTACT_ICON}} Contacts:</strong> '; <?php
echo implode(', ', $contactList); $contactgroups = array();
} foreach ($object->contactgroups as $contactgroup) {
$contactgroups[] = '<a href="'
if (!empty($this->contactgroups)) { . $this->href(
$contactGroupList = array();
foreach ($this->contactgroups as $contactgroup) {
$contactGroupList[] = '<a href="' . $this->href(
'monitoring/show/contactgroup', 'monitoring/show/contactgroup',
array( array(
'contactgroup_name' => $contactgroup->contactgroup_name 'contactgroup_name' => $contactgroup->contactgroup_name
) )
) . '">' . $contactgroup->contactgroup_alias . '</a>'; )
} . '">'
echo '<strong>{{CONTACTGROUP_ICON}} Contactgroups:</strong> '; . $contactgroup->contactgroup_alias
echo implode(', ', $contactGroupList); . '</a>';
} }
?> ?>
<div class="panel panel-default">
<div class="panel-heading">
{{CONTACTGROUP_ICON}} <span>Contactgroups</span>
</div>
<div class="panel-body">
<?= implode(', ', $contactgroups); ?>
</div>
</div>
<?php endif; ?>

View File

@ -1,4 +1,4 @@
<?php if (isset($this->customvars) && count($this->customvars)) { ?> <?php if (isset($object->customvars) && count($object->customvars)) { ?>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<span>Customvariables</span> <span>Customvariables</span>
@ -10,7 +10,7 @@
<th>Name</th> <th>Name</th>
<th>Value</th> <th>Value</th>
</tr> </tr>
<?php foreach ($this->customvars as $name => $value) { ?> <?php foreach ($object->customvars as $name => $value) { ?>
<tr> <tr>
<td><?= $this->escape($name) ?></td> <td><?= $this->escape($name) ?></td>
<td><?= $this->escape($value) ?></td> <td><?= $this->escape($value) ?></td>

View File

@ -29,9 +29,8 @@
?> ?>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<span>{{IN_DOWNTIME_ICON}} Downtimes</span> {{IN_DOWNTIME_ICON}}<span>Downtimes</span>
</div> </div>
<div class="panel-body"> <div class="panel-body">
<table> <table>
<tr> <tr>

View File

@ -1,16 +1,9 @@
<?php <div class="panel panel-default">
$object = null; <div class="panel-heading">Heading</div>
if (isset($this->service)) { <div class="panel-body">
$object = $this->service;
} elseif (isset($this->host)) {
$object = $this->host;
}
$flags = $this->monitoringFlags($object);
?>
<table class="table table-condensed"> <table class="table table-condensed">
<?php foreach ($flags as $name => $value): ?> <?php foreach ($this->monitoringFlags($object) as $name => $value): ?>
<tr> <tr>
<th><?= $name; ?></th> <th><?= $name; ?></th>
<td> <td>
@ -23,3 +16,5 @@
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</table> </table>
</div>
</div>

View File

@ -0,0 +1,18 @@
<?php if (!empty($object->hostgroups)): ?>
<?php
$hostgroups = array();
foreach ($object->hostgroups as $name => $alias) {
$hostgroups[] = '<a href="' . $this->href('monitoring/list/hosts', array('hostgroups' => $name)) . '">'
. $alias
. '</a>';
}
?>
<div class="panel panel-default">
<div class="panel-heading">
{{HOSTGROUP_ICON}} <span>Hostgroups</span>
</div>
<div class="panel-body">
<?= implode(', ', $hostgroups); ?>
</div>
</div>
<?php endif; ?>

View File

@ -0,0 +1,10 @@
<?php if ($this->object->perfdata): ?>
<div class="panel panel-default">
<div class="panel-heading">
<span>Perfdata</span>
</div>
<div class="panel-body">
<?= $this->perfdata($this->object->perfdata); ?>
</div>
</div>
<?php endif; ?>

View File

@ -0,0 +1,9 @@
<div class="panel panel-default">
<div class="panel-heading">
<span>Plugin Output</span>
</div>
<div class="panel-body">
<?= $this->pluginOutput($this->object->output); ?>
<?= $this->pluginOutput($this->object->long_output); ?>
</div>
</div>

View File

@ -1,19 +1,15 @@
<?php <div class="panel panel-default">
$object = null; <div class="panel-heading">
<span>Properties</span>
if (isset($this->service)) { </div>
$object = $this->service; <div class="panel-body">
} elseif (isset($this->host)) {
$object = $this->host;
}
$properties = $this->monitoringProperties($object);
?>
<table class="table table-bordered"> <table class="table table-bordered">
<?php foreach ($properties as $label => $value): ?> <?php foreach ($this->monitoringProperties($object) as $label => $value): ?>
<tr> <tr>
<th><?= $label ?></th> <th><?= $label ?></th>
<td><?= $value ?></td> <td><?= $value ?></td>
</tr> </tr>
<?php endforeach; ?> <?php endforeach; ?>
</table> </table>
</div>
</div>

View File

@ -1,12 +1,18 @@
<?php if (!empty($object->servicegroups)): ?>
<?php <?php
$servicegroups = array();
if (empty($object->servicegroups)) return;
$list = array();
foreach ($object->servicegroups as $name => $alias) { foreach ($object->servicegroups as $name => $alias) {
$list[] = '<a href="' . $this->href('monitoring/list/service', array('servicegroups' => $name)) . '">' $servicegroups[] = '<a href="' . $this->href('monitoring/list/service', array('servicegroups' => $name)) . '">'
. $alias . $alias
. '</a>'; . '</a>';
} }
echo '{{SERVICEGROUP_ICON}} <b>Servicegroups:</b> ' . implode(', ', $list) . "<br />\n"; ?>
<div class="panel panel-default">
<div class="panel-heading">
{{SERVICEGROUP_ICON}} <span>Servicegroups</span>
</div>
<div class="panel-body">
<?= implode(', ', $servicegroups); ?>
</div>
</div>
<?php endif; ?>

View File

@ -20,12 +20,7 @@ if (!$this->compact) {
<div> <div>
<?php if ($inlineCommands === true): ?> <?php if ($inlineCommands === true): ?>
<div class="pull-right"> <div class="pull-right">
<?=
$this->monitoringCommands(
($showService === true) ? $this->service : $this->host,
'small'
);
?>
</div> </div>
<?php endif; ?> <?php endif; ?>
@ -33,43 +28,43 @@ if (!$this->compact) {
<tr> <tr>
<td> <td>
{{HOST_ICON}} {{HOST_ICON}}
<?php if ($this->host->host_icon_image): ?> <?php if ($this->object->host_icon_image): ?>
<div> <div>
<img src="<?= $this->host->host_icon_image; ?>" alt="Host image"/> <img src="<?= $this->object->host_icon_image; ?>" alt="Host image"/>
</div> </div>
<?php endif; ?> <?php endif; ?>
<strong> <strong>
<?= $this->escape($this->host->host_name); ?> <?= $this->escape($this->object->host_name); ?>
<?php if ($this->host->host_address && $this->host->host_address !== $this->host->host_name): ?> <?php if ($this->object->host_address && $this->object->host_address !== $this->object->host_name): ?>
(<?= $this->escape($this->host->host_address); ?>) (<?= $this->escape($this->object->host_address); ?>)
<?php endif; ?> <?php endif; ?>
</strong> </strong>
<?php if (isset($this->host->host_alias) && $this->host->host_alias !== $this->host->host_name): ?> <?php if (isset($this->object->host_alias) && $this->object->host_alias !== $this->object->host_name): ?>
<br/> <br/>
<sup>(<?= $this->host->host_alias; ?>)</sup> <sup>(<?= $this->object->host_alias; ?>)</sup>
<?php endif; ?> <?php endif; ?>
</td> </td>
<td <td
<?= $showService ? '' : ' rowspan="2"'; ?> <?= $showService ? '' : ' rowspan="2"'; ?>
<?= $this->util()->getHostStateName($this->host->host_state); ?> <?= $this->util()->getHostStateName($this->object->host_state); ?>
since <?= $this->timeSince($this->host->host_last_state_change); ?> since <?= $this->timeSince($this->object->host_last_state_change); ?>
<?php if ($this->host->host_acknowledged === '1'): ?> <?php if ($this->object->host_acknowledged === '1'): ?>
(Has been acknowledged) (Has been acknowledged)
<?php endif; ?> <?php endif; ?>
</td> </td>
</tr> </tr>
<?php if ($this->host->host_action_url || $this->host->host_notes_url): ?> <?php if ($this->object->host_action_url || $this->object->host_notes_url): ?>
<tr> <tr>
<td rowspan="2"> <td rowspan="2">
<?php if ($this->host->host_action_url): ?> <?php if ($this->object->host_action_url): ?>
{{EXTERNAL_LINK_ICON}} {{EXTERNAL_LINK_ICON}}
<a target="_new" href='<?= $this->host->host_notes_url ?>'>Host actions </a> <a target="_new" href='<?= $this->object->host_notes_url ?>'>Host actions </a>
<?php endif; ?> <?php endif; ?>
<?php if ($this->host->host_notes_url): ?> <?php if ($this->object->host_notes_url): ?>
{{EXTERNAL_LINK_ICON}} {{EXTERNAL_LINK_ICON}}
<a target="_new" href='<?= $this->host->host_notes_url ?>'>Host notes </a> <a target="_new" href='<?= $this->object->host_notes_url ?>'>Host notes </a>
<?php endif; ?> <?php endif; ?>
</td> </td>
</tr> </tr>

View File

@ -1,66 +1,10 @@
<?php <?= $this->render('show/components/pluginoutput.phtml') ?>
$hostgroupLinkList = array(); <?= $this->render('show/components/command.phtml') ?>
if (!empty($this->hostgroups)) {
foreach ($this->hostgroups as $name => $alias) {
$hostgroupLinkList[] = '<a href="' . $this->href(
'monitoring/list/hosts',
array(
'hostgroups' => $name
)
) . '">'.$alias. '</a>';
}
}
?>
<?=
$this->partial(
'show/header.phtml',
array(
'host' => $this->host,
'service' => $this->service,
'tabs' => $this->tabs,
'compact' => $this->compact
)
);
?>
<?= $this->preview_image ?>
<br/>
<div class="panel panel-default">
<div class="panel-heading">
<span>Plugin Output</span>
</div>
<div class="panel-body">
<?= $this->pluginOutput($this->host->host_output); ?>
<?= $this->pluginOutput($this->host->host_long_output); ?>
</div>
</div>
<div class="panel panel-default"> <?= $this->render('show/components/hostgroups.phtml') ?>
<div class="panel-heading">
{{CHECK_ICON}} <span>Check Command</span>
</div>
<div class="panel-body">
<?php
$explodedCommand = explode('!', $this->host->host_check_command, 2);
array_shift($explodedCommand);
?>
<?= $this->commandArguments($this->host->host_check_command); ?>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span>Groups and Contacts</span>
</div>
<div class="panel-body">
<?php if (count($hostgroupLinkList)): ?>
{{HOSTGROUP_ICON}} <strong>Hostgroups:</strong>
<?= implode(' ', $hostgroupLinkList); ?>
<?php endif; ?>
<?= $this->render('show/components/contacts.phtml') ?> <?= $this->render('show/components/contacts.phtml') ?>
</div>
</div>
<?= $this->render('show/components/comments.phtml'); ?> <?= $this->render('show/components/comments.phtml'); ?>
@ -68,40 +12,6 @@ $this->partial(
<?= $this->render('show/components/customvars.phtml'); ?> <?= $this->render('show/components/customvars.phtml'); ?>
<?php if ($this->host->host_perfdata): ?>
<div class="panel panel-default">
<div class="panel-heading">
<span>Perfdata</span>
</div>
<div class="panel-body">
<?= $this->perfdata($this->host->host_perfdata); ?>
</div>
</div>
<?php endif; ?>
<div class="panel panel-default">
<div class="panel-heading">
<span>Flags</span>
</div>
<div class="panel-body">
<?= $this->render('show/components/flags.phtml'); ?> <?= $this->render('show/components/flags.phtml'); ?>
</div>
</div>
<div class="panel panel-default"> <?= $this->render('show/components/perfdata.phtml'); ?>
<div class="panel-heading">
<span>Properties</span>
</div>
<div class="panel-body">
<?= $this->render('show/components/properties.phtml'); ?>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
{{COMMAND_ICON}} <span>Commands</span>
</div>
<div class="panel-body">
<?= $this->monitoringCommands($this->host, 'full'); ?>
</div>
</div>

View File

@ -1,67 +1,10 @@
<?php <?= $this->render('show/components/pluginoutput.phtml') ?>
$servicegroupLinkList = array(); <?= $this->render('show/components/command.phtml') ?>
if (!empty($this->servicegroups)) {
foreach ($this->servicegroups as $name => $alias) {
$servicegroupLinkList[] = '<a href="' . $this->href(
'monitoring/list/services',
array(
'servicegroups' => $name
)
) . '">' . $alias . '</a>';
}
}
?>
<?=
$this->partial(
'show/header.phtml',
array(
'host' => $this->host,
'service' => $this->service,
'tabs' => $this->tabs,
'compact' => $this->compact
)
);
?>
<?= $this->preview_image ?> <?= $this->render('show/components/contacts.phtml'); ?>
<div class="panel panel-default">
<div class="panel-heading">
<span>Plugin output</span>
</div>
<div class="panel-body">
<?= $this->pluginOutput($this->service->service_output); ?>
<?= $this->pluginOutput($this->service->service_long_output); ?>
</div>
</div>
<div class="panel panel-default"> <?= $this->render('show/components/servicegroups.phtml'); ?>
<div class="panel-heading">
{{CHECK_ICON}} <span>Check Command</span>
</div>
<div class="panel-body">
<?php
$explodedCommand = explode('!', $this->service->service_check_command, 2);
echo array_shift($explodedCommand);
?>
<?= $this->commandArguments($this->service->service_check_command); ?>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
{{GROUP_ICON}} <span>Groups and Contacts</span>
</div>
<div class="panel-body">
<?php if (count($servicegroupLinkList)) { ?>
{{SERVICEGROUP_ICON}} <strong>Servicegroups:</strong>
<?= implode(' ', $servicegroupLinkList); ?>
<?php } ?>
<?= $this->render('show/components/contacts.phtml') ?>
</div>
</div>
<?= $this->render('show/components/comments.phtml'); ?> <?= $this->render('show/components/comments.phtml'); ?>
@ -69,40 +12,6 @@ $this->partial(
<?= $this->render('show/components/customvars.phtml'); ?> <?= $this->render('show/components/customvars.phtml'); ?>
<?php if ($this->service->service_perfdata): ?> <?= $this->render('show/components/perfdata.phtml'); ?>
<div class="panel panel-default">
<div class="panel-heading">
<span>Perfdata</span>
</div>
<div class="panel-body">
<?= $this->perfdata($this->service->service_perfdata); ?>
</div>
</div>
<?php endif; ?>
<div class="panel panel-default">
<div class="panel-heading">
<span>Flags</span>
</div>
<div class="panel-body">
<?= $this->render('show/components/flags.phtml'); ?>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<span>Properties</span>
</div>
<div class="panel-body">
<?= $this->render('show/components/properties.phtml'); ?> <?= $this->render('show/components/properties.phtml'); ?>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
{{COMMAND_ICON}} <span>Commands</span>
</div>
<div class="panel-body">
<?= $this->monitoringCommands($this->service, 'full'); ?>
</div>
</div>

View File

@ -1,2 +0,0 @@
<?= $this->render('show/components/header.phtml') ?>
<?= $services ?>

View File

@ -1,88 +1,121 @@
<?php <?php
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}} // {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring; namespace Icinga\Module\Monitoring;
use \Exception; use Zend_config;
use \Icinga\Application\Config as IcingaConfig; use Icinga\Application\Config as IcingaConfig;
use \Icinga\Authentication\Manager as AuthManager; use Icinga\Exception\ConfigurationError;
use Icinga\Data\DatasourceInterface;
use Icinga\Data\ResourceFactory;
use Icinga\Util\ConfigAwareFactory;
/** class Backend implements ConfigAwareFactory, DatasourceInterface
* Container for monitoring backends
*/
class Backend
{ {
/** /**
* Array of backends * Resource config
* *
* @var array * @var Zend_config
*/ */
protected static $instances = array(); private $config;
/** /**
* Array of configuration settings for backends * The resource the backend utilizes
* *
* @var array * @var mixed
*/ */
protected static $backendConfigs; private $resource;
private static $backendInstances = array();
private static $backendConfigs = array();
/** /**
* Locked constructor * Create a new backend from the given resource config
*
* @param Zend_config $config
*/ */
final protected function __construct() public function __construct(Zend_Config $config)
{ {
$this->config = $config;
$this->resource = ResourceFactory::createResource($config->resource);
} }
/** /**
* Test if configuration key exist * Set backend configs
* *
* @param string $name * @param Zend_Config $backendConfigs
*
* @return bool
*/ */
public static function exists($name) public static function setConfig($backendConfigs)
{ {
$configs = self::getBackendConfigs(); foreach ($backendConfigs as $name => $config) {
return array_key_exists($name, $configs); self::$backendConfigs[$name] = $config;
}
} }
/** /**
* Get the first configuration name of all backends * Backend entry point
*
* return self
*/
public function select()
{
return $this;
}
/**
* Create query to retrieve columns and rows from the the given table
*
* @param string $table
* @param array $columns
*
* @return Query
*/
public function from($table, array $columns)
{
$queryClass = '\\Icinga\\Module\\Monitoring\\Backend\\'
. ucfirst($this->config->type)
. '\\Query\\'
. ucfirst($table)
. 'Query';
return new $queryClass($this->resource, $columns);
}
/**
* Get the resource which was created in the constructor
*
* @return mixed
*/
public function getResource()
{
return $this->resource;
}
/**
* Get backend configs
*
* @return Zend_Config
*/
public static function getBackendConfigs()
{
if (empty(self::$backendConfigs)) {
self::setConfig(IcingaConfig::module('monitoring', 'backends'));
}
return self::$backendConfigs;
}
/**
* Retrieve the name of the default backend which is the INI's first entry
* *
* @return string * @return string
* * @throws ConfigurationError When no backend has been configured
* @throws Exception
*/ */
public static function getDefaultName() public static function getDefaultBackendName()
{ {
$configs = self::getBackendConfigs(); $configs = self::getBackendConfigs();
if (empty($configs)) { if (empty($configs)) {
throw new Exception( throw new ConfigurationError(
'Cannot get default backend as no backend has been configured' 'Cannot get default backend as no backend has been configured'
); );
} }
@ -91,77 +124,32 @@ class Backend
} }
/** /**
* Getter for backend configuration with lazy initializing * Create the backend with the given name
* *
* @return array * @param $name
*
* @return Backend
*/ */
public static function getBackendConfigs() public static function createBackend($name)
{ {
if (self::$backendConfigs === null) { if (array_key_exists($name, self::$backendInstances)) {
$resources = IcingaConfig::app('resources'); return self::$backendInstances[$name];
foreach ($resources as $resource) {
}
$backends = IcingaConfig::module('monitoring', 'backends');
foreach ($backends as $name => $config) {
self::$backendConfigs[$name] = $config;
}
} }
return self::$backendConfigs;
}
/**
* Get a backend by name or a default one
*
* @param string $name
*
* @return AbstractBackend
*
* @throws Exception
*/
public static function getBackend($name = null)
{
if (! array_key_exists($name, self::$instances)) {
if ($name === null) { if ($name === null) {
$name = self::getDefaultName(); $name = self::getDefaultBackendName();
} else {
if (!self::exists($name)) {
throw new Exception(
sprintf(
'There is no such backend: "%s"',
$name
)
);
}
} }
$config = self::$backendConfigs[$name]; $config = self::$backendConfigs[$name];
$type = $config->type; self::$backendInstances[$name] = $backend = new self($config);
$type[0] = strtoupper($type[0]); switch (strtolower($config->type)) {
$class = '\\Icinga\\Module\\Monitoring\\Backend\\' . $type; case 'ido':
self::$instances[$name] = new $class($config); if ($backend->getResource()->getDbType() !== 'oracle') {
} $backend->getResource()->setTablePrefix('icinga_');
return self::$instances[$name];
} }
break;
/**
* Get backend by name or by user configuration
*
* @param string $name
*
* @return AbstractBackend
*/
public static function getInstance($name = null)
{
if (array_key_exists($name, self::$instances)) {
return self::$instances[$name];
} else {
if ($name === null) {
// TODO: Remove this, will be chosen by Environment
$name = AuthManager::getInstance()->getSession()->get('backend');
}
return self::getBackend($name);
} }
return $backend;
} }
} }

View File

@ -11,7 +11,7 @@ class AbstractBackend implements DatasourceInterface
{ {
protected $config; protected $config;
public function __construct(Zend_Config $config = null) public function __construct(Zend_Config $config)
{ {
if ($config === null) { if ($config === null) {
// $config = new Zend_Config(array()); ??? // $config = new Zend_Config(array()); ???
@ -25,7 +25,7 @@ class AbstractBackend implements DatasourceInterface
} }
/** /**
* Dummy function for fluent code * Backend entry point
* *
* return self * return self
*/ */

View File

@ -1,64 +0,0 @@
<?php
namespace Icinga\Module\Monitoring\Backend;
use Icinga\Data\Db\Connection;
/**
* This class provides an easy-to-use interface to the IDO database
*
* You should usually not directly use this class but go through Icinga\Module\Monitoring\Backend.
*
* New MySQL indexes:
* <code>
* CREATE INDEX web2_index ON icinga_scheduleddowntime (object_id, is_in_effect);
* CREATE INDEX web2_index ON icinga_comments (object_id);
* CREATE INDEX web2_index ON icinga_objects (object_id, is_active); -- (not sure yet)
* </code>
*
* Other possible (history-related) indexes, still subject to tests:
* CREATE INDEX web2_index ON icinga_statehistory (object_id, state_time DESC);
* CREATE INDEX web2_time ON icinga_statehistory (state_time DESC);
* CREATE INDEX web2_index ON icinga_notifications (object_id, start_time DESC);
* CREATE INDEX web2_start ON icinga_downtimehistory (actual_start_time);
* CREATE INDEX web2_end ON icinga_downtimehistory (actual_end_time);
* CREATE INDEX web2_index ON icinga_commenthistory (object_id, comment_time);
* CREATE INDEX web2_object ON icinga_commenthistory (object_id);
* CREATE INDEX web2_time ON icinga_commenthistory (comment_time DESC);
*
* CREATE INDEX web2_notification_contact ON icinga_contactnotifications (contact_object_id, notification_id);
*
* These should be unique:
* CREATE INDEX web2_index ON icinga_host_contacts (host_id, contact_object_id);
* CREATE INDEX web2_index ON icinga_service_contacts (service_id, contact_object_id);
*
* ...and we should drop a lot's of useless and/or redundant index definitions
*/
class Ido extends AbstractBackend
{
protected $db;
protected $prefix = 'icinga_';
protected function init()
{
$this->db = new Connection($this->config);
if ($this->db->getDbType() === 'oracle') {
$this->prefix = '';
}
}
public function getConnection()
{
return $this->db;
}
/**
* Get our IDO table prefix
*
* return string
*/
public function getPrefix()
{
return $this->prefix;
}
}

View File

@ -39,9 +39,9 @@ abstract class AbstractQuery extends Query
{ {
parent::init(); parent::init();
// TODO: $this->applyDbSpecificWorkarounds // TODO: $this->applyDbSpecificWorkarounds
$this->prefix = $this->ds->getPrefix(); $this->prefix = $this->ds->getTablePrefix();
if ($this->ds->getConnection()->getDbType() === 'oracle') { if ($this->ds->getDbType() === 'oracle') {
$this->object_id = $this->host_id = $this->service_id $this->object_id = $this->host_id = $this->service_id
= $this->hostgroup_id = $this->servicegroup_id = $this->hostgroup_id = $this->servicegroup_id
= $this->contact_id = $this->contactgroup_id = 'id'; // REALLY? = $this->contact_id = $this->contactgroup_id = 'id'; // REALLY?
@ -52,7 +52,7 @@ abstract class AbstractQuery extends Query
} }
} }
} }
if ($this->ds->getConnection()->getDbType() === 'pgsql') { if ($this->ds->getDbType() === 'pgsql') {
foreach ($this->columnMap as $table => & $columns) { foreach ($this->columnMap as $table => & $columns) {
foreach ($columns as $key => & $value) { foreach ($columns as $key => & $value) {
$value = preg_replace('/ COLLATE .+$/', '', $value); $value = preg_replace('/ COLLATE .+$/', '', $value);
@ -115,7 +115,8 @@ abstract class AbstractQuery extends Query
protected function getDefaultColumns() protected function getDefaultColumns()
{ {
$table = array_shift(array_keys($this->columnMap)); reset($this->columnMap);
$table = key($this->columnMap);
return array_keys($this->columnMap[$table]); return array_keys($this->columnMap[$table]);
} }

View File

@ -24,7 +24,7 @@ class NotificationhistoryQuery extends AbstractQuery
//"('[' || cndetails.contacts || '] ' || n.output)" //"('[' || cndetails.contacts || '] ' || n.output)"
// This is one of the db-specific workarounds that could be abstracted // This is one of the db-specific workarounds that could be abstracted
// in a better way: // in a better way:
switch ($this->ds->getConnection()->getDbType()) { switch ($this->ds->getDbType()) {
case 'mysql': case 'mysql':
$concat_contacts = "GROUP_CONCAT(c.alias ORDER BY c.alias SEPARATOR ', ')"; $concat_contacts = "GROUP_CONCAT(c.alias ORDER BY c.alias SEPARATOR ', ')";
break; break;

View File

@ -1,45 +0,0 @@
<?php
/**
* Icinga Livestatus Backend
*
* @package Monitoring
*/
namespace Icinga\Module\Monitoring\Backend;
use Icinga\Protocol\Livestatus\Connection;
/**
* This class provides an easy-to-use interface to the Livestatus socket library
*
* You should usually not directly use this class but go through Icinga\Backend.
*
* @copyright Copyright (c) 2013 Icinga-Web Team <info@icinga.org>
* @author Icinga-Web Team <info@icinga.org>
* @package Icinga\Application
* @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
*/
class Livestatus extends AbstractBackend
{
protected $connection;
/**
* Backend initialization starts here
*
* return void
*/
protected function init()
{
$this->connection = new Connection($this->config->socket);
}
/**
* Get our Livestatus connection
*
* return \Icinga\Protocol\Livestatus\Connection
*/
public function getConnection()
{
return $this->connection;
}
}

View File

@ -1,109 +0,0 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
/**
* This file is part of Icinga 2 Web.
*
* Icinga 2 Web - Head for multiple monitoring backends.
* Copyright (C) 2013 Icinga Development Team
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* @copyright 2013 Icinga Development Team <info@icinga.org>
* @license http://www.gnu.org/licenses/gpl-2.0.txt GPL, version 2
* @author Icinga Development Team <info@icinga.org>
*/
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\Backend;
use Icinga\Protocol\Statusdat as StatusdatProtocol;
/**
* Class Statusdat
* @package Icinga\Backend
*/
class Statusdat extends AbstractBackend
{
/**
* @var null
*/
private $reader = null;
/**
*
*/
public function init()
{
$this->reader = new StatusdatProtocol\Reader($this->config);
}
/**
* @return null
*/
public function getReader()
{
return $this->reader;
}
/**
* @param array $filter
* @param array $flags
* @return mixed
*/
public function listServices($filter = array(), $flags = array())
{
$query = $this->select()->from("servicelist");
return $query->fetchAll();
}
/**
* @param $host
* @return MonitoringObjectList|null
*/
public function fetchHost($host, $fetchAll = false)
{
$objs = & $this->reader->getObjects();
if (!isset($objs["host"][$host])) {
return null;
}
$result = array($objs["host"][$host]);
return new MonitoringObjectList(
$result,
new StatusdatHostView($this->reader)
);
}
/**
* @param $host
* @param $service
* @return MonitoringObjectList|null
*/
public function fetchService($host, $service, $fetchAll = false)
{
$idxName = $host . ";" . $service;
$objs = & $this->reader->getObjects();
if (!isset($objs["service"][$idxName])) {
return null;
}
$result = array($objs["service"][$idxName]);
return new MonitoringObjectList(
$result,
new StatusdatServiceView($this->reader)
);
}
}

View File

@ -0,0 +1,176 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\DataView;
use Icinga\Data\AbstractQuery;
use Icinga\Module\Monitoring\Backend;
use Icinga\Web\Request;
/**
* A read-only view of an underlying Query
*/
abstract class DataView
{
/**
* The query used to populate the view
*
* @var AbstractQuery
*/
private $query;
/**
* Sort in ascending order, default
*/
const SORT_ASC = AbstractQuery::SORT_ASC;
/**
* Sort in reverse order
*/
const SORT_DESC = AbstractQuery::SORT_DESC;
/**
* Create a new view
*
* @param Backend $ds Which backend to query
* @param array $columns Select columns
*/
public function __construct(Backend $ds, array $columns = null)
{
$this->query = $ds->select()->from(static::getTableName(), $columns === null ? $this->getColumns() : $columns);
}
/**
* Get the queried table name
*
* @return string
*/
public static function getTableName()
{
$tableName = explode('\\', get_called_class());
$tableName = strtolower(end($tableName));
return $tableName;
}
/**
* Retrieve columns provided by this view
*
* @return array
*/
abstract public function getColumns();
/**
* Retrieve default sorting rules for particular columns. These involve sort order and potential additional to sort
*
* @return array
*/
abstract public function getSortRules();
public function getFilterColumns()
{
return array();
}
/**
* Create view from request
*
* @param Request $request
* @param array $columns
*
* @return static
*/
public static function fromRequest(Request $request, array $columns = null)
{
$view = new static(Backend::createBackend($request->getParam('backend')), $columns);
$view->filter($request->getParams());
$order = $request->getParam('dir');
if ($order !== null) {
if (strtolower($order) === 'desc') {
$order = self::SORT_DESC;
} else {
$order = self::SORT_ASC;
}
}
$view->sort(
$request->getParam('sort'),
$order
);
return $view;
}
/**
* Filter rows that match all of the given filters. If a filter is not valid, it's silently ignored
*
* @param array $filters
*
* @see isValidFilterColumn()
*/
public function filter(array $filters)
{
foreach ($filters as $column => $filter) {
if ($this->isValidFilterColumn($column)) {
$this->query->where($column, $filter);
}
}
}
/**
* Check whether the given column is a valid filter column, i.e. the view actually provides the column or it's
* a non-queryable filter column
*
* @param string $column
*
* @return bool
*/
protected function isValidFilterColumn($column)
{
return in_array($column, $this->getColumns()) || in_array($column, $this->getFilterColumns());
}
/**
* Sort the rows, according to the specified sort column and order
*
* @param string $column Sort column
* @param int $order Sort order, one of the SORT_ constants
*
* @see DataView::SORT_ASC
* @see DataView::SORT_DESC
*/
public function sort($column = null, $order = null)
{
$sortRules = $this->getSortRules();
if ($column === null) {
$sortColumns = reset($sortRules);
if (!isset($sortColumns['columns'])) {
$sortColumns['columns'] = array(key($sortRules));
}
} else {
if (isset($sortRules[$column])) {
$sortColumns = $sortRules[$column];
if (!isset($sortColumns['columns'])) {
$sortColumns['columns'] = array($column);
}
} else {
$sortColumns = array(
'columns' => array($column),
'order' => $order
);
};
}
$order = $order === null ? (isset($sortColumns['order']) ? $sortColumns['order'] : self::SORT_ASC) : $order;
foreach ($sortColumns['columns'] as $column) {
$this->query->order($column, $order);
}
}
/**
* Return the query which was created in the constructor
*
* @return mixed
*/
public function getQuery()
{
return $this->query;
}
}

View File

@ -0,0 +1,50 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\DataView;
class Downtime extends DataView
{
/**
* Retrieve columns provided by this view
*
* @return array
*/
public function getColumns()
{
return array(
'host_name',
'object_type',
'service_host_name',
'service_description',
'downtime_type',
'downtime_author_name',
'downtime_comment_data',
'downtime_is_fixed',
'downtime_duration',
'downtime_entry_time',
'downtime_scheduled_start_time',
'downtime_scheduled_end_time',
'downtime_was_started',
'downtime_actual_start_time',
'downtime_actual_start_time_usec',
'downtime_is_in_effect',
'downtime_trigger_time',
'downtime_triggered_by_id',
'downtime_internal_downtime_id'
);
}
public function getSortRules()
{
return array(
'downtime_is_in_effect' => array(
'order' => self::SORT_DESC
),
'downtime_actual_start_time' => array(
'order' => self::SORT_DESC
)
);
}
}

View File

@ -0,0 +1,131 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\DataView;
class HostAndServiceStatus extends DataView
{
/**
* Retrieve columns provided by this view
*
* @return array
*/
public function getColumns()
{
return array(
'host_name',
'host_state',
'host_state_type',
'host_last_state_change',
'host_address',
'host_handled',
'service_description',
'service_display_name',
'service_state',
'service_in_downtime',
'service_acknowledged',
'service_handled',
'service_output',
'service_last_state_change',
'service_icon_image',
'service_long_output',
'service_is_flapping',
'service_state_type',
'service_severity',
'service_last_check',
'service_notifications_enabled',
'service_action_url',
'service_notes_url',
'service_last_comment',
'host_icon_image',
'host_acknowledged',
'host_output',
'host_long_output',
'host_in_downtime',
'host_is_flapping',
'host_last_check',
'host_notifications_enabled',
'host_unhandled_service_count',
'host_action_url',
'host_notes_url',
'host_last_comment',
'host',
'host_display_name',
'host_alias',
'host_ipv4',
// 'host_problems',
'host_severity',
'host_perfdata',
'host_does_active_checks',
'host_accepts_passive_checks',
'host_last_hard_state',
'host_last_hard_state_change',
'host_last_time_up',
'host_last_time_down',
'host_last_time_unreachable',
'service',
// 'current_state',
'service_hard_state',
'service_perfdata',
'service_does_active_checks',
'service_accepts_passive_checks',
'service_last_hard_state',
'service_last_hard_state_change',
'service_last_time_ok',
'service_last_time_warning',
'service_last_time_critical',
'service_last_time_unknown',
// 'object_type',
// 'problems',
// 'handled',
// 'severity'
);
}
public static function getTableName()
{
return 'status';
}
public function getSortRules()
{
return array(
'host_name' => array(
'order' => self::SORT_ASC
),
'host_address' => array(
'columns' => array(
'host_ipv4',
'service_description'
),
'order' => self::SORT_ASC
),
'host_last_state_change' => array(
'order' => self::SORT_ASC
),
'host_severity' => array(
'columns' => array(
'host_severity',
'host_last_state_change',
),
'order' => self::SORT_ASC
)
);
}
public function getFilterColumns()
{
return array('hostgroups', 'servicegroups');
}
protected function isValidFilterColumn($column)
{
if ($column[0] === '_'
&& preg_match('/^_(?:host|service)_/', $column)
) {
return true;
}
return parent::isValidFilterColumn($column);
}
}

View File

@ -0,0 +1,41 @@
<?php
// {{{ICINGA_LICENSE_HEADER}}}
// {{{ICINGA_LICENSE_HEADER}}}
namespace Icinga\Module\Monitoring\DataView;
class Notification extends DataView
{
/**
* Retrieve columns provided by this view
*
* @return array
*/
public function getColumns()
{
return array(
'host_name',
'service_description',
'notification_type',
'notification_reason',
'notification_start_time',
'notification_contact',
'notification_information',
'notification_command'
);
}
public function getSortRules()
{
return array(
'notification_start_time' => array(
'order' => self::SORT_DESC
)
);
}
public function getTableName()
{
}
}

View File

@ -3,7 +3,7 @@
namespace Icinga\Module\Monitoring\Object; namespace Icinga\Module\Monitoring\Object;
use Icinga\Data\AbstractQuery as Query; use Icinga\Data\AbstractQuery as Query;
use \Icinga\Module\Monitoring\Backend\AbstractBackend; use \Icinga\Module\Monitoring\Backend;
abstract class AbstractObject abstract class AbstractObject
{ {
@ -26,7 +26,7 @@ abstract class AbstractObject
// 'comments' => null, // 'comments' => null,
); );
public function __construct(AbstractBackend $backend, $name1, $name2 = null) public function __construct(Backend $backend, $name1, $name2 = null)
{ {
$this->backend = $backend; $this->backend = $backend;
$this->name1 = $name1; $this->name1 = $name1;
@ -34,7 +34,7 @@ abstract class AbstractObject
$this->properties = (array) $this->fetchObject(); $this->properties = (array) $this->fetchObject();
} }
public static function fetch(AbstractBackend $backend, $name1, $name2 = null) public static function fetch(Backend $backend, $name1, $name2 = null)
{ {
return new static($backend, $name1, $name2); return new static($backend, $name1, $name2);
} }

View File

@ -31,8 +31,7 @@ class Service extends AbstractObject
->fetchContacts() ->fetchContacts()
->fetchContactgroups() ->fetchContactgroups()
->fetchCustomvars() ->fetchCustomvars()
->fetchComments() ->fetchComments();
;
} }
protected function fetchObject() protected function fetchObject()