compact ? ' data-base-target="col1"' : ''; ?>>
@@ -10,19 +21,21 @@ $currentUrl = Url::fromRequest()->getRelativeUrl();
stats->services_ok): ?>
- = $this->qlink(
- $this->stats->services_ok,
- $selfUrl,
- array('service_state' => 0),
- array('title' => sprintf(
- $this->translatePlural(
- 'List %u service that is currently in state OK',
- 'List %u services which are currently in state OK',
+ =
+ $this->qlink(
+ $this->stats->services_ok,
+ urlAddFilterOptional($selfUrl, Filter::where('service_state', 0), $this->baseFilter),
+ null,
+ array('title' => sprintf(
+ $this->translatePlural(
+ 'List %u service that is currently in state OK',
+ 'List %u services which are currently in state OK',
+ $this->stats->services_ok
+ ),
$this->stats->services_ok
- ),
- $this->stats->services_ok
- ))
- ); ?>
+ ))
+ );
+ ?>
'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
if ($this->stats->$pre) {
$handled = $pre . '_handled';
$unhandled = $pre . '_unhandled';
- $paramsHandled = array('service_state' => $stateId, 'service_handled' => 1);
- $paramsUnhandled = array('service_state' => $stateId, 'service_handled' => 0);
+ $paramsHandled = Filter::matchAll(
+ Filter::where('service_state', $stateId),
+ Filter::where('service_handled', 1)
+ );
+ $paramsUnhandled = Filter::matchAll(
+ Filter::where('service_state', $stateId),
+ Filter::where('service_handled', 0)
+ );
if ($this->stats->$unhandled) {
- $compareUrl = Url::fromPath($selfUrl, $paramsUnhandled)->getRelativeUrl();
+ $compareUrl = Url::fromPath($selfUrl)->setQueryString($paramsUnhandled->toQueryString())->getRelativeUrl();
} else {
- $compareUrl = Url::fromPath($selfUrl, $paramsHandled)->getRelativeUrl();
+ $compareUrl = Url::fromPath($selfUrl)->setQueryString($paramsUnhandled->toQueryString())->getRelativeUrl();
}
if ($compareUrl === $currentUrl) {
@@ -50,8 +69,8 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
echo $this->qlink(
$this->stats->$unhandled,
- $selfUrl,
- $paramsUnhandled,
+ urlAddFilterOptional($selfUrl, $paramsUnhandled, $this->baseFilter),
+ null,
array('title' => sprintf(
$this->translatePlural(
'List %u service that is currently in state %s',
@@ -65,7 +84,7 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
}
if ($this->stats->$handled) {
- if (Url::fromPath($selfUrl, $paramsHandled)->getRelativeUrl() === $currentUrl) {
+ if (Url::fromPath($selfUrl)->setQueryString($paramsHandled->toQueryString())->getRelativeUrl() === $currentUrl) {
$active = ' active';
} else {
$active = '';
@@ -75,8 +94,8 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
}
echo $this->qlink(
$this->stats->$handled,
- $selfUrl,
- $paramsHandled,
+ urlAddFilterOptional($selfUrl, $paramsHandled, $this->baseFilter),
+ null,
array('title' => sprintf(
$this->translatePlural(
'List %u service that is currently in state %s (Acknowledged)',
@@ -99,8 +118,8 @@ foreach (array(2 => 'critical', 3 => 'unknown', 1 => 'warning') as $stateId => $
= $this->qlink(
$this->stats->services_pending,
- $selfUrl,
- array('service_state' => 99),
+ urlAddFilterOptional($selfUrl, Filter::where('service_state', 99), $this->baseFilter),
+ null,
array('title' => sprintf(
$this->translatePlural(
'List %u service that is currently in state PENDING',
diff --git a/modules/monitoring/application/views/scripts/list/hosts.phtml b/modules/monitoring/application/views/scripts/list/hosts.phtml
index 04fadf2ec..196279b04 100644
--- a/modules/monitoring/application/views/scripts/list/hosts.phtml
+++ b/modules/monitoring/application/views/scripts/list/hosts.phtml
@@ -11,7 +11,6 @@ if (! $this->compact): ?>
= $this->sortBox; ?>
= $this->limiter; ?>
= $this->paginator; ?>
- = $this->selectionToolbar('multi', $this->href('monitoring/hosts/show?' . $this->filter->toQueryString())); ?>
= $this->filterEditor; ?>
@@ -36,38 +35,7 @@ if (count($hosts) === 0) {
$hostStateName = Host::getStateText($host->host_state);
$hostLink = $this->href('monitoring/host/show', array('host' => $host->host_name));
- $icons = array();
- if (! $host->host_handled && $host->host_state > 0){
- $icons[] = $this->icon('attention-alt', $this->translate('Unhandled'));
- }
- if ($host->host_acknowledged) {
- $icons[] = $this->icon('ok', $this->translate('Acknowledged'));
- }
-
- if ($host->host_is_flapping) {
- $icons[] = $this->icon('flapping', $this->translate('Flapping'));
- }
-
- if (! $host->host_notifications_enabled) {
- $icons[] = $this->icon('bell-off-empty', $this->translate('Notifications Disabled'));
- }
-
- if ($host->host_in_downtime) {
- $icons[] = $this->icon('plug', $this->translate('In Downtime'));
- }
-
- if (! $host->host_active_checks_enabled) {
- if (! $host->host_passive_checks_enabled) {
- $icons[] = $this->icon('eye-off', $this->translate('Active And Passive Checks Disabled'));
- } else {
- $icons[] = $this->icon('eye-off', $this->translate('Active Checks Disabled'));
- }
- }
-
- if (isset($host->host_last_comment) && $host->host_last_comment !== null) {
- $icons[] = $this->icon('comment', $this->translate('Last Comment: ') . $host->host_last_comment);
- }
?>
@@ -87,7 +55,7 @@ if (count($hosts) === 0) {
host_icon_image && ! preg_match('/[\'"]/', $host->host_icon_image)): ?>
= $this->icon($this->resolveMacros($host->host_icon_image, $host)) ?>
- = implode(' ', $icons) ?>
+ = implode(' ', $this->hostFlags($host)) ?>
= $this->qlink(
$host->host_display_name,
$hostLink,
diff --git a/modules/monitoring/application/views/scripts/list/services.phtml b/modules/monitoring/application/views/scripts/list/services.phtml
index f3e36c18c..63d9076c3 100644
--- a/modules/monitoring/application/views/scripts/list/services.phtml
+++ b/modules/monitoring/application/views/scripts/list/services.phtml
@@ -59,39 +59,7 @@ if (count($services) === 0) {
= $this->perfdata($service->service_perfdata, true, 8) ?>
- service_handled && $service->service_state > 0): ?>
- = $this->icon('attention-alt', $this->translate('Unhandled')) ?>
-
-
- service_acknowledged && !$service->service_in_downtime): ?>
- = $this->icon('ok', $this->translate('Acknowledged') . (
- $service->service_last_ack ? ': ' . $service->service_last_ack : ''
- )) ?>
-
-
- service_is_flapping): ?>
- = $this->icon('flapping', $this->translate('Flapping')) ?>
-
-
- service_notifications_enabled): ?>
- = $this->icon('bell-off-empty', $this->translate('Notifications Disabled')) ?>
-
-
- service_in_downtime): ?>
- = $this->icon('plug', $this->translate('In Downtime')) ?>
-
-
- service_last_comment) && $service->service_last_comment !== null): ?>
- = $this->icon('comment', $this->translate('Last Comment: ') . $service->service_last_comment) ?>
-
-
- service_active_checks_enabled): ?>
- service_passive_checks_enabled): ?>
- = $this->icon('eye-off', $this->translate('Active And Passive Checks Disabled')) ?>
-
- = $this->icon('eye-off', $this->translate('Active Checks Disabled')) ?>
-
-
+ = implode(' ', $this->serviceFlags($service)); ?>
service_icon_image && ! preg_match('/[\'"]/', $service->service_icon_image)): ?>
= $this->icon($this->resolveMacros($service->service_icon_image, $service)) ?>
diff --git a/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml b/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml
index d387202c2..42c6e73cd 100644
--- a/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml
+++ b/modules/monitoring/application/views/scripts/partials/command/objects-command-form.phtml
@@ -1,31 +1,19 @@
+
+ compact): ?>
+ = $tabs; ?>
+
+
+ = $this->render('list/components/servicesummary.phtml') ?>
= $this->render('partials/service/objects-header.phtml'); ?>
+ = $this->render('list/components/hostssummary.phtml') ?>
= $this->render('partials/host/objects-header.phtml'); ?>
+
-
-
-
- = $this->icon('host'); ?> = $this->translate('Host'); ?> |
- = $this->icon('conf'); ?> = $this->translate('Service'); ?> |
-
-
-
- getObjects() as $object): /** @var \Icinga\Module\Monitoring\Object\MonitoredObject $object */ ?>
-
- getType() === $object::TYPE_HOST): ?>
- = $this->escape($object->getName()); ?> |
-
- = $this->escape($object->getHost()->getName()); ?> |
- = $this->escape($object->getName()); ?> |
-
-
-
-
-
= $form; ?>
diff --git a/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml b/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml
index 838a78dd8..17cf9f7fe 100644
--- a/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml
+++ b/modules/monitoring/application/views/scripts/partials/host/objects-header.phtml
@@ -1,13 +1,39 @@
+
+
0): ?>
-
- = sprintf($this->translatePlural('Host (%u)', 'Hosts (%u)', $hostCount), $hostCount); ?>
-
-
- = $hostStatesPieChart; ?>
-
-
- $count): ?>
- = sprintf('%s: %u', $this->translate(strtoupper($text)), $count); ?>
-
-
-
\ No newline at end of file
+
+
+
+ 5) {
+ continue;
+ }
+ ?>
+
+
+ = Host::getStateText($host->host_state, true); ?>
|
+
+ = implode(' ', $this->hostFlags($host)) ?>
+ = $this->escape($host->getName()); ?>
+ = $this->escape($host->host_output) ?>
+ |
+
+
+
+
+
+ =
+ $this->qlink(
+ sprintf($this->translate('list all %d hosts ...'), $i),
+ $listAllLink,
+ null,
+ array('data-base-target' => '_next')
+ );
+ ?>
+
+
+
diff --git a/modules/monitoring/application/views/scripts/partials/host/servicesummary.phtml b/modules/monitoring/application/views/scripts/partials/host/servicesummary.phtml
index c0acdead4..04408808f 100644
--- a/modules/monitoring/application/views/scripts/partials/host/servicesummary.phtml
+++ b/modules/monitoring/application/views/scripts/partials/host/servicesummary.phtml
@@ -3,6 +3,15 @@
use Icinga\Web\Url;
use Icinga\Module\Monitoring\Object\Service;
+function urlAddFilterOptional($url, $filter, $optional) {
+ $url = Url::fromPath($url);
+ $f = $filter;
+ if (isset($optional)) {
+ $f = Filter::matchAll($filter, $optional);
+ }
+ return $url->setQueryString($f->toQueryString());
+}
+
$selfUrl = Url::fromPath('monitoring/show/services', array('host' => $object->host_name));
$currentUrl = Url::fromRequest()->without('limit')->getRelativeUrl();
?>compact ? ' data-base-target="col1"' : ''; ?>>
@@ -31,6 +40,7 @@ $currentUrl = Url::fromRequest()->without('limit')->getRelativeUrl();
= $this->translate('No services configured on this host'); ?>
+
stats->services_ok): ?>
diff --git a/modules/monitoring/application/views/scripts/partials/service/objects-header.phtml b/modules/monitoring/application/views/scripts/partials/service/objects-header.phtml
index 25a7117dd..c51861f03 100644
--- a/modules/monitoring/application/views/scripts/partials/service/objects-header.phtml
+++ b/modules/monitoring/application/views/scripts/partials/service/objects-header.phtml
@@ -1,29 +1,40 @@
+
0): ?>
-
-
- = sprintf($this->translatePlural('Service (%u)', 'Services (%u)', $serviceCount), $serviceCount); ?>
-
+
+
+
+ 5) {
+ continue;
+ }
+ ?>
+
+ = Service::getStateText($service->service_state, true); ?>
|
+
+ = implode(' ', $this->serviceFlags($service)) ?>
+
+ = $this->escape($service->getName()); ?>
+ = $this->translate('on') ?>
+ = $this->escape($service->getHost()->getName()); ?>
+
+ = $this->escape($service->service_output) ?>
+ |
+
+
+
+
- = $serviceStatesPieChart; ?>
+ qlink(
+ sprintf($this->translate('List all %d services ...'), $i),
+ $listAllLink,
+ null,
+ array('data-base-target' => '_next')
+ );
+ ?>
-
- $count): ?>
- = sprintf('%s: %u', $this->translate(strtoupper($text)), $count); ?>
-
-
-
-
-
-
- = sprintf($this->translatePlural('Host (%u)', 'Hosts (%u)', $hostCount), $hostCount); ?>
-
-
- = $hostStatesPieChart; ?>
-
-
- $count): ?>
- = sprintf('%s: %u', $this->translate(strtoupper($text)), $count); ?>
-
-
-
-
\ No newline at end of file
+
diff --git a/modules/monitoring/application/views/scripts/services/show.phtml b/modules/monitoring/application/views/scripts/services/show.phtml
index 8bf45a32c..429f43ea6 100644
--- a/modules/monitoring/application/views/scripts/services/show.phtml
+++ b/modules/monitoring/application/views/scripts/services/show.phtml
@@ -1,127 +1,214 @@
-
- compact): ?>
- = $tabs; ?>
-
+
+
+ compact): ?>
+ = $tabs; ?>
+
+
+ = $this->render('list/components/servicesummary.phtml') ?>
= $this->render('partials/service/objects-header.phtml'); ?>
+
-
+
+
+ = $this->icon('reschedule') ?>
+ = $this->translate('Commands') ?>
+
+
= $this->translate('No services found matching the filter'); ?>
- = sprintf($this->translatePlural('%u Service', '%u Services', $serviceCount), $serviceCount); ?>
- = $this->qlink(
- sprintf($this->translate('List all %u services'), $serviceCount),
- $listAllLink
- ); ?>
-
- = $checkNowForm; ?>
-
- = $this->qlink(
- sprintf($this->translate('Reschedule the next check for all %u services'), $serviceCount),
+
+ = sprintf($this->translatePlural(
+ 'Issue commands to %s selected service:',
+ 'Issue commands to all %s selected services:',
+ count($objects)
+ ), '' . count($objects) . '') ?>
+
+ = $checkNowForm; ?>
+
+ = $this->qlink(
+ $this->translate('Reschedule next checks'),
$rescheduleAllLink,
null,
array('icon' => 'reschedule')
- ); ?>
- = $this->qlink(
- sprintf($this->translate('Schedule a downtime for all %u services'), $serviceCount),
+ ); ?>
+
+
+ = $this->qlink(
+ $this->translate('Schedule downtimes'),
$downtimeAllLink,
null,
array('icon' => 'plug')
- ); ?>
- = $this->qlink(
- sprintf($this->translate('Submit a passive check result for all %u services'), $serviceCount),
+ ); ?>
+
+
+ = $this->qlink(
+ $this->translate('Submit passive check results'),
$processCheckResultAllLink,
null,
array('icon' => 'reply')
- ); ?>
- hasPermission('monitoring/command/send-custom-notification')): ?>
- = $this->qlink(
- sprintf($this->translate('Send a custom notification for all %u services'), $serviceCount),
- $sendCustomNotificationLink,
- null,
- array('icon' => 'comment')
- ); ?>
-
- 0): ?>
-
- = sprintf(
- $this->translatePlural(
- '%u Unhandled Service Problem',
- '%u Unhandled Service Problems',
- $unhandledCount
- ),
- $unhandledCount
- ); ?>
- = $this->qlink(
- sprintf(
- $this->translatePlural(
- 'Schedule a downtime for %u unhandled service problem',
- 'Schedule a downtime for %u unhandled service problems',
- $unhandledCount
- ),
- $unhandledCount
- ),
- $downtimeUnhandledLink,
- null,
- array('icon' => 'plug')
- ); ?>
- = $this->qlink(
- sprintf(
- $this->translatePlural(
- 'Acknowledge %u unhandled service problem',
- 'Acknowledge %u unhandled service problems',
- $unhandledCount
- ),
- $unhandledCount
- ),
- $acknowledgeUnhandledLink,
- null,
- array('icon' => 'ok')
- ); ?>
-
-
- 0): ?>
-
- = sprintf(
- $this->translatePlural(
- '%u Acknowledged Service Problem',
- '%u Acknowledged Service Problems',
- $acknowledgedCount
- ),
- $acknowledgedCount
- ); ?>
- = $removeAckForm ?>
-
-
- 0): ?>
- = $this->qlink(
- sprintf(
- $this->translatePlural(
- 'List %u service currently in downtime',
- 'List %u services currently in downtime',
- $inDowntimeCount
- ),
- $inDowntimeCount
- ),
- $inDowntimeLink,
- null,
- array('icon' => 'plug')
- ); ?>
-
- getComments())) > 0): ?>
- = $this->qlink(
- sprintf(
- $this->translatePlural(
- 'List %u service comment',
- 'List %u service comments',
- $commentCount
- ),
- $commentCount
- ),
- $commentsLink,
+ ); ?>
+
+
+ = $this->qlink(
+ $this->translate('Add comments'),
+ $addCommentLink,
null,
array('icon' => 'comment')
- ); ?>
-
+ ); ?>
+
+ hasPermission('monitoring/command/send-custom-notification')): ?>
+
+ = $this->qlink(
+ sprintf($this->translate('Send a custom notification for all %u services'), $serviceCount),
+ $sendCustomNotificationLink,
+ null,
+ array('icon' => 'comment')
+ ); ?>
+
+
+
+
+
+
+
+ = $this->icon('attention-alt') ?>
+ = $this->translate('Problems') ?>
+
+
+
+
+ = sprintf(
+ $this->translatePlural(
+ 'There is %s problem, issue commands to the problem service',
+ 'There are %s problems, issue commands to the problem services',
+ $problemCount
+ ),
+ '' . $problemCount . ''
+ ); ?>
+
+ = $this->qlink(
+ sprintf(
+ $this->translatePlural(
+ 'Schedule a downtime for %s problem service',
+ 'Schedule downtimes for %s problem services',
+ $problemCount
+ ),
+ $problemCount
+ ),
+ $downtimeLink,
+ null,
+ array('icon' => 'plug')
+ ); ?>
+
+
+
+
+ = sprintf($this->translate('There are %s unhandled problem services. ' .
+ 'Issue commands to the problematic services:'),
+ '' . $unhandledCount . '') ?>
+
+
+ = $this->qlink(
+ sprintf(
+ $this->translatePlural(
+ 'Schedule a downtime for %u unhandled problem service',
+ 'Schedule a downtime for %u unhandled problem services',
+ $unhandledCount
+ ),
+ $unhandledCount
+ ),
+ $downtimeUnhandledLink,
+ null,
+ array('icon' => 'plug')
+ ); ?>
+
+
+ = $this->qlink(
+ sprintf(
+ $this->translatePlural(
+ 'Acknowledge %u unhandled problem service',
+ 'Acknowledge %u unhandled problem services',
+ $unhandledCount
+ ),
+ $unhandledCount
+ ),
+ $acknowledgeUnhandledLink,
+ null,
+ array('icon' => 'ok')
+ ); ?>
+
+
+
+
+
+ 0): ?>
+ = $this->icon('ok', $this->translate('Acknowledgements')) ?> = $this->translate('Acknowledgements') ?>
+
+ = sprintf(
+ $this->translatePlural(
+ '%s Acknowledged Service Problem.',
+ '%s Acknowledged Service Problems.',
+ $acknowledgedCount
+ ),
+ '' . $acknowledgedCount . ''
+ ); ?> = $removeAckForm ?>
+
-
\ No newline at end of file
+
+ getScheduledDowntimes()) ?>
+
+
+ = $this->icon('plug', $this->translate('Downtimes')) ?> = $this->translate('Downtimes') ?>
+ = $this->qlink(
+ sprintf(
+ $this->translatePlural(
+ '%s scheduled downtime',
+ '%s scheduled downtimes',
+ $scheduledDowntimeCount
+ ),
+ $scheduledDowntimeCount
+ ),
+ $showDowntimesLink,
+ null,
+ array('data-base-target' => '_next')
+ );?>
+ = sprintf($this->translate('on all selected services.')) ?>
+
+ 0): ?>
+
+ = $this->qlink(
+ sprintf($this->translatePlural(
+ '%s service',
+ '%s services',
+ $inDowntimeCount
+ ), $inDowntimeCount),
+ $inDowntimeLink,
+ null,
+ array('data-base-target' => '_next')
+ );?>
+ = sprintf($this->translate('are currently in downtime.')) ?>
+
+
+
+ getComments()) ?>
+ 0): ?>
+ = $this->icon('comment') ?> = $this->translate('Comments') ?>
+ = $this->qlink(
+ sprintf(
+ $this->translatePlural(
+ '%s comment.',
+ '%s comments.',
+ $commentCount
+ ), $commentCount),
+ $commentsLink,
+ null,
+ array('data-base-target' => '_next')
+ ); ?>
+ = $this->translate('on all selected services.') ?>
+
+
+
diff --git a/modules/monitoring/library/Monitoring/Object/HostList.php b/modules/monitoring/library/Monitoring/Object/HostList.php
index f0adced24..2aa5bb04f 100644
--- a/modules/monitoring/library/Monitoring/Object/HostList.php
+++ b/modules/monitoring/library/Monitoring/Object/HostList.php
@@ -3,6 +3,10 @@
namespace Icinga\Module\Monitoring\Object;
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterOr;
+use Icinga\Util\String;
+
/**
* A host list
*/
@@ -25,4 +29,74 @@ class HostList extends ObjectList
}
return $hosts;
}
+
+ /**
+ * Create a state summary of all hosts that can be consumed by hostssummary.phtml
+ *
+ * @return object The summary
+ */
+ public function getStateSummary()
+ {
+ $hostStates = array_fill_keys(self::getHostStatesSummaryEmpty(), 0);
+ foreach ($this as $host) {
+ $unhandled = (bool) $host->problem === true && (bool) $host->handled === false;
+
+ $stateName = 'hosts_' . $host::getStateText($host->state);
+ ++$hostStates[$stateName];
+ ++$hostStates[$stateName. ($unhandled ? '_unhandled' : '_handled')];
+ }
+
+ $hostStates['hosts_total'] = count($this);
+
+ return (object)$hostStates;
+ }
+
+ /**
+ * Return an empty array with all possible host state names
+ *
+ * @return array An array containing all possible host states as keys and 0 as values.
+ */
+ public static function getHostStatesSummaryEmpty()
+ {
+ return String::cartesianProduct(
+ array(
+ array('hosts'),
+ array(
+ Host::getStateText(Host::STATE_UP),
+ Host::getStateText(Host::STATE_DOWN),
+ Host::getStateText(Host::STATE_UNREACHABLE),
+ Host::getStateText(Host::STATE_PENDING)
+ ),
+ array(null, 'handled', 'unhandled')
+ ),
+ '_'
+ );
+ }
+
+ /**
+ * Returns a Filter that matches all hosts in this list
+ *
+ * @return Filter
+ */
+ public function objectsFilter($columns = array('host' => 'host'))
+ {
+ $filterExpression = array();
+ foreach ($this as $host) {
+ $filterExpression[] = Filter::where($columns['host'], $host->getName());
+ }
+ return FilterOr::matchAny($filterExpression);
+ }
+
+ /**
+ * Get the scheduled downtimes
+ *
+ * @return type
+ */
+ public function getScheduledDowntimes()
+ {
+ return $this->backend->select()
+ ->from('downtime')
+ ->applyFilter(clone $this->filter)
+ ->where('downtime_objecttype', 'host');
+ }
}
diff --git a/modules/monitoring/library/Monitoring/Object/ObjectList.php b/modules/monitoring/library/Monitoring/Object/ObjectList.php
index 146499805..75fe1ba76 100644
--- a/modules/monitoring/library/Monitoring/Object/ObjectList.php
+++ b/modules/monitoring/library/Monitoring/Object/ObjectList.php
@@ -5,21 +5,40 @@ namespace Icinga\Module\Monitoring\Object;
use ArrayIterator;
use Countable;
+use Icinga\Data\Filter\Filter;
use IteratorAggregate;
use Icinga\Module\Monitoring\Backend\MonitoringBackend;
abstract class ObjectList implements Countable, IteratorAggregate
{
+ /**
+ * @var string
+ */
protected $dataViewName;
+ /**
+ * @var MonitoringBackend
+ */
protected $backend;
+ /**
+ * @var array
+ */
protected $columns;
+ /**
+ * @var Filter
+ */
protected $filter;
+ /**
+ * @var array
+ */
protected $objects;
+ /**
+ * @var int
+ */
protected $count;
public function __construct(MonitoringBackend $backend)
@@ -27,23 +46,39 @@ abstract class ObjectList implements Countable, IteratorAggregate
$this->backend = $backend;
}
+ /**
+ * @param array $columns
+ *
+ * @return $this
+ */
public function setColumns(array $columns)
{
$this->columns = $columns;
return $this;
}
+ /**
+ * @return array
+ */
public function getColumns()
{
return $this->columns;
}
+ /**
+ * @param $filter
+ *
+ * @return $this
+ */
public function setFilter($filter)
{
$this->filter = $filter;
return $this;
}
+ /**
+ * @return Filter
+ */
public function getFilter()
{
return $this->filter;
@@ -51,6 +86,9 @@ abstract class ObjectList implements Countable, IteratorAggregate
abstract protected function fetchObjects();
+ /**
+ * @return array
+ */
public function fetch()
{
if ($this->objects === null) {
@@ -59,6 +97,9 @@ abstract class ObjectList implements Countable, IteratorAggregate
return $this->objects;
}
+ /**
+ * @return int
+ */
public function count()
{
if ($this->count === null) {
@@ -85,4 +126,94 @@ abstract class ObjectList implements Countable, IteratorAggregate
{
return $this->backend->select()->from('comment')->applyFilter($this->filter);
}
+
+ /**
+ * Get the scheduled downtimes
+ *
+ * @return type
+ */
+ public function getScheduledDowntimes()
+ {
+ return $this->backend->select()->from('downtime')->applyFilter($this->filter);
+ }
+
+ /**
+ * @return ObjectList
+ */
+ public function getAcknowledgedObjects()
+ {
+ $acknowledgedObjects = array();
+ foreach ($this as $object) {
+ if ((bool) $object->acknowledged === true) {
+ $acknowledgedObjects[] = $object;
+ }
+ }
+ return $this->newFromArray($acknowledgedObjects);
+ }
+
+ /**
+ * @return ObjectList
+ */
+ public function getObjectsInDowntime()
+ {
+ $objectsInDowntime = array();
+ foreach ($this as $object) {
+ if ((bool) $object->in_downtime === true) {
+ $objectsInDowntime[] = $object;
+ }
+ }
+ return $this->newFromArray($objectsInDowntime);
+ }
+
+ /**
+ * @return ObjectList
+ */
+ public function getUnhandledObjects()
+ {
+ $unhandledObjects = array();
+ foreach ($this as $object) {
+ if ((bool) $object->problem === true && (bool) $object->handled === false) {
+ $unhandledObjects[] = $object;
+ }
+ }
+ return $this->newFromArray($unhandledObjects);
+ }
+
+ /**
+ * @return ObjectList
+ */
+ public function getProblemObjects()
+ {
+ $handledObjects = array();
+ foreach ($this as $object) {
+ if ((bool) $object->problem === true) {
+ $handledObjects[] = $object;
+ }
+ }
+ return $this->newFromArray($handledObjects);
+ }
+
+ /**
+ * Create a ObjectList from an array of hosts without querying a backend
+ *
+ * @return ObjectList
+ */
+ protected function newFromArray(array $objects)
+ {
+ $class = get_called_class();
+ $list = new $class($this->backend);
+ $list->objects = $objects;
+ $list->count = count($objects);
+ $list->filter = $list->objectsFilter();
+ return $list;
+ }
+
+ /**
+ * Create a filter that matches exactly the elements of this object list
+ *
+ * @param array $columns Override default column names.
+ *
+ * @return Filter
+ */
+ abstract function objectsFilter($columns = array());
}
diff --git a/modules/monitoring/library/Monitoring/Object/ServiceList.php b/modules/monitoring/library/Monitoring/Object/ServiceList.php
index d9ffa0d8e..5ae9b8193 100644
--- a/modules/monitoring/library/Monitoring/Object/ServiceList.php
+++ b/modules/monitoring/library/Monitoring/Object/ServiceList.php
@@ -3,11 +3,19 @@
namespace Icinga\Module\Monitoring\Object;
+use Icinga\Data\Filter\Filter;
+use Icinga\Data\Filter\FilterOr;
+use Icinga\Util\String;
+
/**
* A service list
*/
class ServiceList extends ObjectList
{
+ protected $hostStateSummary;
+
+ protected $serviceStateSummary;
+
protected $dataViewName = 'serviceStatus';
protected $columns = array('host_name', 'service_description');
@@ -25,4 +33,118 @@ class ServiceList extends ObjectList
}
return $services;
}
+
+ /**
+ * Create a state summary of all services that can be consumed by servicesummary.phtml
+ *
+ * @return object The summary
+ */
+ public function getServiceStateSummary()
+ {
+ if (! $this->serviceStateSummary) {
+ $this->initStateSummaries();
+ }
+ return (object)$this->serviceStateSummary;
+ }
+
+ /**
+ * Create a state summary of all hosts that can be consumed by hostsummary.phtml
+ *
+ * @return object The summary
+ */
+ public function getHostStateSummary()
+ {
+ if (! $this->hostStateSummary) {
+ $this->initStateSummaries();
+ }
+ return (object)$this->hostStateSummary;
+ }
+
+ /**
+ * Calculate the current state summary and populate hostStateSummary and serviceStateSummary
+ * properties
+ */
+ protected function initStateSummaries()
+ {
+ $serviceStates = array_fill_keys(self::getServiceStatesSummaryEmpty(), 0);
+ $hostStates = array_fill_keys(HostList::getHostStatesSummaryEmpty(), 0);
+
+ foreach ($this as $service) {
+ $unhandled = false;
+ if ((bool) $service->problem === true && (bool) $service->handled === false) {
+ $unhandled = true;
+ }
+
+ $stateName = 'services_' . $service::getStateText($service->state);
+ ++$serviceStates[$stateName];
+ ++$serviceStates[$stateName . ($unhandled ? '_unhandled' : '_handled')];
+
+ if (! isset($knownHostStates[$service->getHost()->getName()])) {
+ $unhandledHost = (bool) $service->host_problem === true && (bool) $service->host_handled === false;
+ ++$hostStates['hosts_' . $service->getHost()->getStateText($service->host_state)];
+ ++$hostStates['hosts_' . $service->getHost()->getStateText($service->host_state)
+ . ($unhandledHost ? '_unhandled' : '_handled')];
+ $knownHostStates[$service->getHost()->getName()] = true;
+ }
+ }
+
+ $serviceStates['services_total'] = count($this);
+ $this->hostStateSummary = $hostStates;
+ $this->serviceStateSummary = $serviceStates;
+ }
+
+ /**
+ * Return an empty array with all possible host state names
+ *
+ * @return array An array containing all possible host states as keys and 0 as values.
+ */
+ public static function getServiceStatesSummaryEmpty()
+ {
+ return String::cartesianProduct(
+ array(
+ array('services'),
+ array(
+ Service::getStateText(Service::STATE_OK),
+ Service::getStateText(Service::STATE_WARNING),
+ Service::getStateText(Service::STATE_CRITICAL),
+ Service::getStateText(Service::STATE_UNKNOWN),
+ Service::getStateText(Service::STATE_PENDING)
+ ),
+ array(null, 'handled', 'unhandled')
+ ),
+ '_'
+ );
+ }
+
+ /**
+ * Returns a Filter that matches all hosts in this HostList
+ *
+ * @param array $columns Override filter column names
+ *
+ * @return Filter
+ */
+ public function objectsFilter($columns = array('host' => 'host', 'service' => 'service'))
+ {
+ $filterExpression = array();
+ foreach ($this as $service) {
+ $filterExpression[] = Filter::matchAll(
+ Filter::where($columns['host'], $service->getHost()->getName()),
+ Filter::where($columns['service'], $service->getName())
+ );
+ }
+ return FilterOr::matchAny($filterExpression);
+ }
+
+ /**
+ * Get the scheduled downtimes
+ *
+ * @return type
+ */
+ public function getScheduledDowntimes()
+ {
+ return $this->backend->select()
+ ->from('downtime')
+ ->applyFilter(clone $this->filter)
+ ->where('downtime_objecttype', 'service');
+ }
}
diff --git a/modules/monitoring/public/css/module.less b/modules/monitoring/public/css/module.less
index ee4c931e5..357948373 100644
--- a/modules/monitoring/public/css/module.less
+++ b/modules/monitoring/public/css/module.less
@@ -90,7 +90,7 @@ div.contacts div.notification-periods {
margin-top: 0.5em;
}
-div.tinystatesummary {
+.tinystatesummary {
.page-header();
font-size: 1em;
margin-bottom: 0.5em;
@@ -99,6 +99,7 @@ div.tinystatesummary {
display: inline-block;
margin-bottom: 4px;
margin-left: 1em;
+ height: auto;
}
.state > a {
@@ -130,14 +131,26 @@ span.state.ok {
background: @colorOk;
}
+span.state.up {
+ background: @colorOk;
+}
+
span.state.critical {
background: @colorCritical;
}
+span.state.down {
+ background: @colorCritical;
+}
+
span.state.handled.critical {
background: @colorCriticalHandled;
}
+span.state.handled.down {
+ background: @colorCriticalHandled;
+}
+
span.state.warning {
background: @colorWarning;
}
@@ -198,7 +211,7 @@ div.selection-info {
.optionbox label {
max-width: 6.5em;
text-align: left;
- vertical-align: middle;
+ vertgical-align: middle;
margin-right: 0em;
}
diff --git a/public/css/icinga/layout-structure.less b/public/css/icinga/layout-structure.less
index 9d0d38def..63be9f546 100644
--- a/public/css/icinga/layout-structure.less
+++ b/public/css/icinga/layout-structure.less
@@ -346,6 +346,7 @@ html {
.hbox-item {
display: inline-block;
vertical-align: top;
+ margin-top: 0.5em;
margin-bottom: 0.25em;
margin-left: 1em;
margin-right: 1em;
@@ -371,3 +372,7 @@ html {
position: absolute;
width: 1px;
}
+
+.no-padding-top {
+ padding-top: 0em;
+}
diff --git a/public/css/icinga/monitoring-colors.less b/public/css/icinga/monitoring-colors.less
index 8ab95b3cc..4902bebb1 100644
--- a/public/css/icinga/monitoring-colors.less
+++ b/public/css/icinga/monitoring-colors.less
@@ -926,3 +926,44 @@ table.groupview {
}
/* End of monitoring groupsummary styles */
+
+/* compact table */
+table.statesummary {
+ text-align: left;
+ width: auto;
+ border-collapse: separate;
+
+ td {
+ padding: 0em 0.4em 0em 0.4em;
+ line-height: 1.2em;
+ }
+
+ tr.state td.state {
+ width: auto;
+ font-weight: bold;
+ }
+
+ td {
+ font-size: 0.9em;
+ line-height: 1.2em;
+ padding-left: 0.2em;
+ margin: 0;
+ }
+
+ td.state {
+ padding: 0.2em;
+ min-width: 75px;
+ font-size: 0.75em;
+ text-align: center;
+ }
+
+ td.name {
+ font-weight: bold;
+ }
+
+ td a {
+ color: inherit;
+ text-decoration: none;
+ }
+}
+
diff --git a/public/css/icinga/widgets.less b/public/css/icinga/widgets.less
index 1993704b6..7e6789dff 100644
--- a/public/css/icinga/widgets.less
+++ b/public/css/icinga/widgets.less
@@ -217,23 +217,13 @@ li li .badge-container {
margin-right: 0.75em;
}
-/*
-#layout.hoveredmenu .active > .badge-container {
- display: none;
-}
-
-#layout.hoveredmenu .hover > .badge-container {
- //margin-right: 14.15em;
- display: none;
-}
-*/
-
.badge {
position: relative;
- top: 0.3em;
+ top: -0.15em;
display: inline-block;
min-width: 1em;
padding: 3px 7px;
+ margin: 0 0.2em 0 0.2em;
font-size: 0.8em;
font-weight: 700;
line-height: 1.1em;
@@ -244,6 +234,11 @@ li li .badge-container {
background-color: @colorInvalid;
}
+#menu nav ul .badge {
+ margin-right: 0em;
+ top: 0.3em;
+}
+
#menu nav > ul > li.active > .badge-container {
display: none;
}
@@ -279,6 +274,10 @@ li li .badge {
background-color: @colorCritical;
}
+.badge-down {
+ background-color: @colorCritical;
+}
+
.badge-warning {
background-color: @colorWarning;
}
@@ -287,11 +286,15 @@ li li .badge {
background-color: @colorOk;
}
+.badge-up {
+ background-color: @colorOk;
+}
+
.badge-pending {
background-color: @colorPending;
}
-.badge-pending {
+.badge-unknown {
background-color: @colorUnknown;
}
@@ -313,3 +316,25 @@ li li .badge {
margin: 0em 0em 0em 0.1em;
}
+
+.tipsy .tipsy-inner {
+ // overwrite tooltip max width, we need them to grow bigger
+ max-width: 300px;
+ text-align: left;
+}
+
+.color-box {
+ position: relative;
+ top: 2px;
+ margin: 0px 3px 0px 3px;
+ display: inline-block;
+ width: 12px;
+ height: 12px;
+}
+
+.oneline {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
|