diff --git a/modules/monitoring/application/controllers/CommandController.php b/modules/monitoring/application/controllers/CommandController.php
new file mode 100644
index 000000000..1b04f8cd9
--- /dev/null
+++ b/modules/monitoring/application/controllers/CommandController.php
@@ -0,0 +1,213 @@
+_request->getPost($name, false);
+ if ($value === false)
+ throw new IcingaException\MissingParameterException("Missing parameter $name");
+ return $value;
+ }
+
+ public function init()
+ {
+ if (!$this->_request->isPost()) {
+ $this->_response->clearBody();
+ $this->_response->clearHeaders();
+ $this->_response->setHttpResponseCode(405);
+ $this->_redirect("/");
+ }
+ if (!$this->hasValidToken())
+ throw new Exception("Invalid token given", 401);
+ $this->_helper->viewRenderer->setNoRender(true);
+ $this->_helper->layout()->disableLayout();
+ $targets = Icinga\Application\Config::getInstance()->getModuleConfig("instances", "monitoring");
+ $instance = $this->_getParam("instance");
+ if ($instance && isset($targets[$instance])) {
+ $this->target = new \Icinga\Protocol\Commandpipe\CommandPipe($targets[$instance]);
+ } else {
+ foreach ($targets as $target) {
+ $this->target = new \Icinga\Protocol\Commandpipe\CommandPipe($target);
+ break;
+ }
+ }
+ }
+
+ private function selectCommandTargets()
+ {
+ $hostname = $this->_getParam("hosts");
+ $servicename = $this->_getParam("services");
+ $target = "hostlist";
+ $filter = array();
+ if (!$hostname && !$servicename) {
+ throw new IcingaException\MissingParameterException("Missing host and service definition");
+ }
+ if ($hostname) {
+ $filter["hostname"] = explode(";", $hostname);
+ }
+ if ($servicename) {
+ $filter["servicedescription"] = explode(";", $servicename);
+ $target = "servicelist";
+ }
+
+ return $this->backend = Icinga\Backend::getInstance()
+ ->select()
+ ->from($target)
+ ->applyFilters($filter)
+ ->fetchAll();
+ }
+
+ public function sendReschedule()
+ {
+ $forced = (trim($this->_getParam("forced"), false) === "true");
+ $time = $this->_request->getPost("time", false);
+ $childs = $this->_request->getPost("withChilds", false);
+ if ($forced) {
+ $this->target->scheduleForcedCheck($this->selectCommandTargets(), $time, $childs);
+ } else {
+ $this->target->scheduleCheck($this->selectCommandTargets(), $time, $childs);
+ }
+ }
+
+ public function sendAcknowledge()
+ {
+ $author = "AUTHOR"; //@TODO: get from auth backend
+ $comment = $this->getMandatoryParameter("comment");
+ $persistent = $this->_request->getPost("persistent", false) == "true";
+ $commentObj = new \Icinga\Protocol\Commandpipe\Comment($author, $comment, $persistent);
+
+ $notify = $this->_request->getPost("notify", false) == "true";
+ $sticky = $this->_request->getPost("sticky", false) == "true";
+ $expire = intval($this->_request->getPost("expire", false));
+ if (!$expire) {
+ $expire = -1;
+ }
+ $ack = new \Icinga\Protocol\Commandpipe\Acknowledgement($commentObj, $notify, $expire, $sticky);
+ $this->target->acknowledge($this->selectCommandTargets(), $ack);
+ }
+
+ public function sendScheduledowntime()
+ {
+ $author = "AUTHOR"; //@TODO: get from auth backend
+ $comment = $this->getMandatoryParameter("comment");
+ $persistent = $this->_request->getPost("persistent", false) == "true";
+ $commentObj = new \Icinga\Protocol\Commandpipe\Comment($author, $comment, $persistent);
+
+ $start = intval($this->_request->getPost("start", time()));
+ $end = intval($this->getMandatoryParameter("end"));
+ $duration = $this->_request->getPost("duration", false);
+ if ($duration !== false) {
+ $duration = intval($duration);
+ }
+ $downtime = new \Icinga\Protocol\Commandpipe\Downtime($start, $end, $commentObj, $duration);
+
+ $this->target->scheduleDowntime($this->selectCommandTargets(), $downtime);
+ }
+
+ public function sendActivechecks()
+ {
+ if ($this->getMandatoryParameter("enable")) {
+ $this->target->enableActiveChecks($this->selectCommandTargets());
+ } else {
+ $this->target->disableActiveChecks($this->selectCommandTargets());
+ }
+ }
+
+ public function sendPassivechecks()
+ {
+ if ($this->getMandatoryParameter("enable")) {
+ $this->target->enablePassiveChecks($this->selectCommandTargets());
+ } else {
+ $this->target->disablePassiveChecks($this->selectCommandTargets());
+ }
+ }
+
+ public function sendFlappingdetection()
+ {
+ if ($this->getMandatoryParameter("enable")) {
+ $this->target->enableFlappingDetection($this->selectCommandTargets());
+ } else {
+ $this->target->disableFlappingDetection($this->selectCommandTargets());
+ }
+ }
+
+ public function sendComment()
+ {
+ $author = "AUTHOR"; //@TODO: get from auth backend
+ $comment = $this->getMandatoryParameter("comment");
+ $persistent = $this->_request->getPost("persistent", false) == "true";
+ $commentObj = new \Icinga\Protocol\Commandpipe\Comment($author, $comment, $persistent);
+ $this->target->addComment($this->selectCommandTargets(), $commentObj);
+ }
+
+ public function sendDeletecomment()
+ {
+ if ($this->_request->getPost("comments")) {
+ $comments = array();
+ foreach ($this->_request->getPost("comments") as $id => $content) {
+ $comment = new StdClass();
+ $comment->comment_id = $id;
+ $value = explode(";", $content, 2);
+ $comment->host_name = $value[0];
+ if (isset($value[1])) {
+ $comment->service_description = $value[1];
+ }
+ $comments[] = $comment;
+ }
+ $this->target->removeComment($comments);
+ } else {
+ $this->target->removeComment($this->selectCommandTargets());
+ }
+ }
+
+ public function sendRestartIcinga()
+ {
+ $this->target->restartIcinga();
+ }
+
+ public function sendDeletedowntime()
+ {
+ if ($this->_request->getPost("downtimes")) {
+ $downtimes = array();
+ foreach ($this->_request->getPost("comments") as $id => $content) {
+ $downtime = new StdClass();
+ $downtime->downtime_id = $id;
+ $value = explode(";", $content, 2);
+ $downtime->host_name = $value[0];
+ if (isset($value[1])) {
+ $downtime->service_description = $value[1];
+ }
+ $downtimes[] = $downtime;
+ }
+ $this->target->removeDowntime($downtimes);
+ } else {
+ $this->target->removeDowntime($this->selectCommandTargets());
+ }
+ }
+
+
+ public function __call($method, $args)
+ {
+ $command = substr($method, 0, -6);
+ if ('Action' == substr($method, -6)) {
+ $command[0] = strtoupper($command[0]);
+ if (method_exists($this, "send$command")) {
+ return $this->{"send$command"}();
+ }
+ throw new Exception("Invalid command $command", 404);
+ }
+
+ throw new BadMethodCallException("Call to undefined method $method");
+
+ }
+
+
+}
diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php
new file mode 100644
index 000000000..ac5108eb9
--- /dev/null
+++ b/modules/monitoring/application/controllers/ListController.php
@@ -0,0 +1,208 @@
+view->tabs = $this->getTabs()
+ ->activate($this->action_name)
+ ->enableSpecialActions();
+ $this->backend = Backend::getInstance($this->_getParam('backend'));
+ $this->view->grapher = Hook::get('grapher');
+ }
+
+ public function hostsAction()
+ {
+ $this->view->hosts = $this->backend->select()->from('status', array(
+ 'host_name',
+ 'host_state',
+ 'host_acknowledged',
+ 'host_output',
+ 'host_in_downtime',
+ 'host_handled',
+ 'host_last_state_change'
+ ));
+
+ if ($search = $this->_getParam('search')) {
+ $this->_setParam('search', null);
+ if (strpos($search, '=') === false) {
+ $this->_setParam('host_name', $search);
+ } else {
+ list($key, $val) = preg_split('~\s*=\s*~', $search, 2);
+ if ($this->view->hosts->isValidFilterColumn($key) || $key[0] === '_') {
+ $this->_setParam($key, $val);
+ }
+ }
+ }
+ $this->view->hosts->applyRequest($this->_request);
+$this->view->hosts->getQuery()->group('hs.host_object_id');
+ if ($this->_getParam('dump') === 'sql') {
+ echo '
' . htmlspecialchars(wordwrap($this->view->hosts->getQuery()->dump())) . '
';
+ exit;
+ }
+
+ // TODO: Get rid of "preserve"
+ $preserve = array();
+ if ($this->_getParam('sort')) {
+ $preserve['sort'] = $this->view->sort = $this->_getParam('sort');
+ }
+ if ($this->_getParam('backend')) {
+ $preserve['backend'] = $this->_getParam('backend');
+ }
+ $this->view->preserve = $preserve;
+
+ if ($this->_getParam('view') === 'compact') {
+ $this->_helper->viewRenderer('hosts_compact');
+ }
+ }
+
+ public function servicesAction()
+ {
+ $state_type = $this->_getParam('_statetype', 'soft');
+ if ($state_type = 'soft') {
+ $state_column = 'service_state';
+ $state_change_column = 'service_last_state_change';
+ } else {
+ $state_column = 'service_hard_state';
+ $state_change_column = 'service_last_hard_state_change';
+ }
+ $this->view->services = $this->backend->select()
+ ->from('status', array(
+ 'host_name',
+ 'service_description',
+ 'service_state' => $state_column,
+ 'service_in_downtime',
+ 'service_acknowledged',
+ 'service_handled',
+ 'service_output',
+ 'service_last_state_change' => $state_change_column
+ ));
+
+ if ($search = $this->_getParam('search')) {
+ $this->_setParam('search', null);
+ if (strpos($search, '=') === false) {
+ $this->_setParam('service_description', $search);
+ } else {
+ list($key, $val) = preg_split('~\s*=\s*~', $search, 2);
+ if ($this->view->services->isValidFilterColumn($key) || $key[0] === '_') {
+ $this->_setParam($key, $val);
+ }
+ }
+ }
+
+ $this->view->services->applyRequest($this->_request);
+ if ($this->_getParam('dump') === 'sql') {
+ echo '' . htmlspecialchars(wordwrap($this->view->services->getQuery()->dump())) . '
';
+ exit;
+ }
+
+ $preserve = array();
+ if ($this->_getParam('sort')) {
+ $preserve['sort'] = $this->view->sort = $this->_getParam('sort');
+
+ }
+ if ($this->_getParam('backend')) {
+ $preserve['backend'] = $this->_getParam('backend');
+ }
+ $this->view->preserve = $preserve;
+ if ($this->_getParam('view') == 'compact') {
+ $this->_helper->viewRenderer('services-compact');
+ }
+ }
+
+ public function hostgroupsAction()
+ {
+ $this->view->hostgroups = $this->backend->select()
+ ->from('hostgroup', array(
+ 'hostgroup_name',
+ 'hostgroup_alias',
+ ))->applyRequest($this->_request);
+ }
+
+ public function servicegroupsAction()
+ {
+ $this->view->servicegroups = $this->backend->select()
+ ->from('servicegroup', array(
+ 'servicegroup_name',
+ 'servicegroup_alias',
+ ))->applyRequest($this->_request);
+ }
+
+ public function contactgroupsAction()
+ {
+ $this->view->contactgroups = $this->backend->select()
+ ->from('contactgroup', array(
+ 'contactgroup_name',
+ 'contactgroup_alias',
+ ))->applyRequest($this->_request);
+ }
+
+ public function contactsAction()
+ {
+ $this->view->contacts = $this->backend->select()
+ ->from('contact', array(
+ 'contact_name',
+ 'contact_alias',
+ 'contact_email',
+ 'contact_pager'
+ ))->applyRequest($this->_request);
+ }
+
+ // TODO: Search helper playground
+ public function searchAction()
+ {
+ $data = array(
+ 'service_description',
+ 'service_state',
+ 'service_acknowledged',
+ 'service_handled',
+ 'service_output',
+ // '_host_satellite',
+ 'service_last_state_change'
+ );
+ echo json_encode($data);
+ exit;
+ }
+
+ protected function getTabs()
+ {
+ $tabs = $this->widget('tabs');
+ $tabs->add('services', array(
+ 'title' => 'Services',
+ 'icon' => 'img/classic/service.png',
+ 'url' => 'monitoring/list/services',
+ ));
+ $tabs->add('hosts', array(
+ 'title' => 'Hosts',
+ 'icon' => 'img/classic/server.png',
+ 'url' => 'monitoring/list/hosts',
+ ));
+ $tabs->add('hostgroups', array(
+ 'title' => 'Hostgroups',
+ 'icon' => 'img/classic/servers-network.png',
+ 'url' => 'monitoring/list/hostgroups',
+ ));
+ $tabs->add('servicegroups', array(
+ 'title' => 'Servicegroups',
+ 'icon' => 'img/classic/servers-network.png',
+ 'url' => 'monitoring/list/servicegroups',
+ ));
+ $tabs->add('contacts', array(
+ 'title' => 'Contacts',
+ 'icon' => 'img/classic/servers-network.png',
+ 'url' => 'monitoring/list/contacts',
+ ));
+ $tabs->add('contactgroups', array(
+ 'title' => 'Contactgroups',
+ 'icon' => 'img/classic/servers-network.png',
+ 'url' => 'monitoring/list/contactgroups',
+ ));
+ return $tabs;
+ }
+}
diff --git a/modules/monitoring/application/controllers/ShowController.php b/modules/monitoring/application/controllers/ShowController.php
new file mode 100644
index 000000000..66e7e103d
--- /dev/null
+++ b/modules/monitoring/application/controllers/ShowController.php
@@ -0,0 +1,296 @@
+_getParam('host');
+ $service = $this->_getParam('service');
+ if ($host !== null) {
+ // TODO: $this->assertPermission('host/read', $host);
+ }
+ if ($service !== null) {
+ // TODO: $this->assertPermission('service/read', $service);
+ }
+ // TODO: don't allow wildcards
+
+ $this->backend = Backend::getInstance($this->_getParam('backend'));
+ if ($service !== null && $service !== '*') {
+ $this->view->service = $this->backend->fetchService($host, $service);
+ }
+ if ($host !== null) {
+ $this->view->host = $this->backend->fetchHost($host);
+ }
+ $this->view->compact = $this->_getParam('view') === 'compact';
+ $this->view->tabs = $this->createTabs();
+
+ // If ticket hook:
+ $params = array();
+ if ($host !== null) {
+ $params['host'] = $this->view->host->host_name;
+ }
+ if ($service !== null) {
+ $params['service'] = $this->view->service->service_description;
+ }
+ if (Hook::has('ticket')) {
+ $params['ticket'] = '__ID__';
+ $this->view->ticket_link = preg_replace(
+ '~__ID__~',
+ '\$1',
+ $this->view->qlink('#__ID__',
+ 'monitoring/show/ticket',
+ $params
+ )
+ );
+ // TODO: Global ticket pattern config (or per environment)
+ $this->view->ticket_pattern = '~#(\d{4,6})~';
+ }
+ }
+
+ public function serviceAction()
+ {
+ Benchmark::measure('Entered service action');
+ $this->view->active = 'service';
+ $this->view->tabs->activate('service')->enableSpecialActions();
+
+ if ($grapher = Hook::get('grapher')) {
+ if ($grapher->hasGraph(
+ $this->view->host->host_name,
+ $this->view->service->service_description
+ )) {
+ $this->view->preview_image = $grapher->getPreviewImage(
+ $this->view->host->host_name,
+ $this->view->service->service_description
+ );
+ }
+ }
+
+ $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->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');
+ }
+
+ public function hostAction()
+ {
+ $this->view->active = 'host';
+ $this->view->tabs->activate('host')->enableSpecialActions();
+
+ 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->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();
+ }
+
+ public function historyAction()
+ {
+ if ($this->view->host) {
+ $this->view->tabs->activate('history')->enableSpecialActions();
+ }
+ $this->view->history = $this->backend->select()
+ ->from('eventHistory', array(
+ 'object_type',
+ 'host_name',
+ 'service_description',
+ 'timestamp',
+ 'state',
+ 'attempt',
+ 'max_attempts',
+ 'output',
+ 'type'
+ ))->applyRequest($this->_request);
+
+
+ $this->view->preserve = $this->view->history->getAppliedFilter()->toParams();
+ if ($this->_getParam('dump') === 'sql') {
+ echo '' . htmlspecialchars($this->view->history->getQuery()->dump()) . '
';
+ exit;
+ }
+ if ($this->_getParam('sort')) {
+ $this->view->preserve['sort'] = $this->_getParam('sort');
+ }
+ }
+
+ public function servicesAction()
+ {
+ // Ugly and slow:
+ $this->view->services = $this->view->action('services', 'list', 'monitoring', array(
+ 'host_name' => $this->view->host->host_name,
+ //'sort', 'service_description'
+ ));
+ }
+
+ public function ticketAction()
+ {
+ $this->view->tabs->activate('ticket')->enableSpecialActions();
+ $id = $this->_getParam('ticket');
+ // Still hardcoded, TODO: get URL:
+ if (Hook::has('ticket')) {
+ $ticketModule = 'rt';
+ $this->render();
+ $this->_forward('ticket', 'show', $ticketModule, array(
+ 'id' => $id
+ ));
+ }
+ }
+
+ protected function createTabs()
+ {
+ $tabs = $this->widget('tabs');
+ if ( ! $this->view->host) {
+ return $tabs;
+ }
+ $params = array(
+ 'host' => $this->view->host->host_name,
+ );
+ if ($backend = $this->_getParam('backend')) {
+ $params['backend'] = $backend;
+ }
+ if (isset($this->view->service)) {
+ $params['service'] = $this->view->service->service_description;
+ $hostParams = $params + array('active' => 'host');
+ } else {
+ $hostParams = $params;
+ }
+ $tabs->add('host', array(
+ 'title' => 'Host',
+ 'icon' => 'img/classic/server.png',
+ 'url' => 'monitoring/show/host',
+ 'urlParams' => $hostParams,
+ ));
+ $tabs->add('services', array(
+ 'title' => 'Services',
+ 'icon' => 'img/classic/service.png',
+ 'url' => 'monitoring/show/services',
+ 'urlParams' => $params,
+ ));
+ if (isset($params['service'])) {
+ $tabs->add('service', array(
+ 'title' => 'Service',
+ 'icon' => 'img/classic/service.png',
+ 'url' => 'monitoring/show/service',
+ 'urlParams' => $params,
+ ));
+ }
+ $tabs->add('history', array(
+ 'title' => 'History',
+ 'icon' => 'img/classic/history.gif',
+ 'url' => 'monitoring/show/history',
+ 'urlParams' => $params,
+ ));
+ if ($this->action_name === 'ticket') {
+ $tabs->add('ticket', array(
+ 'title' => 'Ticket',
+ 'icon' => 'img/classic/ticket.gif',
+ 'url' => 'monitoring/show/ticket',
+ 'urlParams' => $params + array('ticket' => $this->_getParam('ticket')),
+ ));
+ }
+/*
+ $tabs->add('contacts', array(
+ 'title' => 'Contacts',
+ 'icon' => 'img/classic/customer.png',
+ 'url' => 'monitoring/detail/contacts',
+ 'urlParams' => $params,
+ ));
+*/
+ // TODO: Inventory 'img/classic/facts.gif'
+ // Ticket 'img/classic/ticket.gif'
+ // Customer 'img/classic/customer.png'
+ return $tabs;
+ }
+}
diff --git a/modules/monitoring/application/controllers/SummaryController.php b/modules/monitoring/application/controllers/SummaryController.php
new file mode 100644
index 000000000..fdda65a22
--- /dev/null
+++ b/modules/monitoring/application/controllers/SummaryController.php
@@ -0,0 +1,70 @@
+backend = Backend::getInstance($this->_getParam('backend'));
+ $this->view->compact = $this->_getParam('view') === 'compact';
+ $this->view->tabs = $this->getTabs();
+ }
+
+ protected function getTabs()
+ {
+ $tabs = $this->widget('tabs');
+ $tabs->add('hostgroup', array(
+ 'title' => 'Hostgroups',
+ 'url' => 'monitoring/summary/group',
+ 'urlParams' => array('by' => 'hostgroup'),
+ ));
+ $tabs->add('servicegroup', array(
+ 'title' => 'Servicegroups',
+ 'url' => 'monitoring/summary/group',
+ 'urlParams' => array('by' => 'servicegroup'),
+ ));
+ $tabs->activate($this->_getParam('by', 'hostgroup'));
+ return $tabs;
+ }
+
+ public function historyAction()
+ {
+ $this->_helper->viewRenderer('history');
+ }
+
+ public function groupAction()
+ {
+ if ($this->_getParam('by') === 'servicegroup') {
+ $view = 'servicegroupsummary';
+ } else {
+ $view = 'hostgroupsummary';
+ }
+ if (! $this->backend->hasView($view)) {
+ $this->view->backend = $this->backend;
+ $this->view->view_name = $view;
+ $this->_helper->viewRenderer('backend-is-missing');
+ return;
+ }
+
+ $this->view->preserve = array(
+ 'problems' => $this->_getParam('problems') ? 'true' : 'false',
+ 'search' => $this->_getParam('search')
+ );
+ $query = $this->backend->select()->from($view);
+ $query->where('problems', $this->_getParam('problems') ? 'true' : 'false');
+ //$query->where('ss.current_state > 0');
+ $query->where('search', $this->_getParam('search'));
+
+ // echo '' . $query->dump() . '
'; exit;
+ $this->view->summary = $query->paginate();
+
+ }
+
+}
+
diff --git a/modules/monitoring/application/views/helpers/CommandArguments.php b/modules/monitoring/application/views/helpers/CommandArguments.php
new file mode 100644
index 000000000..c0dfc5cca
--- /dev/null
+++ b/modules/monitoring/application/views/helpers/CommandArguments.php
@@ -0,0 +1,19 @@
+%s: %s\n";
+ for ($i = 1; $i < count($parts); $i++) {
+ $parts[$i] = sprintf($row, '$ARG' . $i . '$', $parts[$i]);
+ }
+ array_shift($parts);
+ return "\n" . implode("\n", $parts) . "
\n";
+ }
+}
+
diff --git a/modules/monitoring/application/views/helpers/MonitoringState.php b/modules/monitoring/application/views/helpers/MonitoringState.php
new file mode 100644
index 000000000..0adf1135e
--- /dev/null
+++ b/modules/monitoring/application/views/helpers/MonitoringState.php
@@ -0,0 +1,19 @@
+ 'pending', null => 'pending');
+ private $hoststates = array('up', 'down', 'unreachable', 99 => 'pending', null => 'pending');
+
+ public function monitoringState($object, $type = 'service') {
+
+ if ($type === 'service') {
+ return $this->servicestates[$object->service_state];
+ } else if ($type === 'host') {
+ return $this->hoststates[$object->host_state];
+ }
+ }
+
+}
+
diff --git a/modules/monitoring/application/views/helpers/Perfdata.php b/modules/monitoring/application/views/helpers/Perfdata.php
new file mode 100644
index 000000000..f7ae4672f
--- /dev/null
+++ b/modules/monitoring/application/views/helpers/Perfdata.php
@@ -0,0 +1,84 @@
+getAll();
+ $perfdata = preg_replace('~\'([^\']+)\'~e', "str_replace(' ', '\'', '$1')", $perfdata);
+ $parts = preg_split('~\s+~', $perfdata, -1, PREG_SPLIT_NO_EMPTY);
+
+ $result = '';
+ if ($compact === true) {
+ $compact = 5;
+ }
+ if ($compact && count($parts) > $compact) {
+ $parts = array_slice($parts, 0, $compact);
+ }
+ foreach ($parts as $part) {
+ if (strpos($part, '=') === false) continue;
+ list($name, $vals) = preg_split('~=~', $part, 2);
+ $name = str_replace("'", ' ', $name);
+ $parts = preg_split('~;~', $vals, 5);
+ while (count($parts) < 5) $parts[] = null;
+ list($val, $warn, $crit, $min, $max) = $parts;
+
+ $unit = '';
+ if (preg_match('~^([\d+\.]+)([^\d]+)$~', $val, $m)) {
+ $unit = $m[2];
+ $val = $m[1];
+ } else {
+ continue;
+ }
+ if ($unit == 'c') continue; // Counter pie graphs are not useful
+ if ($unit == '%') {
+ if (! $min ) $min = 0;
+ if (! $max) $max = 100;
+ } else {
+ if (! $max && $crit > 0) $max = $crit;
+ //return '';
+ }
+ if (! $max) continue;
+ $green = 0;
+ $orange = 0;
+ $red = 0;
+ $gray = $max - $val;
+ if ($val < $warn) $green = $val;
+ elseif ($val < $crit) $orange = $val;
+ else $red = $val;
+ if ($compact) {
+ $result .= ''
+ . implode(',', array($green, $orange, $red, $gray))
+ . '
';
+ } else {
+ $result .= ''
+ . implode(',', array($green, $orange, $red, $gray))
+ . ' | '
+ . htmlspecialchars($name)
+ . ' | '
+ . htmlspecialchars($ps[$name]->getFormattedValue() /* $val*/)
+ //. htmlspecialchars($unit)
+ . ' |
';
+ }
+ }
+ if (! $compact && $result !== '') {
+ $result = '';
+ }
+ return $result;
+ }
+}
+
diff --git a/modules/monitoring/application/views/helpers/PluginOutput.php b/modules/monitoring/application/views/helpers/PluginOutput.php
new file mode 100644
index 000000000..9596bbad8
--- /dev/null
+++ b/modules/monitoring/application/views/helpers/PluginOutput.php
@@ -0,0 +1,87 @@
+]*>~', $output)) {
+ // HTML
+ $output = preg_replace('~getPurifier()->purify($output)
+ );
+ } elseif (preg_match('~\\\n~', $output)) {
+ // Plaintext
+ $output = ''
+ . preg_replace(
+ '~\\\n~', "\n", preg_replace(
+ '~\\\n\\\n~', "\n",
+ preg_replace('~\[OK\]~', '[OK]',
+ preg_replace('~\[WARNING\]~', '[WARNING]',
+ preg_replace('~\[CRITICAL\]~', '[CRITICAL]',
+ preg_replace('~\@{6,}~', '@@@@@@',
+ $this->view->escape(wordwrap($output, 72, ' ', true))
+ ))))
+ )
+ ) . '';
+ } else {
+ $output = preg_replace('~\@{6,}~', '@@@@@@',
+ $this->view->escape(wordwrap($output, 72, ' ', true))
+ );
+ }
+ $output = $this->fixLinks($output);
+ return $output;
+ }
+
+ protected function fixLinks($html)
+ {
+
+
+ $ret = array();
+ $dom = new DOMDocument;
+ $dom->loadXML('' . $html . '
', LIBXML_NOERROR | LIBXML_NOWARNING);
+ $dom->preserveWhiteSpace = false;
+ $links = $dom->getElementsByTagName('a');
+ foreach ($links as $tag)
+ {
+ $href = $tag->getAttribute('href');
+ if (preg_match('~^/cgi\-bin/status\.cgi\?(.+)$~', $href, $m)) {
+ parse_str($m[1], $params);
+ if (isset($params['host'])) {
+ $tag->setAttribute('href', $this->view->baseUrl(
+ '/monitoring/detail/show?host=' . urlencode($params['host']
+ )));
+ }
+ } else {
+ // ignoring
+ }
+ //$ret[$tag->getAttribute('href')] = $tag->childNodes->item(0)->nodeValue;
+ }
+ return substr($dom->saveHTML(), 5, -7);
+ }
+
+ protected function getPurifier()
+ {
+ if (self::$purifier === null) {
+ // require_once 'vendor/htmlpurifier/library/HTMLPurifier.auto.php';
+ require_once 'vendor/htmlpurifier-4.5.0-lite/library/HTMLPurifier.auto.php';
+ $config = HTMLPurifier_Config::createDefault();
+ $config->set('Core.EscapeNonASCIICharacters', true);
+ $config->set('HTML.Allowed', 'p,br,b,a[href],i,table,tr,td[colspan],div[class]');
+ // This avoids permission problems:
+ // $config->set('Core.DefinitionCache', null);
+ $config->set('Cache.DefinitionImpl', null);
+ // TODO: Use a cache directory:
+ // $config->set('Cache.SerializerPath', '/var/spool/whatever');
+
+ // $config->set('URI.Base', 'http://www.example.com');
+ // $config->set('URI.MakeAbsolute', true);
+ // $config->set('AutoFormat.AutoParagraph', true);
+ self::$purifier = new HTMLPurifier($config);
+ }
+ return self::$purifier;
+ }
+}
+
diff --git a/modules/monitoring/application/views/helpers/ResolveComments.php b/modules/monitoring/application/views/helpers/ResolveComments.php
new file mode 100644
index 000000000..e0432aaa1
--- /dev/null
+++ b/modules/monitoring/application/views/helpers/ResolveComments.php
@@ -0,0 +1,32 @@
+ array("self::renderDiskPie")
+ );
+
+ public function renderServicePerfdata($service)
+ {
+ if (isset(self::$RENDERMAP[$service->check_command])) {
+ $fn = self::$RENDERMAP[$service->check_command];
+ $fn($service);
+ }
+ }
+
+ public static function renderDiskPie($service) {
+ $perfdata = $service->performance_data;
+ if(!$perfdata)
+ return "";
+
+ }
+}
diff --git a/modules/monitoring/application/views/scripts/list/contactgroups.phtml b/modules/monitoring/application/views/scripts/list/contactgroups.phtml
new file mode 100644
index 000000000..a4841c008
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/contactgroups.phtml
@@ -0,0 +1,4 @@
+= $this->tabs ?>
+
+= $this->escape(print_r($this->contactgroups->fetchAll(), 1)) ?>
+
diff --git a/modules/monitoring/application/views/scripts/list/contacts.phtml b/modules/monitoring/application/views/scripts/list/contacts.phtml
new file mode 100644
index 000000000..bacc8f878
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/contacts.phtml
@@ -0,0 +1,4 @@
+= $this->tabs ?>
+
+= $this->escape(print_r($this->contacts->fetchAll(), 1)) ?>
+
diff --git a/modules/monitoring/application/views/scripts/list/hostgroups.phtml b/modules/monitoring/application/views/scripts/list/hostgroups.phtml
new file mode 100644
index 000000000..df832cf16
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/hostgroups.phtml
@@ -0,0 +1,4 @@
+= $this->tabs ?>
+
+= $this->escape(print_r($this->hostgroups->fetchAll(), 1)) ?>
+
diff --git a/modules/monitoring/application/views/scripts/list/hosts-compact.phtml b/modules/monitoring/application/views/scripts/list/hosts-compact.phtml
new file mode 100644
index 000000000..85ccf8282
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/hosts-compact.phtml
@@ -0,0 +1,59 @@
+hosts)): ?>
+- no hosts is matching this filter -
+ return; endif ?>
+ $hosts = $this->hosts->paginate(); ?>
+
+
+
+ | State |
+ Host |
+
+
+
+ foreach ($hosts as $host): ?>
+host_acknowledged) {
+ $icons['ack.gif'] = 'Problem has been acknowledged';
+}
+
+if ($host->host_in_downtime) {
+ $icons['downtime.gif'] = 'Host is in a scheduled downtime';
+}
+
+$state_classes = array($this->monitoringState($host, 'host'));
+
+if ($host->host_acknowledged || $host->host_in_downtime) {
+ $state_classes[] = 'handled';
+}
+if ($host->host_last_state_change > (time() - 600)) {
+ $state_classes[] = 'new';
+}
+$state_title = strtoupper($this->monitoringState($host, 'host'))
+ . ' since '
+ . date('Y-m-d H:i:s', $host->host_last_state_change);
+?>
+
+ | = $this->qlink(
+ $this->timeSince($host->host_last_state_change),
+ 'monitoring/show/history',
+ array('host' => $host->host_name),
+ array('quote' => false)) ?> |
+
+ foreach ($icons as $icon => $alt)
+ echo $this->img('img/classic/' . $icon, array(
+ 'class' => 'icon',
+ 'title' => $alt
+ ));
+?>
+= $this->qlink(
+ $host->host_name,
+ 'monitoring/show/host',
+ array('host' => $host->host_name),
+ array('class' => 'row-action')
+ ) ?> |
+
+ endforeach ?>
+
+
diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml
new file mode 100644
index 000000000..7336baa8a
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/hosts.phtml
@@ -0,0 +1,125 @@
+= $this->tabs ?>
+hosts->limit(10);
+$hosts = $this->hosts->paginate();
+
+function getRowProperties(& $host, $scope) {
+
+ $icons = array();
+ if ($host->host_acknowledged) {
+ $icons['ack.gif'] = 'Problem has been acknowledged';
+ }
+
+ if ($host->host_in_downtime) {
+ $icons['downtime.gif'] = 'Host is in a scheduled downtime';
+ }
+
+ $state_classes = array($scope->monitoringState($host, 'host'));
+
+ if ($host->host_acknowledged || $host->host_in_downtime) {
+ $state_classes[] = 'handled';
+ }
+ if ($host->host_last_state_change > (time() - 600)) {
+ $state_classes[] = 'new';
+ }
+ $state_title = strtoupper($scope->monitoringState($host,"host"))
+ . ' since '
+ . date('Y-m-d H:i:s', $host->host_last_state_change);
+ return array($icons,$state_classes,$state_title);
+}
+// filter start
+$fparams = $this->hosts->getAppliedFilter()->toParams();
+if ($this->preserve === null) {
+ $this->preserve = $fparams;
+} else {
+ $this->preserve += $fparams;
+}
+
+$always = array();
+if (isset($_GET['sort'])) {
+ $always['sort'] = $_GET['sort'];
+}
+if (isset($_GET['dir'])) {
+ $always['dir'] = $_GET['dir'];
+}
+?>
+ if (! empty($fparams)): ?>
+Filters
+ foreach ($fparams as $k => $v): ?>
+= $this->qlink(
+ 'x',
+ 'monitoring/list/hosts',
+ $this->hosts->getAppliedFilter()->without($k)->toParams() + $always,
+ array(
+ 'style' => array('color' => 'red')
+ )
+) ?> = $this->escape("$k = $v") ?>
+ endforeach ?>
+
+ endif ?>
+
+
+ if (empty($hosts)): ?>
+
+
+ Sorry, no host found for this search
+
+ return; endif ?>
+
+= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)) ?>
+
+
+
+
+ foreach ($hosts as $host):
+ list($icons,$state_classes,$state_title) = getRowProperties($host,$this); ?>
+
+ = $this->qlink(
+ substr(strtoupper($this->monitoringState($host,"host")), 0, 4)
+ . ' since '
+ . $this->timeSince($host->host_last_state_change),
+ 'monitoring/show/history', array(
+ 'host' => $host->host_name
+ ),
+ array('quote' => false)
+) ?> |
+
+
+foreach ($icons as $icon => $alt)
+ echo $this->img('img/classic/' . $icon, array(
+ 'class' => 'icon',
+ 'title' => $alt
+ ));
+?>
+= $this->qlink(
+ $host->host_name,
+ 'monitoring/show/host', array(
+ 'host' => $host->host_name
+ ), array('class' => 'row-action')
+) ?>
+ =
+ $this->escape(substr(strip_tags($host->host_output), 0, 10000))
+?>
+ |
+
+
+
+
diff --git a/modules/monitoring/application/views/scripts/list/servicegroups.phtml b/modules/monitoring/application/views/scripts/list/servicegroups.phtml
new file mode 100644
index 000000000..926a6dd33
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/servicegroups.phtml
@@ -0,0 +1,4 @@
+= $this->tabs ?>
+
+= $this->escape(print_r($this->servicegroups->fetchAll(), 1)) ?>
+
diff --git a/modules/monitoring/application/views/scripts/list/services-compact.phtml b/modules/monitoring/application/views/scripts/list/services-compact.phtml
new file mode 100644
index 000000000..eaf26293a
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/services-compact.phtml
@@ -0,0 +1,73 @@
+ if (empty($this->services)): ?>
+
+ Sorry, no services found for this search
+
+ return; endif ?>
+
+
+$services = $this->services->paginate();
+
+?>
+
+
+
+ | State |
+ Service |
+
+
+
+ foreach ($services as $service): ?>
+service_acknowledged) {
+ $icons['ack.gif'] = 'Problem has been acknowledged';
+}
+
+if (! empty($service->service_downtimes_with_info)) {
+ $icons['downtime.gif'] = implode("\n",
+ $this->resolveComments($service->service_downtimes_with_info)
+ );
+}
+
+if (! empty($service->service_comments_with_info)) {
+ $icons['comment.gif'] = implode("\n",
+ $this->resolveComments($service->service_comments_with_info)
+ );
+}
+
+$state_classes = array($this->monitoringState($service, 'service'));
+if ($service->service_handled || $service->service_acknowledged || ! empty($service->service_downtimes_with_info)) {
+ $state_classes[] = 'handled';
+}
+if ($service->service_last_state_change > (time() - 600)) {
+ $state_classes[] = 'new';
+}
+$state_title = date('Y-m-d H:i:s', $service->service_last_state_change);
+
+$params = array(
+ 'host' => $service->host_name,
+ 'service' => $service->service_description
+);
+if (isset($this->preserve['backend'])) {
+ $params['backend'] = $this->preserve['backend'];
+}
+?>
+
+ |
+ = $this->qlink(
+ $this->timeSince($service->service_last_state_change),
+ 'monitoring/show/history', $params, array('quote' => false)) ?>
+ |
+
+ = $this->qlink(
+ $service->host_name,
+ 'monitoring/show/host',
+ $params
+ ); ?>:
+ = $this->qlink($service->service_description, 'monitoring/show/service', $params, array('class' => 'row-action')) ?>
+ |
+
+ endforeach ?>
+
+
\ No newline at end of file
diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml
new file mode 100644
index 000000000..c62ed3ef6
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/list/services.phtml
@@ -0,0 +1,154 @@
+= $this->tabs ?>
+services->limit(10);
+$services = $this->services->paginate();
+
+function getRowProperties(&$service, &$last_host, $scope) {
+ if ($last_host !== $service->host_name) {
+ $host_col = '' . $scope->qlink(
+ $service->host_name,
+ 'monitoring/show/host',
+ array('host' => $service->host_name)
+ ) . ':'
+ . (isset($service->host->address) ? ' ( ' . $scope->escape($service->host->address) . ')' : '')
+ . '';
+ $last_host = $service->host_name;
+ } else {
+ $host_col = ' ';
+ }
+ $icons = array();
+ if ($service->service_acknowledged) {
+ $icons['ack.gif'] = 'Problem has been acknowledged';
+ }
+
+ if (! empty($service->service_in_downtime)) {
+ $icons['downtime.gif'] = 'Service is in a scheduled downtime';
+ }
+
+ $state_classes = array($scope->monitoringState($service));
+
+ if ($service->service_handled) {
+ $state_classes[] = 'handled';
+ }
+ if ($service->service_last_state_change > (time() - 600)) {
+ $state_classes[] = 'new';
+ }
+ $state_title = strtoupper($scope->monitoringState($service))
+ . ' since '
+ . date('Y-m-d H:i:s', $service->service_last_state_change);
+ if ($scope->grapher && $scope->grapher->hasGraph($service->host_name, $service->service_description)) {
+ $graph = $scope->grapher->getSmallPreviewImage(
+ $service->host_name,
+ $service->service_description
+ );
+ } else {
+ $graph = '';
+ }
+ return array($host_col,$icons,$state_classes,$state_title,$graph);
+}
+
+$fparams = $this->services->getAppliedFilter()->toParams();
+if ($this->preserve === null) {
+ $this->preserve = $fparams;
+} else {
+ $this->preserve += $fparams;
+}
+ $last_host = null;
+$always = array();
+if (isset($_GET['sort'])) {
+ $always['sort'] = $_GET['sort'];
+}
+if (isset($_GET['dir'])) {
+ $always['dir'] = $_GET['dir'];
+}
+?>
+
+ if (! empty($fparams)): ?>
+
Filters
+ foreach ($fparams as $k => $v): ?>
+= $this->qlink(
+ 'x',
+ 'monitoring/list/services',
+ $this->services->getAppliedFilter()->without($k)->toParams() + $always,
+ array(
+ 'style' => array('color' => 'red')
+ )
+) ?> = $this->escape("$k = $v") ?>
+ endforeach ?>
+
+ endif ?>
+
+
+
+
+
+ Sorry, no services found for this search
+
+
+
+= $this->paginationControl($services, null, null, array('preserve' => $this->preserve )); ?>
+
+
+ foreach ($services as $service):
+ list($host_col,$icons,$state_classes,$state_title,$graph) = getRowProperties($service,$last_host,$this); ?>
+
+
+ = $this->qlink(
+
+ $service->service_state == 99 ? 'PENDING' :
+ substr(strtoupper($this->monitoringState($service)), 0, 4)
+ . ' since '
+ . $this->timeSince($service->service_last_state_change),
+ 'monitoring/show/history', array(
+ 'host' => $service->host_name,
+ 'service' => $service->service_description
+ ), array('quote' => false)) ?>
+ |
+
+
+ $alt) {
+ echo $this->img('img/classic/' . $icon, array(
+ 'class' => 'icon',
+ 'title' => $alt
+ ));
+ } ?>
+ = $host_col ?>
+ = $this->qlink($service->service_description, 'monitoring/show/service', array(
+ 'host' => $service->host_name,
+ 'service' => $service->service_description
+ ), array('class' => 'row-action')
+ )
+ ?>
+
+
+
+ = $this->escape(substr(strip_tags($service->service_output), 0, 900)) ?>
+
+ = $graph ?>
+ |
+
+
+
+
diff --git a/modules/monitoring/application/views/scripts/show/components/comments.phtml b/modules/monitoring/application/views/scripts/show/components/comments.phtml
new file mode 100644
index 000000000..09c4a5f8c
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/components/comments.phtml
@@ -0,0 +1,25 @@
+
+ if (! empty($this->comments)): ?>
+
+$list = array();
+foreach ($this->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);
+ }
+ $list[] = sprintf(
+ '[%s] %s (%s): %s',
+ $this->escape($comment->comment_author),
+ $this->format()->timeSince($comment->comment_timestamp),
+ $comment->comment_type,
+ $text
+ );
+}
+?>
+Comments: = implode('
', $list) ?>
+ endif ?>
diff --git a/modules/monitoring/application/views/scripts/show/components/contacts.phtml b/modules/monitoring/application/views/scripts/show/components/contacts.phtml
new file mode 100644
index 000000000..9ebe38553
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/components/contacts.phtml
@@ -0,0 +1,24 @@
+ if (! empty($this->contacts)): ?>
+
+$list = array();
+foreach ($this->contacts as $contact) {
+ $list[] = $this->qlink($contact->contact_alias, 'monitoring/show/contact', array(
+ 'contact_name' => $contact->contact_name
+ ));
+}
+?>
+Contacts: = implode(', ', $list) ?>
+ endif ?>
+
+ if (! empty($this->contactgroups)): ?>
+
+$list = array();
+foreach ($this->contactgroups as $contactgroup) {
+ $list[] = $this->qlink($contactgroup->contactgroup_alias, 'monitoring/show/contactgroup', array(
+ 'contactgroup_name' => $contactgroup->contactgroup_name
+ ));
+}
+?>
+Contactgroups: = implode(', ', $list) ?>
+ endif ?>
+
diff --git a/modules/monitoring/application/views/scripts/show/header.phtml b/modules/monitoring/application/views/scripts/show/header.phtml
new file mode 100644
index 000000000..d955fdf80
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/header.phtml
@@ -0,0 +1,30 @@
+service) && $this->tabs->getActiveName() !== 'host';
+?>
+ if (! $this->compact): ?>
+= $this->tabs ?>
+ endif ?>
+
+
+ | = $this->escape($this->host->host_name) ?>
+ if ($this->host->host_address && $this->host->host_address !== $this->host->host_name): ?>
+ (= $this->escape($this->host->host_address) ?>)
+ endif ?>
+ |
+ >
+ = $this->util()->getHostStateName($this->host->host_state); ?>
+ since = $this->timeSince($this->host->host_last_state_change) ?>
+ |
+
+ if ($showService): ?>
+
+ | Service: = $this->escape($this->service->service_description) ?> |
+
+ = $this->util()->getServiceStateName($this->service->service_state); ?>
+ since = $this->timeSince($this->service->service_last_state_change) ?>
+ |
+
+ else: ?>
+ | Host state |
+ endif ?>
+
diff --git a/modules/monitoring/application/views/scripts/show/history.phtml b/modules/monitoring/application/views/scripts/show/history.phtml
new file mode 100644
index 000000000..1c8a2e3ad
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/history.phtml
@@ -0,0 +1,99 @@
+= $this->partial('show/header.phtml', array(
+ 'host' => $this->host,
+ 'service' => $this->service,
+ 'tabs' => $this->tabs
+)); ?>history->limit(10);
+$history = $this->history->paginate();
+
+?>
+
+ if (empty($history)): ?>
+There are no matching history entries right now
+ else: ?>
+= $this->paginationControl($history, null, null, array('preserve' => $this->preserve)); ?>
+
+
+ foreach ($history as $event): ?>
+object_type == 'host') {
+ $states = array('up', 'down', 'unreachable', 'unknown', 99 => 'pending', null => 'pending');
+} else {
+ $states = array('ok', 'warning', 'critical', 'unknown', 99 => 'pending', null => 'pending');
+}
+
+$row_class = array_key_exists($event->state, $states) ? $states[$event->state] : 'invalid';
+
+?>
+| = date('d.m. H:i', $event->timestamp ) ?> |
+ if (! isset($this->host)): ?>
+= $this->escape($event->host_name) ?> |
+ endif ?>
+ if (! isset($this->service)): ?>
+ if (isset($this->host)): ?>
+= $this->qlink(
+ $event->service_description,
+ 'monitoring/show/service',
+ array(
+ 'host' => $this->host->host_name,
+ 'service' => $event->service_description
+ )
+) ?>
+ else: ?>
+= $this->escape($event->service_description) ?>
+ endif ?>
+ |
+ endif ?>
+ 16,
+ 'height' => 16,
+);
+switch ($event->type) {
+ case 'notify':
+ echo $this->img('img/classic/mail-notification.png', $imgparams);
+ break;
+ case 'comment':
+ echo $this->img('img/classic/comment.gif', $imgparams);
+ break;
+ case 'ack':
+ echo $this->img('img/classic/ack.gif', $imgparams);
+ break;
+ case 'dt_comment':
+ echo $this->img('img/classic/downtime.gif', $imgparams);
+ break;
+ case 'flapping':
+ echo $this->img('img/classic/flapping.gif', $imgparams);
+ break;
+ case 'hard_state':
+ echo $this->img('img/classic/state-hard.png', $imgparams);
+ break;
+ case 'soft_state':
+ echo $this->img('img/classic/state-soft.png', $imgparams);
+ break;
+ case 'dt_start':
+ echo $this->img('img/classic/downtime-start.png', $imgparams);
+ echo ' Downtime start';
+ break;
+ case 'dt_end':
+ echo $this->img('img/classic/downtime-end.png', $imgparams);
+ echo ' Downtime end';
+ break;
+}
+ ?>
+ if ($event->attempt !== null): ?>
+ [ = $event->attempt ?>/=$event->max_attempts ?> ]
+ endif ?>
+ = $this->ticket_pattern ? preg_replace(
+ $this->ticket_pattern,
+ $this->ticket_link,
+ $this->pluginOutput($event->output)
+ ) : $this->pluginOutput($event->output) ?>
+ |
+
+ endforeach ?>
+
+
+ endif ?>
diff --git a/modules/monitoring/application/views/scripts/show/host.phtml b/modules/monitoring/application/views/scripts/show/host.phtml
new file mode 100644
index 000000000..8d4dfb306
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/host.phtml
@@ -0,0 +1,40 @@
+= $this->partial('show/header.phtml', array(
+ 'host' => $this->host,
+ 'service' => $this->service,
+ 'tabs' => $this->tabs,
+ 'compact' => $this->compact
+)); ?>
+= $this->expandable(
+ $this->pluginOutput($this->host->host_output),
+ $this->pluginOutput($this->host->host_long_output)
+) ?>
+= $this->expandable(
+ 'Command: ' . array_shift(preg_split('|!|', $this->host->host_check_command)),
+ $this->commandArguments($this->host->host_check_command)
+) ?>
+ if (! empty($this->hostgroups)): ?>
+
+$list = array();
+foreach ($this->hostgroups as $name => $alias) {
+ $list[] = $this->qlink($alias, 'monitoring/list/services', array(
+ 'hostgroups' => $name
+ ));
+}
+?>
+Hostgroups: = implode(', ', $list) ?>
+ endif ?>
+= $this->render('show/components/contacts.phtml') ?>
+= $this->render('show/components/comments.phtml') ?>
+
+ foreach ($this->customvars as $name => $value): ?>
+= $this->escape($name) ?>: = $this->escape($value) ?>
+ endforeach ?>
+ if ($this->host->host_perfdata): ?>
+= $this->expandable(
+ 'Performance data',
+ $this->perfdata($this->host->host_perfdata),
+ array('collapsed' => false)
+) ?>
+ endif ?>
+= $this->preview_image ?>
+
diff --git a/modules/monitoring/application/views/scripts/show/legacy-service.phtml b/modules/monitoring/application/views/scripts/show/legacy-service.phtml
new file mode 100644
index 000000000..d528c3c12
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/legacy-service.phtml
@@ -0,0 +1,117 @@
+
+
+= $this->expandable(
+ $this->translate('Check statistics'),
+ 'sdfas'
+) ?>
+
+
+
+
= $this->translate('Check statistics') ?>
+
+
+
+
+
+
+
+
+ | = $this->translate('Last check') ?> |
+ = $this->format()->timeSince($this->service->service_last_check) ?> |
+
+
+ | = $this->translate('Next check')?> |
+
+
+ = $this->format()->timeUntil($this->service->service_next_check) ?>
+
+ |
+
+
+ | = $this->translate('Check execution time') ?> |
+ = $this->service->service_check_execution_time ?> |
+
+
+ | = $this->translate('Check latency') ?> |
+ =$this->service->service_check_latency ?> |
+
+
+
+
+
+
+service->service_comments) && is_array($this->service->service_comments)): ?>
+
+
+ = $this->translate('Comments') ?>
+
+
+
+
diff --git a/modules/monitoring/application/views/scripts/show/service.phtml b/modules/monitoring/application/views/scripts/show/service.phtml
new file mode 100644
index 000000000..9e78f98d4
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/service.phtml
@@ -0,0 +1,31 @@
+= $this->partial('show/header.phtml', array(
+ 'host' => $this->host,
+ 'service' => $this->service,
+ 'tabs' => $this->tabs,
+ 'compact' => $this->compact
+)); ?>
+= $this->expandable(
+ $this->pluginOutput($this->service->service_output),
+ $this->pluginOutput($this->service->service_long_output)
+) ?>
+
+= $this->render('show/components/contacts.phtml') ?>
+= $this->render('show/components/comments.phtml') ?>
+
+ foreach ($this->customvars as $name => $value): ?>
+= $this->escape($name) ?>: = $this->escape($value) ?>
+ endforeach ?>
+= $this->expandable(
+ 'Command: ' . array_shift(preg_split('|!|', $this->service->service_check_command)),
+ $this->commandArguments($this->service->service_check_command)
+) ?>
+ if ($this->service->service_perfdata): ?>
+= $this->expandable(
+ 'Performance data:',
+ $this->perfdata($this->service->service_perfdata),
+ array('collapsed' => false)
+) ?>
+ endif ?>
+
+= $this->partial('show/legacy-service.phtml', array('service' => $this->service)) ?>
+= $this->preview_image ?>
diff --git a/modules/monitoring/application/views/scripts/show/services.phtml b/modules/monitoring/application/views/scripts/show/services.phtml
new file mode 100644
index 000000000..84a566277
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/services.phtml
@@ -0,0 +1 @@
+= $this->services ?>
diff --git a/modules/monitoring/application/views/scripts/show/ticket.phtml b/modules/monitoring/application/views/scripts/show/ticket.phtml
new file mode 100644
index 000000000..b37eda8db
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/show/ticket.phtml
@@ -0,0 +1,2 @@
+= $this->tabs ?>
+
diff --git a/modules/monitoring/application/views/scripts/summary/group.phtml b/modules/monitoring/application/views/scripts/summary/group.phtml
new file mode 100644
index 000000000..8c9547dc5
--- /dev/null
+++ b/modules/monitoring/application/views/scripts/summary/group.phtml
@@ -0,0 +1,167 @@
+ if (! $this->compact): ?>
+= $this->tabs ?>
+ endif ?>
+ if (empty($this->summary)): ?>
+There are no such services right now
+ else: ?>
+
+ if (! $this->compact && $this->summary instanceof \Zend_Paginator): ?>
+= $this->paginationControl($this->summary, null, null, array('preserve' => $this->preserve)); ?>
+ endif ?>
+
+
+
+
+ | |
+ Critical |
+ Unknown |
+ Warning |
+ if (! $this->compact): ?> OK | endif ?>
+
+
+
+ foreach ($this->summary as $row): ?>
+critical > 0) {
+ $class_critical = 'critical';
+ $html_critical = $row->critical;
+ if ($row->critical_ack + $row->critical_dt > 0) {
+ $html_critical = sprintf(
+ '%s (%s/%s)',
+ $row->critical,
+ $row->critical_ack,
+ $row->critical_dt
+ );
+ }
+ if ($name_class === null) $name_class = 'critical';
+} elseif ($row->critical_dt + $row->critical_ack > 0) {
+ $class_critical = 'critical handled';
+ $html_critical = sprintf(
+ '%s / %s',
+ $row->critical_ack,
+ $row->critical_dt
+ );
+ if ($name_class === null) $name_class = 'critical handled';
+}
+
+if ($row->unknown > 0) {
+ $class_unknown = 'unknown';
+ $html_unknown = $row->unknown;
+ if ($row->unknown_ack + $row->unknown_dt > 0) {
+ $html_unknown .= sprintf(
+ ' (%s/%s)',
+ $row->unknown,
+ $row->unknown_ack,
+ $row->unknown_dt
+ );
+ }
+ if ($name_class === null) $name_class = 'unknown';
+} elseif ($row->unknown_dt + $row->unknown_ack > 0) {
+ $class_unknown = 'unknown handled';
+ $html_unknown = sprintf(
+ '%s / %s',
+ $row->unknown_ack,
+ $row->unknown_dt
+ );
+ if ($name_class === null) $name_class = 'unknown handled';
+}
+
+if ($row->warning > 0) {
+ $class_warning = 'warning';
+ $html_warning = $row->warning;
+ if ($row->warning_ack + $row->warning_dt > 0) {
+ $html_warning .= sprintf(
+ ' (%s/%s)',
+ $row->warning,
+ $row->warning_ack,
+ $row->warning_dt
+ );
+ }
+ if ($name_class === null) $name_class = 'warning';
+} elseif ($row->warning_dt + $row->warning_ack > 0) {
+ $class_warning = 'warning handled';
+ $html_warning = sprintf(
+ '%s / %s',
+ $row->warning_ack,
+ $row->warning_dt
+ );
+ if ($name_class === null) $name_class = 'warning handled';
+}
+
+
+if ($row->ok > 0) {
+ $class_ok = 'ok';
+ if (isset($row->hostgroup_name)) {
+ $html_ok = $this->qlink($row->ok, 'monitoring/list/services', array(
+ 'hostgroups' => $row->hostgroup_name
+ ));
+ } else {
+ $html_ok = $this->qlink($row->ok, 'monitoring/list/services', array(
+ 'servicegroups' => $row->servicegroup_name
+ ));
+ }
+ if ($name_class === null) $name_class = 'ok';
+}
+
+
+if (isset($row->hostgroup_name)) {
+ if ($name_class === 'ok') {
+ $name_html = $this->qlink($row->hostgroup_name, 'monitoring/list/services', array(
+ 'hostgroups' => $row->hostgroup_name
+ ));
+ } else {
+ $name_html = $this->qlink($row->hostgroup_name, 'monitoring/list/services', array(
+ 'hostgroups' => $row->hostgroup_name,
+ 'problems' => '1',
+ 'sort' => 'severity'
+ ));
+ }
+} else {
+ if ($name_class === 'ok') {
+ $name_html = $this->qlink($row->servicegroup_name, 'monitoring/list/services', array(
+ 'servicegroups' => $row->servicegroup_name
+ ));
+ } else {
+ $name_html = $this->qlink($row->servicegroup_name, 'monitoring/list/services', array(
+ 'servicegroups' => $row->servicegroup_name,
+ 'problems' => '1',
+ 'sort' => 'severity'
+ ));
+ }
+
+}
+?>
+
+
+ | = $name_html ?> |
+ = $html_critical ?> |
+ = $html_unknown ?> |
+ = $html_warning ?> |
+ if (! $this->compact): ?>= $html_ok ?> | endif ?>
+
+ endforeach ?>
+
+
+ endif ?>
+ if ($this->compact): ?>more endif ?>
diff --git a/modules/monitoring/config/backends.ini b/modules/monitoring/config/backends.ini
new file mode 100644
index 000000000..3fabbbf5d
--- /dev/null
+++ b/modules/monitoring/config/backends.ini
@@ -0,0 +1,9 @@
+
+[localdb]
+type = ido
+host = localhost
+user = "icinga-idoutils"
+pass = "***"
+db = "icinga"
+
+
diff --git a/modules/monitoring/config/instances.ini b/modules/monitoring/config/instances.ini
new file mode 100644
index 000000000..18213f142
--- /dev/null
+++ b/modules/monitoring/config/instances.ini
@@ -0,0 +1,2 @@
+[icinga]
+path=/usr/local/icinga/var/rw/icinga.cmd
diff --git a/modules/monitoring/config/menu.ini b/modules/monitoring/config/menu.ini
new file mode 100644
index 000000000..bd902fd2e
--- /dev/null
+++ b/modules/monitoring/config/menu.ini
@@ -0,0 +1,12 @@
+[menu]
+Issues.title = "Issues" ; Extended version
+Issues.route = "/monitoring/list/services?problems=1&sort=severity" ; Explicit route
+Issues.key = "issues" ; When this key is set in the controller, the item is active
+
+Changes.title = "Recent Changes"
+Changes.route = "/monitoring/list/services?sort=service_last_state_change"
+_1 = 1 ;Spacer after this section
+
+Hosts = "/monitoring/list/hosts"
+Services = "/monitoring/list/services"
+Summaries = "/monitoring/summary/group/by/hostgroup"
diff --git a/modules/monitoring/library/Monitoring/Backend.php b/modules/monitoring/library/Monitoring/Backend.php
new file mode 100644
index 000000000..937ec48cc
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend.php
@@ -0,0 +1,84 @@
+backends;
+ $backends = $config->backends;
+ foreach ($backends as $name => $config) {
+ // TODO: Check if access to this backend is allowed
+ self::$backendConfigs[$name] = $config;
+ }
+ }
+ return self::$backendConfigs;
+ }
+
+ public function getBackend($name = null)
+ {
+ if (! array_key_exists($name, self::$instances)) {
+ if ($name === null) {
+ $name = self::getDefaultName();
+ } else {
+ if (! self::exists($name)) {
+ throw new Exception(sprintf(
+ 'There is no such backend: "%s"',
+ $name
+ ));
+ }
+ }
+
+ $config = self::$backendConfigs[$name];
+ $type = $config->type;
+ $type[0] = strtoupper($type[0]);
+ $class = '\\Icinga\\Monitoring\\Backend\\' . $type;
+ self::$instances[$name] = new $class($config);
+ }
+ return self::$instances[$name];
+ }
+
+ 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 = Session::getInstance()->backend;
+ }
+ return self::getBackend($name);
+ }
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/AbstractBackend.php b/modules/monitoring/library/Monitoring/Backend/AbstractBackend.php
new file mode 100644
index 000000000..0dcdb278a
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/AbstractBackend.php
@@ -0,0 +1,199 @@
+config = $config;
+ $this->init();
+ }
+
+ protected function init()
+ {
+ }
+
+ /**
+ * Dummy function for fluent code
+ *
+ * return self
+ */
+ public function select()
+ {
+ return $this;
+ }
+
+ /**
+ * Create a Query object instance for given virtual table and desired fields
+ *
+ * Leave fields empty to get all available properties
+ *
+ * @param string Virtual table name
+ * @param array Fields
+ * return self
+ */
+ public function from($virtual_table, $fields = array())
+ {
+ $classname = $this->tableToClassName($virtual_table);
+ if (! class_exists($classname)) {
+ throw new ProgrammingError(
+ sprintf(
+ 'Asking for invalid virtual table %s',
+ $classname
+ )
+ );
+ }
+ $query = new $classname($this, $fields);
+ return $query;
+ }
+
+ public function hasView($virtual_table)
+ {
+ // TODO: This is no longer enough, have to check for Query right now
+ return class_exists($this->tableToClassName($virtual_table));
+ }
+
+ protected function tableToClassName($virtual_table)
+ {
+ return 'Icinga\\Monitoring\\View\\'
+ // . $this->getName()
+ // . '\\'
+ . ucfirst($virtual_table)
+ . 'View';
+ }
+
+ public function getName()
+ {
+ return preg_replace('~^.+\\\(.+?)$~', '$1', get_class($this));
+ }
+
+ public function __toString()
+ {
+ return $this->getName();
+ }
+
+
+
+ // UGLY temporary host fetch
+ public function fetchHost($host)
+ {
+ $select = $this->select()
+ ->from('status', array(
+ 'host_name',
+ 'host_address',
+ 'host_state',
+ 'host_handled',
+ 'host_in_downtime',
+ 'host_acknowledged',
+ 'host_check_command',
+ 'host_last_state_change',
+ 'host_alias',
+ 'host_output',
+ 'host_long_output',
+ 'host_perfdata',
+ ))
+ ->where('host_name', $host);
+ return $select->fetchRow();
+ $object = \Icinga\Objects\Host::fromBackend(
+ $this->select()
+ ->from('status', array(
+ 'host_name',
+ 'host_address',
+ 'host_state',
+ 'host_handled',
+ 'host_in_downtime',
+ 'host_acknowledged',
+ 'host_check_command',
+ 'host_last_state_change',
+ 'host_alias',
+ 'host_output',
+ 'host_long_output',
+ 'host_perfdata',
+ ))
+ ->where('host_name', $host)
+ ->fetchRow()
+ );
+ // $object->customvars = $this->fetchCustomvars($host);
+ return $object;
+ }
+
+ // UGLY temporary service fetch
+ public function fetchService($host, $service)
+ {
+Benchmark::measure('Preparing service select');
+ $select = $this->select()
+ ->from('status', array(
+
+ 'host_name',
+ 'host_state',
+ 'host_check_command',
+ 'host_last_state_change',
+
+ 'service_description',
+ 'service_state',
+ 'service_acknowledged',
+ 'service_handled',
+ 'service_output',
+ 'service_long_output',
+ 'service_perfdata',
+ // '_host_satellite',
+ 'service_check_command',
+ 'service_last_state_change',
+ 'service_last_check',
+ 'service_next_check',
+ 'service_check_execution_time',
+ 'service_check_latency',
+ // 'service_
+ ))
+ ->where('host_name', $host)
+ ->where('service_description', $service);
+ // Benchmark::measure((string) $select->getQuery());
+Benchmark::measure('Prepared service select');
+
+ return $select->fetchRow();
+ $object = \Icinga\Objects\Service::fromBackend(
+ $this->select()
+ ->from('status', array(
+
+ 'host_name',
+ 'host_state',
+ 'host_check_command',
+ 'host_last_state_change',
+
+ 'service_description',
+ 'service_state',
+ 'service_acknowledged',
+ 'service_handled',
+ 'service_output',
+ 'service_long_output',
+ 'service_perfdata',
+ // '_host_satellite',
+ 'service_check_command',
+ 'service_last_state_change',
+ 'service_last_check',
+ 'service_next_check',
+ 'service_check_execution_time',
+ 'service_check_latency',
+ // 'service_
+ ))
+ ->where('host_name', $host)
+ ->where('service_description', $service)
+ ->fetchRow()
+ );
+ // $object->customvars = $this->fetchCustomvars($host, $service);
+ return $object;
+ }
+
+
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido.php b/modules/monitoring/library/Monitoring/Backend/Ido.php
new file mode 100644
index 000000000..b456d1957
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido.php
@@ -0,0 +1,57 @@
+
+ * 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)
+ *
+ *
+ * Other possible (history-related) indexes, still subject to tests:
+ * CREATE INDEX web2_index ON icinga_statehistory (object_id, state_time DESC);
+ * CREATE INDEX web2_index ON icinga_notifications (object_id, instance_id, start_time DESC);
+ * CREATE INDEX web2_index ON icinga_downtimehistory (object_id, actual_start_time, actual_end_time);
+ *
+ * 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;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php
new file mode 100644
index 000000000..f27fb1afd
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/AbstractQuery.php
@@ -0,0 +1,326 @@
+applyDbSpecificWorkarounds
+ $this->prefix = $this->ds->getPrefix();
+
+ if ($this->ds->getConnection()->getDbType() === 'oracle') {
+ $this->object_id = $this->hostgroup_id = $this->servicegroup_id = 'id';
+ foreach ($this->columnMap as $table => & $columns) {
+ foreach ($column as $key => & $value) {
+ $value = preg_replace('/UNIX_TIMESTAMP/', 'localts2unixts', $value);
+ }
+ }
+ }
+
+ $this->prepareAliasIndexes();
+ $this->joinBaseTables();
+ }
+
+ protected function isCustomVar($alias)
+ {
+ return $this->allowCustomVars && $alias[0] === '_';
+ }
+
+ protected function joinCustomvar($customvar)
+ {
+ // TODO: This is not generic enough yet
+ list($type, $name) = $this->customvarNameToTypeName($customvar);
+ $alias = ($type === 'host' ? 'hcv_' : 'scv_') . strtolower($name);
+
+ $this->customVars[$customvar] = $alias;
+
+ // TODO: extend if we allow queries with only hosts / only services
+ // ($leftcol s.host_object_id vs h.host_object_id
+ $leftcol = 's.' . $type . '_object_id';
+ $joinOn = $leftcol
+ . ' = '
+ . $alias
+ . '.object_id'
+ . ' AND '
+ . $alias
+ . '.varname = '
+ . $this->db->quote(strtoupper($name));
+
+ $this->baseQuery->joinLeft(
+ array($alias => $this->prefix . 'customvariablestatus'),
+ $joinOn,
+ array()
+ );
+
+ return $this;
+ }
+
+ protected function prepareAliasIndexes()
+ {
+ foreach ($this->columnMap as $tbl => & $cols) {
+ foreach ($cols as $alias => $col) {
+ $this->idxAliasTable[$alias] = $tbl;
+ $this->idxAliasColumn[$alias] = preg_replace('~\n\s*~', ' ', $col);
+ }
+ }
+ }
+
+ protected function getDefaultColumns()
+ {
+ return $this->columnMap['hostgroups'];
+ }
+
+ protected function beforeCreatingCountQuery()
+ {
+ $this->applyAllFilters();
+ }
+
+ protected function beforeCreatingSelectQuery()
+ {
+ $this->setRealColumns();
+ Benchmark::measure(sprintf('%s is going to SELECT', get_class($this)));
+ }
+
+ protected function applyAllFilters()
+ {
+ $filters = array();
+ // TODO: Handle $special in a more generic way
+ $special = array('hostgroups', 'servicegroups');
+ foreach ($this->filters as $f) {
+ $alias = $f[0];
+ $value = $f[1];
+ $this->requireColumn($alias);
+
+ if ($alias === 'hostgroups') {
+ $col = 'hg.alias';
+ } elseif ($alias === 'servicegroups') {
+ $col = 'sg.alias';
+ } elseif ($this->isCustomvar($alias)) {
+ $col = $this->getCustomvarColumnName($alias);
+ } elseif ($this->hasAliasName($alias)) {
+ $col = $this->aliasToColumnName($alias);
+ } else {
+ throw new ProgrammingError(
+ 'If you finished here, code has been messed up'
+ );
+ }
+ $this->baseQuery->where($this->prepareFilterStringForColumn($col, $value));
+ }
+ }
+
+ public function order($col, $dir = null)
+ {
+ $this->requireColumn($col);
+ if ($this->isCustomvar($col)) {
+ // TODO: Doesn't work right now. Does it?
+ $col = $this->getCustomvarColumnName($col);
+ } elseif ($this->hasAliasName($col)) {
+ $col = $this->aliasToColumnName($col);
+ } else {
+ die('SHIT');
+ }
+ $this->order_columns[] = array($col, $dir);
+ return $this;
+ return parent::order($col, $dir);
+ }
+
+ public function setRealColumns()
+ {
+ $columns = $this->columns;
+ $this->columns = array();
+ if (empty($columns)) {
+ $colums = $this->getDefaultColumns();
+ }
+
+ foreach ($columns as $alias => $col) {
+ $this->requireColumn($col);
+ if ($this->isCustomvar($col)) {
+ $name = $this->getCustomvarColumnName($col);
+ } else {
+ $name = $this->aliasToColumnName($col);
+ }
+ if (is_int($alias)) {
+ $alias = $col;
+ }
+
+ $this->columns[$alias] = preg_replace('|\n|', ' ' , $name);
+ }
+ return $this;
+ }
+
+ protected function requireColumn($alias)
+ {
+ if ($this->hasAliasName($alias)) {
+ $this->requireVirtualTable($this->aliasToTableName($alias));
+ } elseif ($this->isCustomVar($alias)) {
+ $this->requireCustomvar($alias);
+ } else {
+ throw new ProgrammingError(sprintf('Got invalid column: %s', $alias));
+ }
+ return $this;
+ }
+
+ protected function hasAliasName($alias)
+ {
+ return array_key_exists($alias, $this->idxAliasColumn);
+ }
+
+ protected function aliasToColumnName($alias)
+ {
+ return $this->idxAliasColumn[$alias];
+ }
+
+ protected function aliasToTableName($alias)
+ {
+ return $this->idxAliasTable[$alias];
+ }
+
+ protected function hasJoinedVirtualTable($name)
+ {
+ return array_key_exists($name, $this->joinedVirtualTables);
+ }
+
+ protected function requireVirtualTable($name)
+ {
+ if ($this->hasJoinedVirtualTable($name)) {
+ return $this;
+ }
+ return $this->joinVirtualTable($name);
+ }
+
+ protected function joinVirtualTable($table)
+ {
+ $func = 'join' . ucfirst($table);
+ if (method_exists($this, $func)) {
+ $this->$func();
+ } else {
+ throw new ProgrammingError(sprintf(
+ 'Cannot join "%s", no such table found',
+ $table
+ ));
+ }
+ $this->joinedVirtualTables[$table] = true;
+ return $this;
+ }
+
+ protected function requireCustomvar($customvar)
+ {
+ if (! $this->hasCustomvar($customvar)) {
+ $this->joinCustomvar($customvar);
+ }
+ return $this;
+ }
+
+ protected function hasCustomvar($customvar)
+ {
+ return array_key_exists($customvar, $this->customVars);
+ }
+
+ protected function getCustomvarColumnName($customvar)
+ {
+ return $this->customVars[$customvar] . '.varvalue';
+ }
+
+ protected function customvarNameToTypeName($customvar)
+ {
+ // TODO: Improve this:
+ if (! preg_match('~^_(host|service)_([a-zA-Z0-9_]+)$~', $customvar, $m)) {
+ throw new ProgrammingError(
+ sprintf(
+ 'Got invalid custom var: "%s"',
+ $customvar
+ )
+ );
+ }
+ return array($m[1], $m[2]);
+ }
+
+ protected function prepareFilterStringForColumn($column, $value)
+ {
+ $filter = '';
+ $filters = array();
+
+ $or = array();
+ $and = array();
+
+ if (! is_array($value) && strpos($value, ',') !== false) {
+ $value = preg_split('~,~', $value, -1, PREG_SPLIT_NO_EMPTY);
+ }
+ if (! is_array($value)) {
+ $value = array($value);
+ }
+
+ // Go through all given values
+ foreach ($value as $val) {
+ // Value starting with minus: negation
+ if ($val[0] === '-') {
+ $val = substr($val, 1);
+ if (strpos($val, '*') === false) {
+ $and[] = $this->db->quoteInto($column . ' != ?', $val);
+ } else {
+ $and[] = $this->db->quoteInto(
+ $column . ' NOT LIKE ?',
+ str_replace('*', '%', $val)
+ );
+ }
+ } elseif ($val[0] === '+') { // Value starting with +: enforces AND
+ // TODO: depends on correct URL handling, not given in all
+ // ZF versions
+ $val = substr($val, 1);
+ if (strpos($val, '*') === false) {
+ $and[] = $this->db->quoteInto($column . ' = ?', $val);
+ } else {
+ $and[] = $this->db->quoteInto(
+ $column . ' LIKE ?',
+ str_replace('*', '%', $val)
+ );
+ }
+ } else { // All others ar ORs:
+ if (strpos($val, '*') === false) {
+ $or[] = $this->db->quoteInto($column . ' = ?', $val);
+ } else {
+ $or[] = $this->db->quoteInto(
+ $column . ' LIKE ?',
+ str_replace('*', '%', $val)
+ );
+ }
+ }
+ }
+
+ if (! empty($or)) {
+ $filters[] = implode(' OR ', $or);
+ }
+
+ if (! empty($and)) {
+ $filters[] = implode(' AND ', $and);
+ }
+
+ if (! empty($filters)) {
+ $filter = '(' . implode(') AND (', $filters) . ')';
+ }
+
+ return $filter;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php
new file mode 100644
index 000000000..5759a1c58
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CommentQuery.php
@@ -0,0 +1,50 @@
+ array(
+ 'comment_data' => 'cm.comment_data',
+ 'comment_author' => 'cm.author_name',
+ 'comment_timestamp' => 'UNIX_TIMESTAMP(cm.entry_time)',
+ 'comment_type' => "CASE cm.entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'downtime' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END",
+ ),
+ 'hosts' => array(
+ 'host_name' => 'ho.name1',
+ ),
+ 'services' => array(
+ 'service_host_name' => 'so.name1',
+ 'service_description' => 'so.name2',
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->baseQuery = $this->db->select()->from(
+ array('cm' => $this->prefix . 'comments'),
+ array()
+ );
+
+ $this->joinedVirtualTables = array('comments' => true);
+ }
+
+ protected function joinHosts()
+ {
+ $this->baseQuery->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'cm.object_id = ho.' . $this->object_id . ' AND ho.is_active = 1 AND ho.objecttype_id = 1',
+ array()
+ );
+ }
+
+ protected function joinServices()
+ {
+ $this->baseQuery->join(
+ array('so' => $this->prefix . 'objects'),
+ 'cm.object_id = so.' . $this->object_id . ' AND so.is_active = 1 AND so.objecttype_id = 2',
+ array()
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php
new file mode 100644
index 000000000..94e17e0f3
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactQuery.php
@@ -0,0 +1,72 @@
+ array(
+ 'contact_name' => 'co.name1',
+ 'contact_alias' => 'c.alias',
+ 'contact_email' => 'c.email_address',
+ 'contact_pager' => 'c.pager_address',
+ ),
+ 'hosts' => array(
+ 'host_name' => 'ho.name1',
+ ),
+ 'services' => array(
+ 'service_host_name' => 'so.name1',
+ 'service_description' => 'so.name2',
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->baseQuery = $this->db->select()->from(
+ array('c' => $this->prefix . 'contacts'),
+ array()
+ )->join(
+ array('co' => $this->prefix . 'objects'),
+ 'c.contact_object_id = co.' . $this->object_id
+ . ' AND co.is_active = 1',
+ array()
+ );
+
+ $this->joinedVirtualTables = array('contacts' => true);
+ }
+
+ protected function joinHosts()
+ {
+ $this->baseQuery->join(
+ array('hc' => $this->prefix . 'host_contacts'),
+ 'hc.contact_object_id = c.contact_object_id',
+ array()
+ )->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'hc.host_id = h.host_id',
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'h.host_object_id = ho.' . $this->object_id . ' AND ho.is_active = 1',
+ array()
+ );
+ }
+
+ protected function joinServices()
+ {
+ $this->baseQuery->join(
+ array('sc' => $this->prefix . 'service_contacts'),
+ 'sc.contact_object_id = c.contact_object_id',
+ array()
+ )->join(
+ array('s' => $this->prefix . 'services'),
+ 'sc.service_id = s.service_id',
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 's.service_object_id = so.' . $this->object_id . ' AND so.is_active = 1',
+ array()
+ );
+ }
+
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php
new file mode 100644
index 000000000..b7f1ac0fc
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ContactgroupQuery.php
@@ -0,0 +1,106 @@
+ array(
+ 'contactgroup_name' => 'cgo.name1',
+ 'contactgroup_alias' => 'cg.alias',
+ ),
+ 'contacts' => array(
+ 'contact_name' => 'co.name1',
+ ),
+ 'hosts' => array(
+ 'host_name' => 'ho.name1',
+ ),
+ 'services' => array(
+ 'service_host_name' => 'so.name1',
+ 'service_description' => 'so.name2',
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->baseQuery = $this->db->select()->from(
+ array('cg' => $this->prefix . 'contactgroups'),
+ array()
+ )->join(
+ array('cgo' => $this->prefix . 'objects'),
+ 'cg.contactgroup_object_id = cgo.' . $this->object_id
+ . ' AND cgo.is_active = 1',
+ array()
+ );
+
+ $this->joinedVirtualTables = array('contactgroups' => true);
+ }
+
+ protected function joinContacts()
+ {
+ $this->baseQuery->join(
+ array('cgm' => $this->prefix . 'contactgroup_members'),
+ 'cgm.contactgroup_id = cg.contactgroup_id',
+ array()
+ )->join(
+ array('co' => $this->prefix . 'objects'),
+ 'cgm.contact_object_id = co.object_id AND co.is_active = 1',
+ array()
+ );
+ }
+
+ protected function joinHosts()
+ {
+ $this->baseQuery->join(
+ array('hcg' => $this->prefix . 'host_contactgroups'),
+ 'hcg.contactgroup_object_id = cg.contactgroup_object_id',
+ array()
+ )->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'hcg.host_id = h.host_id',
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'h.host_object_id = ho.' . $this->object_id . ' AND ho.is_active = 1',
+ array()
+ );
+ }
+
+ protected function joinServices()
+ {
+ $scgSub = $this->db->select()->distinct()
+ ->from($this->prefix . 'service_contactgroups', array(
+ 'contactgroup_object_id', 'service_id'
+ ));
+
+ /*
+ This subselect is a workaround for a fucking stupid bug. Other tables
+ may be affected too. We absolutely need uniqueness here.
+
+ mysql> SELECT * FROM icinga_service_contactgroups WHERE
+ contactgroup_object_id = 143 AND service_id = 2079564;
+ +-------------------------+-------------+------------+------------------------+
+ | service_contactgroup_id | instance_id | service_id | contactgroup_object_id |
+ +-------------------------+-------------+------------+------------------------+
+ | 4904240 | 1 | 2079564 | 143 |
+ | 4904244 | 1 | 2079564 | 143 |
+ +-------------------------+-------------+------------+------------------------+
+ */
+
+ $this->baseQuery->join(
+ // array('scg' => $this->prefix . 'service_contactgroups'),
+ array('scg' => $scgSub),
+ 'scg.contactgroup_object_id = cg.contactgroup_object_id',
+ array()
+ )->join(
+ array('s' => $this->prefix . 'services'),
+ 'scg.service_id = s.service_id',
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 's.service_object_id = so.' . $this->object_id . ' AND so.is_active = 1',
+ array()
+ );
+ }
+
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php
new file mode 100644
index 000000000..a6175373f
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/CustomvarQuery.php
@@ -0,0 +1,40 @@
+ array(
+ 'varname' => 'cvs.varname',
+ 'varvalue' => 'cvs.varvalue',
+ ),
+ 'objects' => array(
+ 'host_name' => 'cvo.name1',
+ 'service_description' => 'cvo.name2',
+ 'contact_name' => 'cvo.name1',
+ 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 10 THEN 'contact' ELSE 'invalid' END"
+// 'object_type' => "CASE cvo.objecttype_id WHEN 1 THEN 'host' WHEN 2 THEN 'service' WHEN 3 THEN 'hostgroup' WHEN 4 THEN 'servicegroup' WHEN 5 THEN 'hostescalation' WHEN 6 THEN 'serviceescalation' WHEN 7 THEN 'hostdependency' WHEN 8 THEN 'servicedependency' WHEN 9 THEN 'timeperiod' WHEN 10 THEN 'contact' WHEN 11 THEN 'contactgroup' WHEN 12 THEN 'command' ELSE 'other' END"
+ ),
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->baseQuery = $this->db->select()->from(
+ array('cvs' => $this->prefix . 'customvariablestatus'),
+ array()
+ )->join(
+ array('cvo' => $this->prefix . 'objects'),
+ 'cvs.object_id = cvo.' . $this->object_id
+ . ' AND cvo.is_active = 1',
+ array()
+ );
+
+ $this->joinedVirtualTables = array(
+ 'customvars' => true,
+ 'objects' => true
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php
new file mode 100644
index 000000000..9c4554e99
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/EventHistoryQuery.php
@@ -0,0 +1,241 @@
+ array(
+ 'host' => 'eho.name1',
+ 'service' => 'eho.name2',
+ 'host_name' => 'eho.name1',
+ 'service_description' => 'eho.name2',
+ 'object_type' => "CASE WHEN eho.objecttype_id = 1 THEN 'host' ELSE 'service' END",
+ 'timestamp' => 'UNIX_TIMESTAMP(eh.state_time)',
+ 'raw_timestamp' => 'eh.state_time',
+ 'state' => 'eh.state',
+// 'last_state' => 'eh.last_state',
+// 'last_hard_state' => 'eh.last_hard_state',
+ 'attempt' => 'eh.attempt',
+ 'max_attempts' => 'eh.max_attempts',
+ 'output' => 'eh.output', // we do not want long_output
+ 'problems' => 'CASE WHEN eh.state = 0 OR eh.state IS NULL THEN 0 ELSE 1 END',
+ 'type' => 'eh.type',
+ )
+ );
+
+ protected function getDefaultColumns()
+ {
+ return $this->columnMap['eventhistory'];
+ }
+
+ protected function joinBaseTables()
+ {
+ $start = date('Y-m-d H:i:s', time() - 3600 * 24 * 30);
+ $end = date('Y-m-d H:i:s');
+ $start = null;
+ $end = null;
+
+ $history = $this->db->select()->from(
+ $this->prefix . 'statehistory',
+ array(
+ 'state_time' => 'state_time',
+ 'object_id' => 'object_id',
+ 'type' => "(CASE WHEN state_type = 1 THEN 'hard_state' ELSE 'soft_state' END)",
+ 'state' => 'state',
+ 'state_type' => 'state_type',
+ 'output' => 'output',
+ 'attempt' => 'current_check_attempt',
+ 'max_attempts' => 'max_check_attempts',
+ )
+ );
+ if ($start !== null) {
+ $history->where('state_time >= ?', $start);
+ }
+ // ->where('state_type = 1') ??
+ if ($end !== null) {
+ $history->where('state_time <= ?', $end);
+ }
+
+ $dt_start = $this->db->select()->from(
+ $this->prefix . 'downtimehistory',
+ array(
+ 'state_time' => 'actual_start_time',
+ 'object_id' => 'object_id',
+ 'type' => "('dt_start')",
+ 'state' => '(NULL)',
+ 'state_type' => '(NULL)',
+ 'output' => "CONCAT('[', author_name, '] ', comment_data)",
+ 'attempt' => '(NULL)',
+ 'max_attempts' => '(NULL)',
+ )
+ );
+ if ($start !== null) {
+ $dt_start->where('actual_start_time >= ?', $start);
+ }
+ if ($end !== null) {
+ $dt_start->where('actual_start_time <= ?', $end);
+ }
+
+ // TODO: check was_cancelled
+ $dt_end = $this->db->select()->from(
+ $this->prefix . 'downtimehistory',
+ array(
+ 'state_time' => 'actual_end_time',
+ 'object_id' => 'object_id',
+ 'type' => "('dt_end')",
+ 'state' => '(NULL)',
+ 'state_type' => '(NULL)',
+ 'output' => "CONCAT('[', author_name, '] ', comment_data)",
+ 'attempt' => '(NULL)',
+ 'max_attempts' => '(NULL)',
+ )
+ );
+ if ($start !== null) {
+ $dt_end->where('actual_end_time >= ?', $start);
+ }
+ if ($end !== null) {
+ $dt_end->where('actual_end_time <= ?', $end);
+ }
+
+ $comments = $this->db->select()->from(
+ $this->prefix . 'commenthistory',
+ array(
+ 'state_time' => 'comment_time',
+ 'object_id' => 'object_id',
+ 'type' => "(CASE entry_type WHEN 1 THEN 'comment' WHEN 2 THEN 'dt_comment' WHEN 3 THEN 'flapping' WHEN 4 THEN 'ack' END)",
+ 'state' => '(NULL)',
+ 'state_type' => '(NULL)',
+ 'output' => "CONCAT('[', author_name, '] ', comment_data)",
+ 'attempt' => '(NULL)',
+ 'max_attempts' => '(NULL)',
+ )
+ );
+
+ if ($start !== null) {
+ $comments->where('comment_time >= ?', $start);
+ }
+ if ($end !== null) {
+ $comments->where('comment_time <= ?', $end);
+ }
+
+ $cndetails = $this->db->select()->from(
+ array('cn' => $this->prefix . 'contactnotifications'),
+ array(
+ 'cnt' => 'COUNT(*)',
+ 'contacts' => 'GROUP_CONCAT(c.alias)',
+ 'notification_id' => 'notification_id'
+ )
+ )->join(
+ array('c' => $this->prefix . 'contacts'),
+ 'cn.contact_object_id = c.contact_object_id',
+ array()
+ )->group('notification_id');
+
+ $notifications = $this->db->select()->from(
+ array('n' => $this->prefix . 'notifications'),
+ array(
+ 'state_time' => 'start_time',
+ 'object_id' => 'object_id',
+ 'type' => "('notify')",
+ 'state' => 'state',
+ 'state_type' => '(NULL)',
+ 'output' => "CONCAT('[', cndetails.contacts, '] ', n.output)",
+ 'attempt' => '(NULL)',
+ 'max_attempts' => '(NULL)',
+ )
+ )->join(
+ array('cndetails' => $cndetails),
+ 'cndetails.notification_id = n.notification_id',
+ array()
+ );
+
+ if ($start !== null) {
+ $notifications->where('start_time >= ?', $start);
+ }
+ if ($end !== null) {
+ $notifications->where('start_time <= ?', $end);
+ }
+
+ $this->subQueries = array(
+ $history,
+ $dt_start,
+ $dt_end,
+ $comments,
+ $notifications
+ );
+ $sub = $this->db->select()->union($this->subQueries, \Zend_Db_Select::SQL_UNION_ALL);
+
+ $this->baseQuery = $this->db->select()->from(
+ array('eho' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('eh' => $sub),
+ 'eho.' . $this->object_id
+ . ' = eh.' . $this->object_id
+ . ' AND eho.is_active = 1',
+ array()
+ );
+
+ $this->joinedVirtualTables = array('eventhistory' => true);
+ }
+
+ // TODO: This duplicates code from AbstractQuery
+ protected function applyAllFilters()
+ {
+ $filters = array();
+
+ $host = null;
+ $service = null;
+
+ foreach ($this->filters as $f) {
+ $alias = $f[0];
+ $value = $f[1];
+ $this->requireColumn($alias);
+
+ if ($this->hasAliasName($alias)) {
+ $col = $this->aliasToColumnName($alias);
+ } else {
+ throw new ProgrammingError(
+ 'If you finished here, code has been messed up'
+ );
+ }
+
+ if (in_array($alias, array('host', 'host_name'))) {
+ $host = $value;
+ continue;
+ }
+ if (in_array($alias, array('service', 'service_description'))) {
+ $service = $value;
+ continue;
+ }
+
+ $this->baseQuery->where($this->prepareFilterStringForColumn($col, $value));
+ }
+
+ $objectQuery = $this->db->select()->from(
+ $this->prefix . 'objects',
+ $this->object_id
+ )->where('is_active = 1');
+
+ if ($service === '*') {
+ $objectQuery->where('name1 = ?', $host)
+ ->where('objecttype_id IN (1, 2)');
+ } elseif ($service) {
+ $objectQuery->where('name1 = ?', $host)
+ ->where('name2 = ?', $service)
+ ->where('objecttype_id = 2');
+ } else {
+ $objectQuery->where('name1 = ?', $host)
+ ->where('objecttype_id = 1');
+ }
+ $objectId = $this->db->fetchCol($objectQuery);
+ foreach ($this->subQueries as $query) {
+ $query->where('object_id IN (?)', $objectId);
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php
new file mode 100644
index 000000000..e1a08f043
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/HostgroupQuery.php
@@ -0,0 +1,44 @@
+ array(
+ 'hostgroup_name' => 'hgo.name1',
+ 'hostgroup_alias' => 'hg.alias',
+ ),
+ 'hosts' => array(
+ 'host_name' => 'ho.name1'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->baseQuery = $this->db->select()->from(
+ array('hg' => $this->prefix . 'hostgroups'),
+ array()
+ )->join(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hg.hostgroup_object_id = hgo.' . $this->object_id
+ . ' AND hgo.is_active = 1',
+ array()
+ );
+
+ $this->joinedVirtualTables = array('hostgroups' => true);
+ }
+
+ protected function joinHosts()
+ {
+ $this->baseQuery->join(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.hostgroup_id = hg.hostgroup_id',
+ array()
+ )->join(
+ array('ho' => $this->prefix . 'objects'),
+ 'hgm.host_object_id = ho.object_id AND ho.is_active = 1',
+ array()
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php
new file mode 100644
index 000000000..d54fa8753
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/ServicegroupQuery.php
@@ -0,0 +1,45 @@
+ array(
+ 'servicegroup_name' => 'sgo.name1',
+ 'servicegroup_alias' => 'sg.alias',
+ ),
+ 'services' => array(
+ 'host_name' => 'so.name1',
+ 'service_description' => 'so.name2'
+ )
+ );
+
+ protected function joinBaseTables()
+ {
+ $this->baseQuery = $this->db->select()->from(
+ array('sg' => $this->prefix . 'servicegroups'),
+ array()
+ )->join(
+ array('sgo' => $this->prefix . 'objects'),
+ 'sg.servicegroup_object_id = sgo.' . $this->object_id
+ . ' AND sgo.is_active = 1',
+ array()
+ );
+
+ $this->joinedVirtualTables = array('servicegroups' => true);
+ }
+
+ protected function joinServices()
+ {
+ $this->baseQuery->join(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.servicegroup_id = sg.servicegroup_id',
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ 'sgm.service_object_id = so.object_id AND so.is_active = 1',
+ array()
+ );
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php
new file mode 100644
index 000000000..4d2ee946e
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Ido/Query/StatusQuery.php
@@ -0,0 +1,258 @@
+ array(
+ 'host' => 'ho.name1',
+ 'host_name' => 'ho.name1',
+ 'host_display_name' => 'h.display_name',
+ 'host_alias' => 'h.alias',
+ 'host_address' => 'h.address',
+ 'host_ipv4' => 'INET_ATON(h.address)',
+ 'host_icon_image' => 'h.icon_image',
+ ),
+ 'hoststatus' => array(
+ 'host_state' => 'CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 99 ELSE hs.current_state END',
+ 'host_output' => 'hs.output',
+ 'host_long_output' => 'hs.long_output',
+ 'host_perfdata' => 'hs.perfdata',
+ 'host_acknowledged' => 'hs.problem_has_been_acknowledged',
+ 'host_in_downtime' => 'CASE WHEN (hs.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
+ 'host_handled' => 'CASE WHEN (hs.problem_has_been_acknowledged + hs.scheduled_downtime_depth) > 0 THEN 1 ELSE 0 END',
+ 'host_does_active_checks' => 'hs.active_checks_enabled',
+ 'host_accepts_passive_checks' => 'hs.passive_checks_enabled',
+ 'host_last_state_change' => 'UNIX_TIMESTAMP(hs.last_state_change)',
+ 'host_check_command' => 'hs.check_command',
+ 'host_problems' => 'CASE WHEN hs.current_state = 0 THEN 0 ELSE 1 END',
+ 'host_severity' => 'CASE WHEN hs.current_state = 0
+ THEN
+ CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL
+ THEN 16
+ ELSE 0
+ END
+ +
+ CASE WHEN hs.problem_has_been_acknowledged = 1
+ THEN 2
+ ELSE
+ CASE WHEN hs.scheduled_downtime_depth > 0
+ THEN 1
+ ELSE 4
+ END
+ END
+ ELSE
+ CASE WHEN hs.has_been_checked = 0 OR hs.has_been_checked IS NULL THEN 16
+ WHEN hs.current_state = 1 THEN 32
+ WHEN hs.current_state = 2 THEN 64
+ ELSE 256
+ END
+ +
+ CASE WHEN hs.problem_has_been_acknowledged = 1
+ THEN 2
+ ELSE
+ CASE WHEN hs.scheduled_downtime_depth > 0
+ THEN 1
+ ELSE 4
+ END
+ END
+ END',
+ ),
+ 'hostgroups' => array(
+ 'hostgroups' => 'hgo.name1',
+ ),
+ 'services' => array(
+ 'service_host_name' => 'so.name1',
+ 'service' => 'so.name2',
+ 'service_description' => 'so.name2',
+ 'service_display_name' => 's.display_name',
+ 'service_icon_image' => 's.icon_image',
+ ),
+ 'servicestatus' => array(
+ 'current_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END',
+ 'service_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE ss.current_state END',
+ 'service_hard_state' => 'CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 99 ELSE CASE WHEN ss.state_type = 1 THEN ss.current_state ELSE ss.last_hard_state END END',
+ 'service_state_type' => 'ss.state_type',
+ 'service_output' => 'ss.output',
+ 'service_long_output' => 'ss.long_output',
+ 'service_perfdata' => 'ss.perfdata',
+ 'service_acknowledged' => 'ss.problem_has_been_acknowledged',
+ 'service_in_downtime' => 'CASE WHEN (ss.scheduled_downtime_depth = 0) THEN 0 ELSE 1 END',
+ 'service_handled' => 'CASE WHEN (ss.problem_has_been_acknowledged + ss.scheduled_downtime_depth + COALESCE(hs.current_state, 0)) > 0 THEN 1 ELSE 0 END',
+ 'service_does_active_checks' => 'ss.active_checks_enabled',
+ 'service_accepts_passive_checks' => 'ss.passive_checks_enabled',
+ 'service_last_state_change' => 'UNIX_TIMESTAMP(ss.last_state_change)',
+ 'service_last_hard_state_change' => 'UNIX_TIMESTAMP(ss.last_hard_state_change)',
+ 'service_check_command' => 'ss.check_command',
+ 'service_last_check' => 'UNIX_TIMESTAMP(ss.last_check)',
+ 'service_next_check' => 'CASE WHEN ss.should_be_scheduled THEN UNIX_TIMESTAMP(ss.next_check) ELSE NULL END',
+ 'service_check_execution_time' => 'ss.execution_time',
+ 'service_check_latency' => 'ss.latency',
+ ),
+ 'status' => array(
+ 'problems' => 'CASE WHEN ss.current_state = 0 THEN 0 ELSE 1 END',
+ 'handled' => 'CASE WHEN ss.problem_has_been_acknowledged = 1 OR ss.scheduled_downtime_depth > 0 THEN 1 ELSE 0 END',
+ 'severity' => 'CASE WHEN ss.current_state = 0
+ THEN
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL
+ THEN 16
+ ELSE 0
+ END
+ +
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 2
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 1
+ ELSE 4
+ END
+ END
+ ELSE
+ CASE WHEN ss.has_been_checked = 0 OR ss.has_been_checked IS NULL THEN 16
+ WHEN ss.current_state = 1 THEN 32
+ WHEN ss.current_state = 2 THEN 128
+ WHEN ss.current_state = 3 THEN 64
+ ELSE 256
+ END
+ +
+ CASE WHEN ss.problem_has_been_acknowledged = 1
+ THEN 2
+ ELSE
+ CASE WHEN ss.scheduled_downtime_depth > 0
+ THEN 1
+ ELSE 4
+ END
+ END
+ END',
+ )
+ );
+public function group($col)
+{
+ $this->baseQuery->group($col);
+}
+ protected function getDefaultColumns()
+ {
+ return $this->columnMap['hosts'];
+ /*
+ + $this->columnMap['services']
+ + $this->columnMap['hoststatus']
+ + $this->columnMap['servicestatus']
+ ;*/
+ }
+
+ protected function joinBaseTables()
+ {
+ // TODO: Shall we always add hostobject?
+ $this->baseQuery = $this->db->select()->from(
+ array('ho' => $this->prefix . 'objects'),
+ array()
+ )->join(
+ array('hs' => $this->prefix . 'hoststatus'),
+ 'ho.object_id = hs.host_object_id AND ho.is_active = 1',
+ array()
+ )->join(
+ array('h' => $this->prefix . 'hosts'),
+ 'hs.host_object_id = h.host_object_id',
+ array()
+ );
+ $this->joinedVirtualTables = array(
+ 'hosts' => true,
+ 'hoststatus' => true,
+ );
+ }
+
+ protected function joinStatus()
+ {
+ $this->requireVirtualTable('services');
+ }
+
+ protected function joinServiceStatus()
+ {
+ $this->requireVirtualTable('services');
+ }
+
+ protected function joinServices()
+ {
+ $this->baseQuery->join(
+ array('s' => $this->prefix . 'services'),
+ 's.host_object_id = h.host_object_id',
+ array()
+ )->join(
+ array('so' => $this->prefix . 'objects'),
+ "so.$this->object_id = s.service_object_id AND so.is_active = 1",
+ array()
+ )->joinLeft(
+ array('ss' => $this->prefix . 'servicestatus'),
+ "so.$this->object_id = ss.service_object_id",
+ array()
+ );
+ }
+
+ // TODO: Test this one, doesn't seem to work right now
+ protected function joinHostgroups()
+ {
+ if ($this->hasJoinedVirtualTable('services')) {
+ return $this->joinServiceHostgroups();
+ } else {
+ return $this->joinHostHostgroups();
+ }
+ }
+
+ protected function joinHostHostgroups()
+ {
+ $this->baseQuery->join(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = h.host_object_id',
+ array()
+ )->join(
+ array('hg' => $this->prefix . 'hostgroups'),
+ "hgm.hostgroup_id = hg.$this->hostgroup_id",
+ array()
+ );
+
+ return $this;
+ }
+
+ protected function joinServiceHostgroups()
+ {
+ $this->baseQuery->join(
+ array('hgm' => $this->prefix . 'hostgroup_members'),
+ 'hgm.host_object_id = s.host_object_id',
+ array()
+ )->join(
+ array('hg' => $this->prefix . 'hostgroups'),
+ 'hgm.hostgroup_id = hg.' . $this->hostgroup_id,
+ array()
+ )->join(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.' . $this->object_id. ' = hg.hostgroup_object_id'
+ . ' AND hgo.is_active = 1',
+ array()
+ );
+
+ return $this;
+ }
+
+ protected function joinServicegroups()
+ {
+ $this->baseQuery->join(
+ array('sgm' => $this->prefix . 'servicegroup_members'),
+ 'sgm.service_object_id = s.service_object_id',
+ array()
+ )->join(
+ array('sg' => $this->prefix . 'servicegroups'),
+ 'sgm.servicegroup_id = sg.' . $this->servicegroup_id,
+ array()
+ )->join(
+ array('hgo' => $this->prefix . 'objects'),
+ 'hgo.' . $this->object_id. ' = hg.' . $this->hostgroup_id
+ . ' AND hgo.is_active = 1',
+ array()
+ );
+
+ return $this;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Livestatus.php b/modules/monitoring/library/Monitoring/Backend/Livestatus.php
new file mode 100644
index 000000000..0cc038291
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Livestatus.php
@@ -0,0 +1,45 @@
+
+ * @author Icinga-Web Team
+ * @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;
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php b/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php
new file mode 100644
index 000000000..cc1be7363
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Backend/Livestatus/Query/StatusQuery.php
@@ -0,0 +1,48 @@
+ 'host_address', // TODO
+ 'host_icon_image',
+
+ // Host state
+ 'host_state',
+ 'host_output' => 'host_plugin_output',
+ 'host_perfdata' => 'host_perf_data',
+ 'host_acknowledged',
+ 'host_does_active_checks' => 'host_active_checks_enabled',
+ 'host_accepts_passive_checks' => 'host_accept_passive_checks',
+ 'host_last_state_change',
+
+ // Service config
+ 'service_description' => 'description',
+ 'service_display_name' => 'display_name',
+
+ // Service state
+ 'service_state' => 'state',
+ 'service_output' => 'plugin_output',
+ 'service_perfdata' => 'perf_data',
+ 'service_acknowledged' => 'acknowledged',
+ 'service_does_active_checks' => 'active_checks_enabled',
+ 'service_accepts_passive_checks' => 'accept_passive_checks',
+ 'service_last_state_change' => 'last_state_change',
+
+ // Service comments
+ 'comments_with_info',
+ 'downtimes_with_info',
+ );
+
+ protected function createQuery()
+ {
+ return $this->connection->getConnection()->select()->from('services', $this->available_columns);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Environment.php b/modules/monitoring/library/Monitoring/Environment.php
new file mode 100644
index 000000000..bf198db4f
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Environment.php
@@ -0,0 +1,61 @@
+ array(
+ 'backend' => null,
+ 'grapher' => null,
+ 'configBackend' => null,
+ 'commandPipe' => null,
+ )
+ );
+
+ public static function defaultName()
+ {
+ // TODO: Check session
+ reset(self::$envs);
+ return key(self::$envs);
+ }
+
+ protected static function config($env, $what)
+ {
+ return self::$config[self::getName($env)][$what];
+ }
+
+ protected static function getName($env)
+ {
+ return $env === null ? self::defaultName() : $env;
+ }
+
+ public static function backend($env = null)
+ {
+ return Backend::getInstance(self::config($env, 'backend'));
+ }
+
+ public static function grapher($env = null)
+ {
+ return Hook::get('grapher', null, self::config($env, 'grapher'));
+ }
+
+ public static function configBackend($env = null)
+ {
+ return Hook::get(
+ 'configBackend',
+ null,
+ self::config($env, 'configBackend')
+ );
+ }
+
+ public static function commandPipe($env = null)
+ {
+ return CommandPipe::getInstance(self::config($env, 'commandPipe'));
+ }
+}
+
diff --git a/modules/monitoring/library/Monitoring/Plugin.php b/modules/monitoring/library/Monitoring/Plugin.php
new file mode 100644
index 000000000..80475f5d9
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Plugin.php
@@ -0,0 +1,9 @@
+unit) {
+ case self::BYTES:
+ return $this->formatBytes() . ' von ' . $this->formatBytes($this->max);
+ break;
+ case self::SECONDS:
+ return $this->formatSeconds();
+ break;
+ case self::PERCENT:
+ return number_format($this->val, 2, ',', '.') . '%';
+ break;
+ default:
+ return $this->val;
+ }
+ }
+
+ public function getValue()
+ {
+ return $this->val;
+ }
+
+ protected function formatBytes($val = null)
+ {
+ $steps = array(
+ 1 => 'Byte',
+ 1024 => 'KByte',
+ 1024 * 1024 => 'MByte',
+ 1024 * 1024 * 1024 => 'GByte',
+ 1024 * 1024 * 1024 * 1024 => 'TByte'
+ );
+ return $this->formatSpecial($steps, 1, $val);
+ }
+
+ protected function formatSeconds()
+ {
+ $steps = array(
+ 1 => 'us',
+ 1000 => 'ms',
+ 10000000 => 's',
+ );
+ return $this->formatSpecial($steps, 1000000, $this->val);
+ }
+
+ protected function formatSpecial($steps, $multi = 1, $val = null)
+ {
+ if ($val === null) {
+ $val = abs($this->val);
+ } else {
+ $val = abs($val);
+ }
+ // TODO: Check this, prefix fails if $val is given
+ if ($this->val < 0) {
+ $prefix = '-';
+ } else {
+ $prefix = '';
+ }
+ $val *= $multi;
+ $step = 1;
+ foreach (array_keys($steps) as $key) {
+ if ($key > $val * 1) {
+ break;
+ }
+ $step = $key;
+ }
+ return $prefix
+ . number_format($val / $step, 1, ',', '.')
+ . ' '
+ . $steps[$step];
+ }
+
+ protected function __construct(& $perfdata)
+ {
+ $this->byte_map = array(
+ 'b' => 1,
+ 'kb' => 1024,
+ 'mb' => 1024 * 1024,
+ 'gb' => 1024 * 1024 * 1024,
+ 'tb' => 1024 * 1024 * 1024 * 1024
+ );
+
+ // UGLY, fixes floats using comma:
+ $perfdata = preg_replace('~\,~', '.', $perfdata);
+
+ $parts = preg_split('~;~', $perfdata, 5);
+ while (count($parts) < 5) {
+ $parts[] = null;
+ }
+ list(
+ $this->val,
+ $this->warn,
+ $this->crit,
+ $this->min,
+ $this->max
+ ) = $parts;
+ // TODO: check numbers!
+
+ $unit = null;
+ if (! preg_match('~^(\-?[\d+\.]+(?:E\-?\d+)?)([^\d]+)?$~', $this->val, $m)) {
+ throw new \Exception('Got invalid perfdata: ' . $perfdata);
+ }
+ $this->val = $m[1];
+ if (isset($m[2])) {
+ $unit = strtolower($m[2]);
+ }
+ if ($unit === 'c') {
+ $this->unit = self::COUNTER;
+ }
+
+ if ($unit === '%') {
+ if (! is_numeric($this->min)) {
+ $this->min = 0;
+ }
+ if (! is_numeric($this->max)) {
+ $this->max = 100;
+ }
+ $this->unit = self::PERCENT;
+ } else {
+ if (! is_numeric($this->max) && $this->crit > 0) {
+ $this->max = $this->crit;
+ }
+ }
+
+
+ if (array_key_exists($unit, $this->byte_map)) {
+ $this->unit = self::BYTES;
+ $this->val = $this->val * $this->byte_map[$unit];
+ $this->min = $this->min * $this->byte_map[$unit];
+ $this->max = $this->max * $this->byte_map[$unit];
+ }
+ if ($unit === 's') {
+ $this->unit = self::SECONDS;
+ }
+ if ($unit === 'ms') {
+ $this->unit = self::SECONDS;
+ $this->val = $this->val / 1000;
+ }
+ if ($unit === '%') {
+ if (! is_numeric($this->min)) {
+ $this->min = 0;
+ }
+ if (! is_numeric($this->max)) {
+ $this->max = 100;
+ }
+ } else {
+ if (! is_numeric($this->max) && $this->crit > 0) {
+ $this->max = $this->crit;
+ }
+ }
+ }
+
+ public function isCounter()
+ {
+ return $this->unit === self::COUNTER;
+ }
+
+ public static function fromString(& $perfdata)
+ {
+ $pdat = new Perfdata($perfdata);
+ return $pdat;
+ }
+
+ protected function normalizeNumber($num)
+ {
+ return $num;
+ // Bullshit, still TODO
+ /*
+ $dot = strpos($num, '.');
+ $comma = strpos($num, ',');
+
+ if ($dot === false) {
+ // No dot...
+ if ($comma === false) {
+ // ...and no comma, it's an integer:
+ return (int) $num;
+ } else {
+ // just a comma
+ }
+ } else {
+ if ($comma === false) {
+ }
+ */
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php b/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php
new file mode 100644
index 000000000..e43a7c56c
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/Plugin/PerfdataSet.php
@@ -0,0 +1,69 @@
+ptr = & $perfdata;
+ $this->len = strlen($this->ptr);
+ while ($this->pos < $this->len) {
+ $label = $this->readLabel();
+ $perf = $this->readUntil(' ');
+ if (empty($perf)) continue;
+ $this->perfdata[$label] = Perfdata::fromString($perf);
+ }
+ }
+
+ public static function fromString(& $perfdata)
+ {
+ $pset = new PerfdataSet($perfdata);
+ return $pset;
+ }
+
+ public function getAll()
+ {
+ return $this->perfdata;
+ }
+
+ protected function readLabel()
+ {
+ $this->skipSpaces();
+ if (in_array($this->ptr[$this->pos], array('"', "'"))) {
+ $this->pos++;
+ $label = $this->readUntil($this->ptr[$this->pos - 1]);
+ $this->pos++; // Skip ' or "
+ $skip = $this->readUntil('=');
+ $this->pos++;
+ } else {
+ $label = $this->readUntil('=');
+ $this->pos++;
+ }
+ $this->skipSpaces();
+ return trim($label);
+ }
+
+ protected function readUntil($stop_char)
+ {
+ $start = $this->pos;
+ while ($this->pos < $this->len && $this->ptr[$this->pos] !== $stop_char) {
+ $this->pos++;
+ }
+ return substr($this->ptr, $start, $this->pos - $start);
+ }
+
+ protected function skipSpaces()
+ {
+ while ($this->pos < $this->len && $this->ptr[$this->pos] === ' ') {
+ $this->pos++;
+ }
+ }
+}
+
diff --git a/modules/monitoring/library/Monitoring/View/CommentView.php b/modules/monitoring/library/Monitoring/View/CommentView.php
new file mode 100644
index 000000000..166c73950
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/CommentView.php
@@ -0,0 +1,23 @@
+ array(
+ 'default_dir' => self::SORT_DESC
+ )
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/View/ContactView.php b/modules/monitoring/library/Monitoring/View/ContactView.php
new file mode 100644
index 000000000..11b015b63
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/ContactView.php
@@ -0,0 +1,24 @@
+ array(
+ 'default_dir' => self::SORT_ASC
+ )
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/View/ContactgroupView.php b/modules/monitoring/library/Monitoring/View/ContactgroupView.php
new file mode 100644
index 000000000..0f4b0c36c
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/ContactgroupView.php
@@ -0,0 +1,23 @@
+ array(
+ 'default_dir' => self::SORT_ASC
+ )
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/View/CustomvarView.php b/modules/monitoring/library/Monitoring/View/CustomvarView.php
new file mode 100644
index 000000000..37e45ebf0
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/CustomvarView.php
@@ -0,0 +1,23 @@
+ array(
+ 'varname' => self::SORT_ASC,
+ 'varvalue' => self::SORT_ASC,
+ )
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/View/EventHistoryView.php b/modules/monitoring/library/Monitoring/View/EventHistoryView.php
new file mode 100644
index 000000000..68c38e87d
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/EventHistoryView.php
@@ -0,0 +1,34 @@
+ array(
+ 'default_dir' => self::SORT_DESC
+ ),
+ 'timestamp' => array(
+ 'default_dir' => self::SORT_DESC
+ ),
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/View/HostgroupView.php b/modules/monitoring/library/Monitoring/View/HostgroupView.php
new file mode 100644
index 000000000..61e204b49
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/HostgroupView.php
@@ -0,0 +1,21 @@
+ array(
+ 'default_dir' => self::SORT_ASC
+ )
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/View/MonitoringView.php b/modules/monitoring/library/Monitoring/View/MonitoringView.php
new file mode 100644
index 000000000..6987c0e82
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/MonitoringView.php
@@ -0,0 +1,135 @@
+availableColumns);
+ }
+
+ public function getAvailableColumns()
+ {
+ return $this->availableColumns;
+ }
+
+ public function applyRequest($request)
+ {
+ return $this->applyRequestFilters($request)
+ ->applyRequestSorting($request);
+ }
+
+ protected function applyRequestSorting($request)
+ {
+ return $this->order(
+ $request->getParam('sort', $this->availableColumns[0]),
+ $request->getParam('dir')
+ );
+ }
+
+ protected function applyRequestFilters($request)
+ {
+ foreach ($request->getParams() as $key => $value) {
+ if ($this->isValidFilterColumn($key)) {
+ $this->where($key, $value);
+ }
+ }
+ return $this;
+ }
+
+ // TODO: applyAuthFilters(Auth $auth = null)
+
+ public function applyFilters($filters)
+ {
+ foreach ($filters as $col => $filter) {
+ $this->where($col, $filter);
+ }
+ return $this;
+ }
+
+ public function getAppliedFilter()
+ {
+ return new Filter($this->filters);
+ }
+
+ protected function getDefaultSortDir($col)
+ {
+ if (isset($this->sortDefaults[$col]['default_dir'])) {
+ return $this->sortDefaults[$col]['default_dir'];
+ }
+ return self::SORT_ASC;
+ }
+
+ public function getQuery()
+ {
+
+ if ($this->query === null) {
+ $class = substr(array_pop(preg_split('|\\\|', get_class($this))), 0, -4) . 'Query';
+ $class = '\\' . get_class($this->ds) . '\\Query\\' . $class;
+
+ $query = new $class($this->ds, $this->columns);
+ foreach ($this->filters as $f) {
+ $query->where($f[0], $f[1]);
+ }
+ foreach ($this->order_columns as $col) {
+ if (isset($this->sortDefaults[$col[0]]['columns'])) {
+ foreach ($this->sortDefaults[$col[0]]['columns'] as $c) {
+ $query->order($c, $col[1]);
+ }
+ } else {
+ $query->order($col[0], $col[1]);
+ }
+ }
+ $this->query = $query;
+ }
+ if ($this->hasLimit()) {
+ $this->query->limit($this->getLimit(), $this->getOffset());
+ }
+ return $this->query;
+ }
+
+ public function count()
+ {
+ return $this->getQuery()->count();
+ }
+
+ public function fetchAll()
+ {
+ return $this->getQuery()->fetchAll();
+ }
+
+ public function fetchRow()
+ {
+ return $this->getQuery()->fetchRow();
+ }
+
+ public function fetchColumn()
+ {
+ return $this->getQuery()->fetchColumn();
+ }
+
+ public function fetchPairs()
+ {
+ return $this->getQuery()->fetchPairs();
+ }
+
+ public function isValidFilterColumn($column)
+ {
+ if (in_array($column, $this->specialFilters)) {
+ return true;
+ }
+ return in_array($column, $this->availableColumns);
+ }
+}
diff --git a/modules/monitoring/library/Monitoring/View/ServicegroupView.php b/modules/monitoring/library/Monitoring/View/ServicegroupView.php
new file mode 100644
index 000000000..3401af68c
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/ServicegroupView.php
@@ -0,0 +1,21 @@
+ array(
+ 'default_dir' => self::SORT_ASC
+ )
+ );
+}
diff --git a/modules/monitoring/library/Monitoring/View/StatusView.php b/modules/monitoring/library/Monitoring/View/StatusView.php
new file mode 100644
index 000000000..35b00d315
--- /dev/null
+++ b/modules/monitoring/library/Monitoring/View/StatusView.php
@@ -0,0 +1,111 @@
+ array(
+ 'columns' => array(
+ 'host_name',
+ 'service_description'
+ ),
+ 'default_dir' => self::SORT_ASC
+ ),
+ 'host_address' => array(
+ 'columns' => array(
+ 'host_ipv4',
+ 'service_description'
+ ),
+ 'default_dir' => self::SORT_ASC
+ ),
+ 'host_last_state_change' => array(
+ 'default_dir' => self::SORT_DESC
+ ),
+ 'service_last_state_change' => array(
+ 'default_dir' => self::SORT_DESC
+ ),
+ 'severity' => array(
+ 'columns' => array(
+ 'severity',
+ 'service_last_state_change',
+ ),
+ 'default_dir' => self::SORT_DESC
+ ),
+ 'host_severity' => array(
+ 'columns' => array(
+ 'host_severity',
+ 'host_last_state_change',
+ ),
+ 'default_dir' => self::SORT_DESC
+ )
+ );
+
+ public function isValidFilterColumn($column)
+ {
+ if ($column[0] === '_'
+ && preg_match('~^_(?:host|service)_~', $column)
+ ) {
+ return true;
+ }
+ return parent::isValidFilterColumn($column);
+ }
+}