Add the monitoring module from the incubator

This commit is contained in:
Eric Lippmann 2013-06-27 10:14:41 +02:00
parent 543285017b
commit 1e9fa28433
58 changed files with 4411 additions and 0 deletions

View File

@ -0,0 +1,213 @@
<?php
use Icinga\Web\ModuleActionController;
use \Icinga\Exception as IcingaException;
class Monitoring_CommandController extends ModuleActionController
{
/**
* @var \Icinga\Protocol\Commandpipe\CommandPipe
*/
public $target;
private function getMandatoryParameter($name)
{
$value = $this->_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");
}
}

View File

@ -0,0 +1,208 @@
<?php
use Icinga\Web\ModuleActionController;
use Icinga\Web\Hook;
use Icinga\Monitoring\Backend;
class Monitoring_ListController extends ModuleActionController
{
protected $backend;
public function init()
{
$this->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 '<pre>' . htmlspecialchars(wordwrap($this->view->hosts->getQuery()->dump())) . '</pre>';
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 '<pre>' . htmlspecialchars(wordwrap($this->view->services->getQuery()->dump())) . '</pre>';
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;
}
}

View File

@ -0,0 +1,296 @@
<?php
use Icinga\Monitoring\Backend;
use Icinga\Web\ModuleActionController;
use Icinga\Web\Hook;
use Icinga\Application\Benchmark;
class Monitoring_ShowController extends ModuleActionController
{
protected $backend;
public function init()
{
$host = $this->_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 '<pre>' . htmlspecialchars($this->view->history->getQuery()->dump()) . '</pre>';
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;
}
}

View File

@ -0,0 +1,70 @@
<?php
use Icinga\Web\ModuleActionController;
use Icinga\Backend;
class Monitoring_SummaryController extends ModuleActionController
{
protected $backend;
protected $host;
protected $service;
public function init()
{
$this->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 '<pre>' . $query->dump() . '</pre>'; exit;
$this->view->summary = $query->paginate();
}
}

View File

@ -0,0 +1,19 @@
<?php
class Zend_View_Helper_CommandArguments extends Zend_View_Helper_Abstract
{
public function commandArguments($command)
{
if (empty($command)) {
return '';
}
$parts = explode('!', $command);
$row = "<dd><b>%s</b>: %s</dd>\n";
for ($i = 1; $i < count($parts); $i++) {
$parts[$i] = sprintf($row, '$ARG' . $i . '$', $parts[$i]);
}
array_shift($parts);
return "<dl>\n" . implode("\n", $parts) . "</dl>\n";
}
}

View File

@ -0,0 +1,19 @@
<?php
class Zend_View_Helper_MonitoringState extends Zend_View_Helper_Abstract
{
private $servicestates = array('ok', 'warning', 'critical', 'unknown', 99 => '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];
}
}
}

View File

@ -0,0 +1,84 @@
<?php
use Icinga\Monitoring\Plugin\PerfdataSet;
class Zend_View_Helper_Perfdata extends Zend_View_Helper_Abstract
{
public function perfdata($perfdata, $compact = false, $float = 'right')
{
if (empty($perfdata)) {
return '';
}
if ($float) {
$float = ' style="float: ' . $float . '"';
} else {
$float = '';
}
$pset = PerfdataSet::fromString($perfdata);
$ps = $pset->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 .= '<div class="inlinepie" title="' . htmlspecialchars($name) . ': ' . htmlspecialchars($ps[$name]->getFormattedValue() /* $val*/)
// . htmlspecialchars($unit)
. '"' . $float . '>'
. implode(',', array($green, $orange, $red, $gray))
. '</div>';
} else {
$result .= '<tr><td><div class="inlinepie" title="' . htmlspecialchars($name) . '">'
. implode(',', array($green, $orange, $red, $gray))
. '</div></td><td>'
. htmlspecialchars($name)
. '</td><td>'
. htmlspecialchars($ps[$name]->getFormattedValue() /* $val*/)
//. htmlspecialchars($unit)
. '</td></tr>';
}
}
if (! $compact && $result !== '') {
$result = '<table style="width: 100%">' . $result . '</table>';
}
return $result;
}
}

View File

@ -0,0 +1,87 @@
<?php
class Zend_View_Helper_PluginOutput extends Zend_View_Helper_Abstract
{
protected static $purifier;
public function pluginOutput($output)
{
if (preg_match('~<\w+[^>]*>~', $output)) {
// HTML
$output = preg_replace('~<table~', '<table style="font-size: 0.65em"',
$this->getPurifier()->purify($output)
);
} elseif (preg_match('~\\\n~', $output)) {
// Plaintext
$output = '<pre style="font-family: monospace; font-size: 0.95em;'
. ' width: 90%; overflow: auto;">'
. preg_replace(
'~\\\n~', "\n", preg_replace(
'~\\\n\\\n~', "\n",
preg_replace('~\[OK\]~', '<span class="ok">[OK]</span>',
preg_replace('~\[WARNING\]~', '<span class="warning">[WARNING]</span>',
preg_replace('~\[CRITICAL\]~', '<span class="error">[CRITICAL]</span>',
preg_replace('~\@{6,}~', '@@@@@@',
$this->view->escape(wordwrap($output, 72, ' ', true))
))))
)
) . '</pre>';
} 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('<div>' . $html . '</div>', 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;
}
}

View File

@ -0,0 +1,32 @@
<?php
// TODO: Throw away as soon as our backends are handling things better
class Zend_View_Helper_ResolveComments extends Zend_View_Helper_Abstract
{
public function resolveComments($infos)
{
$ret = array();
if (is_array($infos)) {
foreach ($infos as $info) {
if (! is_array($info) || empty($info)) continue;
if (is_int(key($info))) {
// livestatus
$ret[] = '[' . $info[1] . '] ' . $info[2];
} else {
// statusdat - doesn't seem to work?!
$ret[] = '[' . $info['author'] . '] '
. (isset($info['comment'])
? $info['comment']
: $info['comment_data']
);
}
}
} else {
// ido
$ret = preg_split('~\|~', $infos);
}
return $ret;
}
}

View File

@ -0,0 +1,23 @@
<?php
class Zend_View_Helper_RenderServicePerfdata extends Zend_View_Helper_Abstract
{
private static $RENDERMAP = array(
"check_local_disk" => 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 "";
}
}

View File

@ -0,0 +1,4 @@
<?= $this->tabs ?>
<pre>
<?= $this->escape(print_r($this->contactgroups->fetchAll(), 1)) ?>
</pre>

View File

@ -0,0 +1,4 @@
<?= $this->tabs ?>
<pre>
<?= $this->escape(print_r($this->contacts->fetchAll(), 1)) ?>
</pre>

View File

@ -0,0 +1,4 @@
<?= $this->tabs ?>
<pre>
<?= $this->escape(print_r($this->hostgroups->fetchAll(), 1)) ?>
</pre>

View File

@ -0,0 +1,59 @@
<?php if (empty($this->hosts)): ?>
- no hosts is matching this filter -
<? return; endif ?>
<? $hosts = $this->hosts->paginate(); ?>
<table class="hosts action">
<thead>
<tr>
<th style="width: 6em;" >State</th>
<th >Host</th>
</tr>
</thead>
<tbody>
<? foreach ($hosts as $host): ?>
<?php
$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($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);
?>
<tr class="<?= implode(' ', $state_classes) ?>">
<td style="width: 20%;" class="state" title="<?= $state_title ?>"><?= $this->qlink(
$this->timeSince($host->host_last_state_change),
'monitoring/show/history',
array('host' => $host->host_name),
array('quote' => false)) ?></td>
<td style="width: 80%;"><?
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')
) ?></td>
</tr>
<? endforeach ?>
</tbody>
</table>

View File

@ -0,0 +1,125 @@
<?= $this->tabs ?>
<?php
$this->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)): ?>
<div style="float: right; width: 20em; font-size: 0.8em;"><b>Filters</b><br>
<? 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") ?></br>
<? endforeach ?>
</div>
<? endif ?>
<form method="get" action="<?= $this->qUrl(
'monitoring/list/hosts?' . http_build_query(
$this->hosts->getAppliedFilter()->toParams()
),
array()
)
?>">
Sort by <?= $this->formSelect(
'sort',
$this->sort,
array('class' => 'autosubmit'),
array(
'host_severity' => 'Severity',
'host_last_state_change' => 'Last state change',
'host_name' => 'Host',
)
) ?>
<input type="text" placeholder="Add filter..." name="search" />
</form>
<?php // end filter ?>
<? if (empty($hosts)): ?>
<div class="alert alert-info fullpage_infobox">
Sorry, no host found for this search
</div>
<? return; endif ?>
<?= $this->paginationControl($hosts, null, null, array('preserve' => $this->preserve)) ?>
<table class="action">
<tbody>
<? foreach ($hosts as $host):
list($icons,$state_classes,$state_title) = getRowProperties($host,$this); ?>
<tr class="<?= implode(' ', $state_classes) ?>">
<td class="state" title="<?= $state_title ?>"><?= $this->qlink(
substr(strtoupper($this->monitoringState($host,"host")), 0, 4)
. '&nbsp;since<br /> '
. $this->timeSince($host->host_last_state_change),
'monitoring/show/history', array(
'host' => $host->host_name
),
array('quote' => false)
) ?></td>
<td><?
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')
) ?><br />
<span style="font-size: 0.7em"><?=
$this->escape(substr(strip_tags($host->host_output), 0, 10000))
?></span>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>

View File

@ -0,0 +1,4 @@
<?= $this->tabs ?>
<pre>
<?= $this->escape(print_r($this->servicegroups->fetchAll(), 1)) ?>
</pre>

View File

@ -0,0 +1,73 @@
<? if (empty($this->services)): ?>
<div class="alert alert-info fullpage_infobox">
Sorry, no services found for this search
</div>
<? return; endif ?>
<?
$services = $this->services->paginate();
?>
<table class="services action">
<thead>
<tr>
<th style="width: 6em;" >State</th>
<th >Service</th>
</tr>
</thead>
<tbody>
<? foreach ($services as $service): ?>
<?php
$icons = array();
if ($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'];
}
?>
<tr class="<?= implode(' ', $state_classes) ?>">
<td class="state" title="<?= $state_title ?>">
<?= $this->qlink(
$this->timeSince($service->service_last_state_change),
'monitoring/show/history', $params, array('quote' => false)) ?>
</td>
<td>
<?= $this->qlink(
$service->host_name,
'monitoring/show/host',
$params
); ?>:
<?= $this->qlink($service->service_description, 'monitoring/show/service', $params, array('class' => 'row-action')) ?>
</td>
</tr>
<? endforeach ?>
</tbody>
</table>

View File

@ -0,0 +1,154 @@
<?= $this->tabs ?>
<?php
$this->services->limit(10);
$services = $this->services->paginate();
function getRowProperties(&$service, &$last_host, $scope) {
if ($last_host !== $service->host_name) {
$host_col = '<b>' . $scope->qlink(
$service->host_name,
'monitoring/show/host',
array('host' => $service->host_name)
) . ':</b><span style="font-size: 0.7em">'
. (isset($service->host->address) ? ' ( ' . $scope->escape($service->host->address) . ')' : '')
. '</span>';
$last_host = $service->host_name;
} else {
$host_col = '&nbsp; ';
}
$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'];
}
?>
<div class="dontprint">
<? if (! empty($fparams)): ?>
<div style="float: right; width: 20em; font-size: 0.8em;"><b>Filters</b><br>
<? 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") ?></br>
<? endforeach ?>
</div>
<? endif ?>
<form method="get" action="<?= $this->qUrl(
'monitoring/list/services?' . http_build_query(
$this->services->getAppliedFilter()->toParams()
),
array()
)
?>">
Sort by <?= $this->formSelect(
'sort',
$this->sort,
array(
'class' => 'autosubmit',
),
array(
'severity' => 'Severity',
'service_last_state_change' => 'Last state change',
'host_name' => 'Host',
'service_description' => 'Service',
)
) ?>
<input type="text" placeholder="Add filter..." name="search" />
</form>
</div>
<?php if (empty($services)): ?>
<div class="alert alert-info fullpage_infobox">
Sorry, no services found for this search
</div>
<?php return; endif ?>
<?= $this->paginationControl($services, null, null, array('preserve' => $this->preserve )); ?>
<table class="action">
<tbody>
<? foreach ($services as $service):
list($host_col,$icons,$state_classes,$state_title,$graph) = getRowProperties($service,$last_host,$this); ?>
<tr class="<?= implode(' ', $state_classes) ?>">
<td class="state" title="<?= $state_title ?>">
<?= $this->qlink(
$service->service_state == 99 ? 'PENDING' :
substr(strtoupper($this->monitoringState($service)), 0, 4)
. '&nbsp;since<br /> '
. $this->timeSince($service->service_last_state_change),
'monitoring/show/history', array(
'host' => $service->host_name,
'service' => $service->service_description
), array('quote' => false)) ?>
</td>
<td>
<?php
foreach ($icons as $icon => $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')
)
?>
<br />
&nbsp; &nbsp; <span style="font-size: 0.7em">
<?= $this->escape(substr(strip_tags($service->service_output), 0, 900)) ?>
</span>
<?= $graph ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>

View File

@ -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
);
}
?>
<b>Comments:</b><blockquote> <?= implode('<br />', $list) ?></blockquote>
<? endif ?>

View File

@ -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
));
}
?>
<b>Contacts:</b> <?= implode(', ', $list) ?><br />
<? 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
));
}
?>
<b>Contactgroups:</b> <?= implode(', ', $list) ?><br />
<? endif ?>

View File

@ -0,0 +1,30 @@
<?php
$showService = isset($this->service) && $this->tabs->getActiveName() !== 'host';
?>
<? if (! $this->compact): ?>
<?= $this->tabs ?>
<? endif ?>
<table style="margin-bottom: 1em">
<tr class="<?= $this->monitoringState($this->host, 'host') ?><?= $this->host->host_handled ? ' handled' : '' ?>">
<td><b><?= $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 ?>
</b></td>
<td class="state"<?= $showService ? '' : ' rowspan="2"' ?>>
<?= $this->util()->getHostStateName($this->host->host_state); ?><br />
since <?= $this->timeSince($this->host->host_last_state_change) ?>
</td>
</tr>
<? if ($showService): ?>
<tr class="<?= $this->monitoringState($this->service, 'service'); ?><?= $this->service->service_handled ? ' handled' : '' ?>">
<td><b>Service: <?= $this->escape($this->service->service_description) ?></b></td>
<td class="state">
<?= $this->util()->getServiceStateName($this->service->service_state); ?><br />
since <?= $this->timeSince($this->service->service_last_state_change) ?>
</td>
</tr>
<? else: ?>
<tr><td><b>Host state</b></td></tr>
<? endif ?>
</table>

View File

@ -0,0 +1,99 @@
<?= $this->partial('show/header.phtml', array(
'host' => $this->host,
'service' => $this->service,
'tabs' => $this->tabs
)); ?><?php
$this->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)); ?>
<table class="paginatable">
<tbody>
<? foreach ($history as $event): ?>
<?php
if ($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';
?>
<tr class="<?= $row_class ?>"><td class="state"><?= date('d.m. H:i', $event->timestamp ) ?></td>
<? if (! isset($this->host)): ?>
<td><?= $this->escape($event->host_name) ?></td>
<? endif ?>
<? if (! isset($this->service)): ?>
<td><? 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 ?>
</td>
<? endif ?>
<td style="padding: 0.2em;"><?php
$imgparams = array(
'width' => 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) ?>
</td>
</tr>
<? endforeach ?>
</tbody>
</table>
<? endif ?>

View File

@ -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(
'<b>Command:</b> ' . 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
));
}
?>
<b>Hostgroups:</b> <?= implode(', ', $list) ?><br />
<? endif ?>
<?= $this->render('show/components/contacts.phtml') ?>
<?= $this->render('show/components/comments.phtml') ?>
<? foreach ($this->customvars as $name => $value): ?>
<b><?= $this->escape($name) ?>:</b> <?= $this->escape($value) ?><br />
<? endforeach ?>
<? if ($this->host->host_perfdata): ?>
<?= $this->expandable(
'<b>Performance data</b>',
$this->perfdata($this->host->host_perfdata),
array('collapsed' => false)
) ?>
<? endif ?>
<?= $this->preview_image ?>

View File

@ -0,0 +1,117 @@
<!--<?php if (!isset($this->service) || $this->service == null): ?>
<div class="alert alert-info fullpage_infobox">
No service selected
</div>
<?php return; endif ?>
<br>
<?= $this->expandable(
'<b>'
. $this->translate('Plugin output:')
. '</b> '
. $this->pluginOutput($this->service->service_output),
$this->service->service_long_output
? $this->pluginOutput($this->service->service_long_output)
: ''
) ?>
<?php
$explodedCmd = explode('!', $this->service->service_check_command);
$row = '<dd><b>%s</b> : %s</dd>';
$table = '';
if (count($explodedCmd) > 1) {
$table = '<dl>';
for ($i = 1; $i < count($explodedCmd); $i++) {
$table .= sprintf($row, '$ARG' . $i . '$', $explodedCmd[$i]);
}
$table .= '</dl>';
}
echo $this->expandable('<b>' . $this->translate('Check command:') . '</b> ' .$explodedCmd[0], $table); ?>
<?php
$perfData = $this->perfdata($this->service->service_perfdata);
if (!$perfData && $this->service->service_perfdata)
$perfData = $this->service->service_perfdata;
?>
<?php if ($perfData): ?>
<div class="expandable" >
<div class="expand-title"><b><?= $this->translate('Performance data') ?></b> </div>
<div class="expand-content">
<?= $perfData ?>
</div>
</div>
<?php endif; ?>
-->
<?php //@TODO: Create check_statistic helper
?>
<?= $this->expandable(
$this->translate('Check statistics'),
'sdfas'
) ?>
<div class="expandable" >
<div class="expand-title">
<b><?= $this->translate('Check statistics') ?></b>
<div class="expand-controls">
<a href="#" target="_self" title="<?= $this->translate('Check now') ?>">
<i class='icon-repeat'></i>
</a>
</div>
</div>
<div class="expand-content">
<table style="width:100%">
<thead>
</thead>
<tbody>
<tr>
<td style="width: 25em"><?= $this->translate('Last check') ?></td>
<td><?= $this->format()->timeSince($this->service->service_last_check) ?></td>
</tr>
<tr>
<td><?= $this->translate('Next check')?></td>
<td>
<span class="icinga-uiwidget-countdown" countdown-end="<?= $this->service->service_next_check ?>">
<?= $this->format()->timeUntil($this->service->service_next_check) ?>
</span>
</td>
</tr>
<tr>
<td><?= $this->translate('Check execution time') ?></td>
<td><?= $this->service->service_check_execution_time ?></td>
</tr>
<tr>
<td><?= $this->translate('Check latency') ?></td>
<td><?=$this->service->service_check_latency ?></td>
</tr>
</tbody>
</table>
</div>
</div>
<?php if (isset($this->service->service_comments) && is_array($this->service->service_comments)): ?>
<div class="expandable" >
<div class="expand-title">
<b><?= $this->translate('Comments') ?></b>
</div>
<div class="expand-content" style="padding: 0px">
<table class="subTable icinga-widget" type="icinga/subTable" maxItems="10" style="width:100%">
<thead>
</thead>
<tbody>
<?php
$comments = $this->service->service_comments;
if (! is_array($comments)) {
$comments = array($comments);
}
foreach ($comments as $comment ): ?>
<tr>
<td><?= $this->timeSince($comment->entry_time); ?></td>
<td><?= htmlspecialchars($comment->author); ?></td>
<td><?= htmlspecialchars($comment->data); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>

View File

@ -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): ?>
<b><?= $this->escape($name) ?>:</b> <?= $this->escape($value) ?><br />
<? endforeach ?>
<?= $this->expandable(
'<b>Command:</b> ' . array_shift(preg_split('|!|', $this->service->service_check_command)),
$this->commandArguments($this->service->service_check_command)
) ?>
<? if ($this->service->service_perfdata): ?>
<?= $this->expandable(
'<b>Performance data</b>:',
$this->perfdata($this->service->service_perfdata),
array('collapsed' => false)
) ?>
<? endif ?>
<?= $this->partial('show/legacy-service.phtml', array('service' => $this->service)) ?>
<?= $this->preview_image ?>

View File

@ -0,0 +1 @@
<?= $this->services ?>

View File

@ -0,0 +1,2 @@
<?= $this->tabs ?>

View File

@ -0,0 +1,167 @@
<? if (! $this->compact): ?>
<?= $this->tabs ?>
<? endif ?>
<? if (empty($this->summary)): ?>
There are no such services right now
<? else: ?>
<?php
$now = time();
?>
<? if (! $this->compact && $this->summary instanceof \Zend_Paginator): ?>
<?= $this->paginationControl($this->summary, null, null, array('preserve' => $this->preserve)); ?>
<? endif ?>
<table class="pivot action">
<thead>
<tr>
<!-- <th style="width: 6em;">&nbsp;</th>-->
<th style="text-align: left;">&nbsp;</th>
<th style="width: 5em;">Critical</th>
<th style="width: 5em;">Unknown</th>
<th style="width: 5em;">Warning</th>
<? if (! $this->compact): ?> <th style="width: 9%;">OK</th><? endif ?>
</tr>
</thead>
<tbody>
<? foreach ($this->summary as $row): ?>
<?php
$class_ok = '';
$class_warning = '';
$class_critical = '';
$class_unknown = '';
$html_ok = '-';
$html_warning = '-';
$html_critical = '-';
$html_unknown = '-';
$name_class = null;
if ($row->critical > 0) {
$class_critical = 'critical';
$html_critical = $row->critical;
if ($row->critical_ack + $row->critical_dt > 0) {
$html_critical = sprintf(
'%s <span class="critical handled">(%s/%s)</span>',
$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(
' <span class="unknown handled">(%s/%s)</span>',
$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(
' <span class="warning handled">(%s/%s)</span>',
$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'
));
}
}
?>
<tr>
<!-- <td class="<?= $name_class ?>"><? if ($row->last_state_change + 600 > $now): ?>
<blink><?= $this->timeSince($row->last_state_change) ?></blink>
<? else: ?>
<?= $this->timeSince($row->last_state_change) ?>
<? endif ?></td>-->
<td style="text-align: left;"><?= $name_html ?></td>
<td class="<?= $class_critical ?>"><?= $html_critical ?></td>
<td class="<?= $class_unknown ?>"><?= $html_unknown ?></td>
<td class="<?= $class_warning ?>"><?= $html_warning ?></td>
<? if (! $this->compact): ?><td class="ok"><?= $html_ok ?></td><? endif ?>
</tr>
<? endforeach ?>
</tbody>
</table>
<? endif ?>
<? if ($this->compact): ?><a href="<?= $this->baseUrl('monitoring/summary/group') ?>">more</a><? endif ?>

View File

@ -0,0 +1,9 @@
[localdb]
type = ido
host = localhost
user = "icinga-idoutils"
pass = "***"
db = "icinga"

View File

@ -0,0 +1,2 @@
[icinga]
path=/usr/local/icinga/var/rw/icinga.cmd

View File

@ -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"

View File

@ -0,0 +1,84 @@
<?php
namespace Icinga\Monitoring;
use Icinga\Application\Config;
use Icinga\Web\Session;
use Exception;
class Backend
{
protected static $instances = array();
protected static $backendConfigs;
final protected function __construct()
{
}
public static function exists($name)
{
$configs = self::getBackendConfigs();
return array_key_exists($name, $configs);
}
public static function getDefaultName()
{
$configs = self::getBackendConfigs();
if (empty($configs)) {
throw new Exception(
'Cannot get default backend as no backend has been configured'
);
}
reset($configs);
return key($configs);
}
public function getBackendConfigs()
{
if (self::$backendConfigs === null) {
$config = Config::getInstance()->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);
}
}
}

View File

@ -0,0 +1,199 @@
<?php
namespace Icinga\Monitoring\Backend;
use Icinga\Data\DatasourceInterface;
use Icinga\Exception\ProgrammingError;
use Icinga\Application\Benchmark;
use Zend_Config;
class AbstractBackend implements DatasourceInterface
{
protected $config;
public function __construct(Zend_Config $config = null)
{
if ($config === null) {
// $config = new Zend_Config(array()); ???
}
$this->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;
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace Icinga\Monitoring\Backend;
use Icinga\Data\Db\Connection;
/**
* This class provides an easy-to-use interface to the IDO database
*
* You should usually not directly use this class but go through Icinga\Monitoring\Backend.
*
* New MySQL indexes:
* <code>
* CREATE INDEX web2_index ON icinga_scheduleddowntime (object_id, is_in_effect);
* CREATE INDEX web2_index ON icinga_comments (object_id);
* CREATE INDEX web2_index ON icinga_objects (object_id, is_active); -- (not sure yet)
* </code>
*
* Other possible (history-related) indexes, still subject to tests:
* CREATE INDEX web2_index ON icinga_statehistory (object_id, state_time DESC);
* CREATE INDEX web2_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;
}
}

View File

@ -0,0 +1,326 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
use Icinga\Data\Db\Query;
use Icinga\Application\Benchmark;
use Icinga\Exception\ProgrammingError;
abstract class AbstractQuery extends Query
{
protected $prefix;
protected $idxAliasColumn;
protected $idxAliasTable;
protected $columnMap = array();
protected $query;
protected $customVars = array();
protected $joinedVirtualTables = array();
protected $object_id = 'object_id';
protected $hostgroup_id = 'hostgroup_id';
protected $servicegroup_id = 'servicegroup_id';
protected $allowCustomVars = false;
protected function init()
{
parent::init();
// TODO: $this->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;
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class CommentQuery extends AbstractQuery
{
protected $columnMap = array(
'comments' => 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()
);
}
}

View File

@ -0,0 +1,72 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class ContactQuery extends AbstractQuery
{
protected $columnMap = array(
'contacts' => 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()
);
}
}

View File

@ -0,0 +1,106 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class ContactgroupQuery extends AbstractQuery
{
protected $columnMap = array(
'contactgroups' => 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()
);
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class CustomvarQuery extends AbstractQuery
{
protected $object_id = 'object_id';
protected $columnMap = array(
'customvars' => 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
);
}
}

View File

@ -0,0 +1,241 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
use Icinga\Exception\ProgrammingError;
class EventHistoryQuery extends AbstractQuery
{
protected $subQueries = array();
protected $columnMap = array(
'eventhistory' => 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);
}
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class HostgroupQuery extends AbstractQuery
{
protected $columnMap = array(
'hostgroups' => 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()
);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class ServicegroupQuery extends AbstractQuery
{
protected $columnMap = array(
'servicegroups' => 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()
);
}
}

View File

@ -0,0 +1,258 @@
<?php
namespace Icinga\Monitoring\Backend\Ido\Query;
class StatusQuery extends AbstractQuery
{
protected $allowCustomVars = true;
protected $columnMap = array(
'hosts' => 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;
}
}

View File

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

View File

@ -0,0 +1,48 @@
<?php
namespace Icinga\Monitoring\Backend\Livestatus\Query;
use Icinga\Data\AbstractQuery;
class StatusQuery extends AbstractQuery
{
protected $available_columns = array(
'host_name',
'host_display_name',
'host_alias',
'host_address',
'host_ipv4' => '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);
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace Icinga\Monitoring;
use Icinga\Application\Config;
use Icinga\Web\Session;
use Exception;
class Environment
{
protected static $envs = array(
'default' => 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'));
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace Icinga\Monitoring;
require_once ICINGA_LIBDIR . '/Icinga/Application/Cli.php';
class Plugin extends Cli
{
}

View File

@ -0,0 +1,205 @@
<?php
namespace Icinga\Monitoring\Plugin;
class Perfdata
{
const COUNTER = 0x01;
const PERCENT = 0x02;
const BYTES = 0x04;
const SECONDS = 0x08;
protected $byte_map;
protected $min;
protected $max;
protected $warn;
protected $crit;
protected $val;
protected $unit;
public function getFormattedValue()
{
switch ($this->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) {
}
*/
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace Icinga\Monitoring\Plugin;
class PerfdataSet
{
protected $ptr;
protected $pos = 0;
protected $len;
protected $perfdata;
protected function __construct($perfdata)
{
if (empty($perfdata)) return;
$this->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++;
}
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace Icinga\Monitoring\View;
class CommentView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
'comment_data',
'comment_author',
'comment_timestamp',
'comment_type',
);
protected $specialFilters = array();
protected $sortDefaults = array(
'comment_timestamp' => array(
'default_dir' => self::SORT_DESC
)
);
}

View File

@ -0,0 +1,24 @@
<?php
namespace Icinga\Monitoring\View;
class ContactView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
'contact_alias',
'contact_email',
'contact_pager',
'contact_notify_hosts',
'contact_notify_services',
);
protected $specialFilters = array();
protected $sortDefaults = array(
'contact_alias' => array(
'default_dir' => self::SORT_ASC
)
);
}

View File

@ -0,0 +1,23 @@
<?php
namespace Icinga\Monitoring\View;
class ContactgroupView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
'contactgroup_name',
'contactgroup_alias',
'host_name',
'service_description'
);
protected $specialFilters = array();
protected $sortDefaults = array(
'contactgroup_alias' => array(
'default_dir' => self::SORT_ASC
)
);
}

View File

@ -0,0 +1,23 @@
<?php
namespace Icinga\Monitoring\View;
class CustomvarView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
'varname',
'varvalue',
'object_type',
);
protected $specialFilters = array();
protected $sortDefaults = array(
'varname' => array(
'varname' => self::SORT_ASC,
'varvalue' => self::SORT_ASC,
)
);
}

View File

@ -0,0 +1,34 @@
<?php
namespace Icinga\Monitoring\View;
class EventHistoryView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
'raw_timestamp',
'timestamp',
'host',
'service',
'host_name',
'state',
'last_state',
'last_hard_state',
'attempt',
'max_attempts',
'output',
'type'
);
protected $specialFilters = array();
protected $sortDefaults = array(
'raw_timestamp' => array(
'default_dir' => self::SORT_DESC
),
'timestamp' => array(
'default_dir' => self::SORT_DESC
),
);
}

View File

@ -0,0 +1,21 @@
<?php
namespace Icinga\Monitoring\View;
class HostgroupView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
'hostgroup_name',
'hostgroup_alias',
);
protected $specialFilters = array();
protected $sortDefaults = array(
'hostgroup_alias' => array(
'default_dir' => self::SORT_ASC
)
);
}

View File

@ -0,0 +1,135 @@
<?php
namespace Icinga\Monitoring\View;
use Icinga\Data\AbstractQuery;
use Icinga\Data\Filter;
class MonitoringView extends AbstractQuery
{
protected $query;
protected $availableColumns = array();
protected $specialFilters = array();
protected $sortDefaults = array();
public function hasColumn($column)
{
return in_array($column, $this->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);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace Icinga\Monitoring\View;
class ServicegroupView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
'servicegroup_name',
'servicegroup_alias',
);
protected $specialFilters = array();
protected $sortDefaults = array(
'servicegroup_alias' => array(
'default_dir' => self::SORT_ASC
)
);
}

View File

@ -0,0 +1,111 @@
<?php
namespace Icinga\Monitoring\View;
class StatusView extends MonitoringView
{
protected $query;
protected $availableColumns = array(
// Hosts
'host_name',
'host_display_name',
'host_alias',
'host_address',
'host_ipv4',
'host_icon_image',
// Hoststatus
'host_state',
'host_problems',
'host_severity',
'host_state_type',
'host_output',
'host_long_output',
'host_perfdata',
'host_acknowledged',
'host_in_downtime',
'host_handled',
'host_does_active_checks',
'host_accepts_passive_checks',
'host_last_state_change',
'host_last_hard_state_change',
// Services
'service_description',
'service_display_name',
// Servicetatus
'current_state',
'service_state',
'service_state_type',
'service_hard_state',
'service_output',
'service_long_output',
'service_perfdata',
'service_acknowledged',
'service_in_downtime',
'service_handled',
'service_does_active_checks',
'service_accepts_passive_checks',
'service_last_state_change',
'service_last_hard_state_change',
// Status
'problems',
'handled',
'severity'
);
protected $specialFilters = array(
'hostgroups',
'servicegroups'
);
protected $sortDefaults = array(
'host_name' => 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);
}
}