summaryrefslogtreecommitdiffstats
path: root/modules/monitoring/application/clicommands/ListCommand.php
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--modules/monitoring/application/clicommands/ListCommand.php400
1 files changed, 400 insertions, 0 deletions
diff --git a/modules/monitoring/application/clicommands/ListCommand.php b/modules/monitoring/application/clicommands/ListCommand.php
new file mode 100644
index 0000000..6dc4193
--- /dev/null
+++ b/modules/monitoring/application/clicommands/ListCommand.php
@@ -0,0 +1,400 @@
+<?php
+/* Icinga Web 2 | (c) 2013 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Monitoring\Clicommands;
+
+use Icinga\Module\Monitoring\Backend\MonitoringBackend;
+use Icinga\Module\Monitoring\Cli\CliUtils;
+use Icinga\Date\DateFormatter;
+use Icinga\Cli\Command;
+use Icinga\File\Csv;
+use Icinga\Module\Monitoring\Plugin\PerfdataSet;
+use Exception;
+use Icinga\Util\Json;
+
+/**
+ * Icinga monitoring objects
+ *
+ * This module is your interface to the Icinga monitoring application.
+ */
+class ListCommand extends Command
+{
+ protected $backend;
+ protected $dumpSql;
+ protected $defaultActionName = 'status';
+
+ public function init()
+ {
+ $this->backend = MonitoringBackend::instance($this->params->shift('backend'));
+ $this->dumpSql = $this->params->shift('showsql');
+ }
+
+ protected function getQuery($table, $columns)
+ {
+ $limit = $this->params->shift('limit');
+ $format = $this->params->shift('format');
+ if ($format !== null) {
+ if ($this->params->has('columns')) {
+ $columnParams = preg_split(
+ '/,/',
+ $this->params->shift('columns')
+ );
+ $columns = array();
+ foreach ($columnParams as $col) {
+ if (false !== ($pos = strpos($col, '='))) {
+ $columns[substr($col, 0, $pos)] = substr($col, $pos + 1);
+ } else {
+ $columns[] = $col;
+ }
+ }
+ }
+ }
+
+ $query = $this->backend->select()->from($table, $columns);
+ if ($limit) {
+ $query->limit($limit, $this->params->shift('offset'));
+ }
+ foreach ($this->params->getParams() as $col => $filter) {
+ $query->where($col, $filter);
+ }
+ // $query->applyFilters($this->params->getParams());
+ if ($this->dumpSql) {
+ echo wordwrap($query->dump(), 72);
+ exit;
+ }
+
+ if ($format !== null) {
+ $this->showFormatted($query, $format, $columns);
+ }
+
+ return $query;
+ }
+
+ protected function showFormatted($query, $format, $columns)
+ {
+ $query = $query->getQuery();
+ switch ($format) {
+ case 'json':
+ echo Json::sanitize($query->fetchAll());
+ break;
+ case 'csv':
+ Csv::fromQuery($query)->dump();
+ break;
+ default:
+ preg_match_all('~\$([a-z0-9_-]+)\$~', $format, $m);
+ $words = array();
+ foreach ($columns as $key => $col) {
+ if (is_numeric($key)) {
+ if (in_array($col, $m[1])) {
+ $words[] = $col;
+ }
+ } else {
+ if (in_array($key, $m[1])) {
+ $words[] = $key;
+ }
+ }
+ }
+ foreach ($query->fetchAll() as $row) {
+ $output = $format;
+ foreach ($words as $word) {
+ $output = preg_replace(
+ '~\$' . $word . '\$~',
+ $row->{$word},
+ $output
+ );
+ }
+ echo $output . "\n";
+ }
+ }
+ exit;
+ }
+
+ /**
+ * List and filter hosts
+ *
+ * This command allows you to search and visualize your hosts in
+ * different ways.
+ *
+ * USAGE
+ *
+ * icingacli monitoring list hosts [options]
+ *
+ * OPTIONS
+ *
+ * --verbose Show detailled output
+ * --showsql Dump generated SQL query (DB backend only)
+ *
+ * --format=<csv|json|<custom>>
+ * Dump columns in the given format. <custom> format allows $column$
+ * placeholders, e.g. --format='$host$: $service$'. This requires
+ * that the columns are specified within the --columns parameter.
+ *
+ * --<column>[=filter]
+ * Filter given column by optional filter. Boolean (1/0) columns are
+ * true if no filter value is given.
+ *
+ * --problems
+ * Only show unhandled problems (HARD state and not acknowledged/in downtime).
+ *
+ * --columns='<comma separated list of host/service columns>'
+ * Add a limited set of columns to the output. The following host
+ * attributes can be fetched: state, handled, output, acknowledged, in_downtime, perfdata last_state_change
+ *
+ * EXAMPLES
+ *
+ * icingacli monitoring list hosts --problems
+ * icingacli monitoring list hosts --problems --host_state_type 0
+ * icingacli monitoring list hosts --host=local*
+ * icingacli monitoring list hosts --columns 'host,host_output' \
+ * --format='$host$ ($host_output$)'
+ */
+ public function hostsAction()
+ {
+ $columns = array(
+ 'host_name',
+ 'host_state',
+ 'host_output',
+ 'host_handled',
+ 'host_acknowledged',
+ 'host_in_downtime'
+ );
+ $query = $this->getQuery('hoststatus', $columns)
+ ->order('host_name');
+ echo $this->renderStatusQuery($query);
+ }
+
+ /**
+ * List and filter services
+ *
+ * This command allows you to search and visualize your services in
+ * different ways.
+ *
+ * USAGE
+ *
+ * icingacli monitoring list services [options]
+ *
+ * OPTIONS
+ *
+ * --verbose Show detailled output
+ * --showsql Dump generated SQL query (DB backend only)
+ *
+ * --format=<csv|json|<custom>>
+ * Dump columns in the given format. <custom> format allows $column$
+ * placeholders, e.g. --format='$host$: $service$'. This requires
+ * that the columns are specified within the --columns parameter.
+ *
+ * --<column>[=filter]
+ * Filter given column by optional filter. Boolean (1/0) columns are
+ * true if no filter value is given.
+ *
+ * --problems
+ * Only show unhandled problems (HARD state and not acknowledged/in downtime).
+ *
+ * --columns='<comma separated list of host/service columns>'
+ * Add a limited set of columns to the output. The following service
+ * attributes can be fetched: state, handled, output, acknowledged, in_downtime, perfdata last_state_change
+ *
+ * EXAMPLES
+ *
+ * icingacli monitoring list services --problems
+ * icingacli monitoring list services --problems --service_state_type 0
+ * icingacli monitoring list services --host=local* --service=*disk*
+ * icingacli monitoring list services --columns 'host,service,service_output' \
+ * --format='$host$: $service$ ($service_output$)'
+ */
+ public function servicesAction()
+ {
+ $columns = array(
+ 'host_name',
+ 'host_state',
+ 'host_output',
+ 'host_handled',
+ 'host_acknowledged',
+ 'host_in_downtime',
+ 'service_description',
+ 'service_state',
+ 'service_acknowledged',
+ 'service_in_downtime',
+ 'service_handled',
+ 'service_output',
+ 'service_perfdata',
+ 'service_last_state_change'
+ );
+ $query = $this->getQuery('servicestatus', $columns)
+ ->order('host_name');
+ echo $this->renderStatusQuery($query);
+ }
+
+ protected function renderStatusQuery($query)
+ {
+ $out = '';
+ $last_host = null;
+ $screen = $this->screen;
+ $utils = new CliUtils($screen);
+ $maxCols = $screen->getColumns();
+ $query = $query->getQuery();
+ $rows = $query->fetchAll();
+ $count = $query->count();
+ $count = count($rows);
+
+ for ($i = 0; $i < $count; $i++) {
+ $row = & $rows[$i];
+
+ $utils->setHostState($row->host_state);
+ if (! array_key_exists($i + 1, $rows)
+ || $row->host_name !== $rows[$i + 1]->host_name
+ ) {
+ $lastService = true;
+ } else {
+ $lastService = false;
+ }
+
+ $hostUnhandled = ! ($row->host_state == 0 || $row->host_handled);
+
+ if ($row->host_name !== $last_host) {
+ if (isset($row->service_description)) {
+ $out .= "\n";
+ }
+
+ $hostTxt = $utils->shortHostState();
+ if ($hostUnhandled) {
+ $out .= $utils->hostStateBackground(
+ sprintf(' %s ', $utils->shortHostState())
+ );
+ } else {
+ $out .= sprintf(
+ '%s %s ',
+ $utils->hostStateBackground(' '),
+ $utils->shortHostState()
+ );
+ }
+ $out .= sprintf(
+ " %s%s: %s\n",
+ $screen->underline($row->host_name),
+ $screen->colorize($utils->objectStateFlags('host', $row), 'lightblue'),
+ $row->host_output
+ );
+
+ if (isset($row->services_ok)) {
+ $out .= sprintf(
+ "%d services, %d problems (%d unhandled), %d OK\n",
+ $row->services_cnt,
+ $row->services_problem,
+ $row->services_problem_unhandled,
+ $row->services_ok
+ );
+ }
+ }
+
+ $last_host = $row->host_name;
+ if (! isset($row->service_description)) {
+ continue;
+ }
+
+ $utils->setServiceState($row->service_state);
+ $serviceUnhandled = ! (
+ $row->service_state == 0 || $row->service_handled
+ );
+
+ if ($lastService) {
+ $straight = ' ';
+ $leaf = '└';
+ } else {
+ $straight = '│';
+ $leaf = '├';
+ }
+ $out .= $utils->hostStateBackground(' ');
+
+ if ($serviceUnhandled) {
+ $out .= $utils->serviceStateBackground(
+ sprintf(' %s ', $utils->shortServiceState())
+ );
+ $emptyBg = ' ';
+ $emptySpace = '';
+ } else {
+ $out .= sprintf(
+ '%s %s ',
+ $utils->serviceStateBackground(' '),
+ $utils->shortServiceState()
+ );
+ $emptyBg = ' ';
+ $emptySpace = ' ';
+ }
+
+ $emptyLine = "\n"
+ . $utils->hostStateBackground(' ')
+ . $utils->serviceStateBackground($emptyBg)
+ . $emptySpace
+ . ' ' . $straight . ' ';
+
+ $perf = '';
+ try {
+ $pset = PerfdataSet::fromString($row->service_perfdata);
+ $perfs = array();
+ foreach ($pset as $p) {
+ if ($percent = $p->getPercentage()) {
+ if ($percent < 0 || $percent > 100) {
+ continue;
+ }
+ $perfs[] = ' '
+ . $p->getLabel()
+ . ': '
+ . $this->getPercentageSign($percent)
+ . ' '
+ . number_format($percent, 2, ',', '.')
+ . '%';
+ }
+ }
+ if (! empty($perfs)) {
+ $perf = ', ' . implode($perfs);
+ }
+ // TODO: fix wordwarp, then remove this line:
+ $perf = '';
+ } catch (Exception $e) {
+ // Ignoring perfdata errors right now, we could show some hint
+ }
+
+ $wrappedOutput = wordwrap(
+ preg_replace('~\@{3,}~', '@@@', $row->service_output),
+ $maxCols - 13
+ ) . "\n";
+ $out .= sprintf(
+ " %1s─ %s%s (%s)",
+ $leaf,
+ $screen->underline($row->service_description),
+ $screen->colorize($utils->objectStateFlags('service', $row) . $perf, 'lightblue'),
+ ucfirst(DateFormatter::timeSince($row->service_last_state_change))
+ );
+ if ($this->isVerbose) {
+ $out .= $emptyLine . preg_replace(
+ '/\n/',
+ $emptyLine,
+ $wrappedOutput
+ ) . "\n";
+ } else {
+ $out .= "\n";
+ }
+ }
+
+ $out .= "\n";
+ return $out;
+ }
+
+ protected function getPercentageSign($percent)
+ {
+ $circles = array(
+ 0 => '○',
+ 15 => '◔',
+ 40 => '◑',
+ 65 => '◕',
+ 90 => '●',
+ );
+ $last = $circles[0];
+ foreach ($circles as $cur => $circle) {
+ if ($percent < $cur) {
+ return $last;
+ }
+ $last = $circle;
+ }
+ }
+}