summaryrefslogtreecommitdiffstats
path: root/application/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'application/controllers')
-rw-r--r--application/controllers/ConfigController.php25
-rw-r--r--application/controllers/DataController.php213
-rw-r--r--application/controllers/IndexController.php93
3 files changed, 331 insertions, 0 deletions
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
new file mode 100644
index 0000000..8ddf94f
--- /dev/null
+++ b/application/controllers/ConfigController.php
@@ -0,0 +1,25 @@
+<?php
+
+namespace Icinga\Module\Map\Controllers;
+
+use Icinga\Module\Map\Forms\Config\GeneralConfigForm;
+use Icinga\Web\Controller;
+
+class ConfigController extends Controller
+{
+ public function init()
+ {
+ $this->assertPermission('config/modules');
+ }
+
+ public function indexAction()
+ {
+ $form = new GeneralConfigForm();
+ $form->setIniConfig($this->Config());
+ $form->handleRequest();
+
+ $this->view->form = $form;
+ $this->view->tabs = $this->Module()->getConfigTabs()->activate('config');
+ }
+}
+
diff --git a/application/controllers/DataController.php b/application/controllers/DataController.php
new file mode 100644
index 0000000..c6051eb
--- /dev/null
+++ b/application/controllers/DataController.php
@@ -0,0 +1,213 @@
+<?php
+
+namespace Icinga\Module\Map\Controllers;
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Module\Monitoring\Controller;
+use Icinga\Module\Monitoring\DataView\DataView;
+
+class DataController extends Controller
+{
+ /**
+ * Apply filters on a DataView
+ *
+ * @param DataView $dataView The DataView to apply filters on
+ *
+ * @return DataView $dataView
+ */
+ protected function filterQuery(DataView $dataView)
+ {
+ $this->setupFilterControl($dataView, null, null, ['stateType', 'objectType', 'problems']);
+ return $dataView;
+ }
+
+ private $stateColumn;
+ private $stateChangeColumn;
+
+ /**
+ * Get JSON state objects
+ */
+ public function pointsAction()
+ {
+ $points = array();
+
+ try {
+ // Borrowed from monitoring module
+ // Handle soft and hard states
+ $config = $this->config();
+ $stateType = strtolower($this->params->shift('stateType',
+ $config->get('map', 'stateType', 'soft')
+ ));
+
+ $userPreferences = $this->Auth()->getUser()->getPreferences();
+ if ($userPreferences->has("map")) {
+ $stateType = $userPreferences->getValue("map", "stateType", $stateType);
+ }
+
+ $filter = (bool)$this->params->shift('problems', false) ? Filter::where('service_problem', 1) : null;
+
+ $objectType = strtolower($this->params->shift('objectType', 'all'));
+
+ if ($stateType === 'hard') {
+ $this->stateColumn = 'hard_state';
+ $this->stateChangeColumn = 'last_hard_state_change';
+ } else {
+ $this->stateColumn = 'state';
+ $this->stateChangeColumn = 'last_state_change';
+ }
+
+ if (in_array($objectType, ['all', 'host'])) {
+ // get host data
+ $hostQuery = $this->backend
+ ->select()
+ ->from('hoststatus', array(
+ 'host_display_name',
+ 'host_name',
+ 'host_acknowledged',
+ 'host_state' => 'host_' . $this->stateColumn,
+ 'host_last_state_change' => 'host_' . $this->stateChangeColumn,
+ 'host_in_downtime',
+ 'host_problem',
+ 'coordinates' => '_host_geolocation',
+ 'icon' => '_host_map_icon',
+ ))
+ ->applyFilter(Filter::fromQueryString('_host_geolocation >'));
+
+ $this->applyRestriction('monitoring/filter/objects', $hostQuery);
+ $this->filterQuery($hostQuery);
+
+ // get service data
+ $serviceQuery = $this->backend
+ ->select()
+ ->from('servicestatus', array(
+ 'host_name',
+ 'service_display_name',
+ 'service_name' => 'service',
+ 'service_acknowledged',
+ 'service_state' => 'service_' . $this->stateColumn,
+ 'service_last_state_change' => 'service_' . $this->stateChangeColumn,
+ 'service_in_downtime'
+ ))
+ ->applyFilter(Filter::fromQueryString('_host_geolocation >'));
+
+ if ($filter) {
+ $serviceQuery->applyFilter($filter);
+ }
+
+ $this->applyRestriction('monitoring/filter/objects', $serviceQuery);
+ $this->filterQuery($serviceQuery);
+
+ if ($hostQuery->count() > 0) {
+ foreach ($hostQuery as $row) {
+ $hostname = $row->host_name;
+
+ $host = (array)$row;
+ $host['services'] = array();
+
+ // check for broken coordinates
+ $coordinate_pattern = '/^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$/';
+
+ if (!preg_match($coordinate_pattern, $host['coordinates'])) {
+ continue;
+ }
+
+ $host['coordinates'] = explode(",", $host['coordinates']);
+
+ $points['hosts'][$hostname] = $host;
+ }
+ }
+
+ // add services to host
+ if ($serviceQuery->count() > 0) {
+ foreach ($serviceQuery as $row) {
+ $hostname = $row->host_name;
+
+ $service = (array)$row;
+ unset($service['host_name']);
+
+ if (isset($points['hosts'][$hostname])) {
+ $points['hosts'][$hostname]['services'][$service['service_display_name']] = $service;
+ }
+ }
+ }
+
+ // remove hosts without problems and services
+ if ($filter) {
+ foreach ($points['hosts'] as $name => $host) {
+ if (empty($host['services']) && $host['host_problem'] != '1') {
+ unset($points['hosts'][$name]);
+ }
+ }
+ }
+ }
+
+ if (in_array($objectType, ['all', 'service'])) {
+
+ // get services with geolocation
+ $geoServiceQuery = $this->backend
+ ->select()
+ ->from('servicestatus', array(
+ 'host_display_name',
+ 'host_name',
+ 'host_acknowledged',
+ 'host_state' => 'host_' . $this->stateColumn,
+ 'host_last_state_change' => 'host_' . $this->stateChangeColumn,
+ 'host_in_downtime',
+ 'service_display_name',
+ 'service_name' => 'service',
+ 'service_acknowledged',
+ 'service_state' => 'service_' . $this->stateColumn,
+ 'service_last_state_change' => 'service_' . $this->stateChangeColumn,
+ 'service_in_downtime',
+ 'coordinates' => '_service_geolocation',
+ 'icon' => '_service_map_icon',
+
+ ))->applyFilter(Filter::fromQueryString('_service_geolocation >'));
+
+ if ($filter) {
+ $geoServiceQuery->applyFilter($filter);
+ }
+
+
+ $this->applyRestriction('monitoring/filter/objects', $geoServiceQuery);
+ $this->filterQuery($geoServiceQuery);
+ // ---
+
+ if ($geoServiceQuery->count() > 0) {
+ foreach ($geoServiceQuery as $row) {
+ $identifier = $row->host_name . "!" . $row->service_name;
+
+ $ar = (array)$row;
+
+ $host = array_filter($ar, function ($k) {
+ return (preg_match("/^host_|^coordinates/", $k));
+ }, ARRAY_FILTER_USE_KEY);
+
+ $service = array_filter($ar, function ($k) {
+ return (preg_match("/^service_/", $k));
+ }, ARRAY_FILTER_USE_KEY);
+
+ $host['services'][$service['service_display_name']] = $service;
+
+ // check for broken coordinates
+ $coordinate_pattern = '/^(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)$/';
+
+ if (!preg_match($coordinate_pattern, $host['coordinates'])) {
+ continue;
+ }
+
+ $host['coordinates'] = explode(",", $host['coordinates']);
+ $host['icon'] = $ar['icon'];
+ $points['services'][$identifier] = $host;
+ }
+ }
+ }
+ } catch (\Exception $e) {
+ $points['message'] = $e->getMessage();
+ $points['trace'] = $e->getTraceAsString();
+ }
+
+ echo json_encode($points);
+ exit();
+ }
+}
diff --git a/application/controllers/IndexController.php b/application/controllers/IndexController.php
new file mode 100644
index 0000000..6160c67
--- /dev/null
+++ b/application/controllers/IndexController.php
@@ -0,0 +1,93 @@
+<?php
+
+namespace Icinga\Module\Map\Controllers;
+
+use Icinga\Data\Filter\FilterException;
+use Icinga\Web\Controller\ModuleActionController;
+
+class IndexController extends ModuleActionController
+{
+ public function indexAction()
+ {
+ $config = $this->Config();
+ $map = null;
+ $mapConfig = null;
+
+ // try to load stored map
+ if ($this->params->has("load")) {
+ $map = $this->params->get("load");
+
+ if (!preg_match("/^[\w]+$/", $map)) {
+ throw new FilterException("Invalid character in map name. Allow characters: a-zA-Z0-9_");
+ }
+
+ $mapConfig = $this->Config("maps");
+ if (!$mapConfig->hasSection($map)) {
+ throw new FilterException("Could not find stored map with name = " . $map);
+ }
+ }
+
+ $this->view->id = uniqid();
+ $this->view->host = $this->params->get("showHost");
+ $this->view->expand = $this->params->get("expand");
+ $this->view->fullscreen = ($this->params->get("showFullscreen") == 1);
+
+ $parameterDefaults = array(
+ "default_zoom" => "4",
+ "default_long" => '13.377485',
+ "default_lat" => '52.515855',
+ "min_zoom" => "2",
+ "max_zoom" => "19",
+ "max_native_zoom" => "19",
+ "disable_cluster_at_zoom" => null, // should be by default: max_zoom - 1
+ "cluster_problem_count" => 0,
+ "tile_url" => "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
+ );
+
+ /*
+ * 1. url
+ * 2. stored map
+ * 3. user config
+ * 4. config
+ */
+ $userPreferences = $this->Auth()->getUser()->getPreferences();
+ if ($userPreferences->has("map")) {
+ $config->getSection("map")->merge($userPreferences->get("map"));
+ }
+
+ foreach ($parameterDefaults as $parameter => $default) {
+ if ($this->params->has($parameter)) {
+ $this->view->$parameter = $this->params->get($parameter);
+ } elseif (isset($map) && $mapConfig->getSection($map)->offsetExists($parameter)) {
+ $this->view->$parameter = $mapConfig->get($map, $parameter);
+ } else {
+ $this->view->$parameter = $config->get("map", $parameter, $default);
+ }
+ }
+
+ if (!$this->view->disable_cluster_at_zoom) {
+ $this->view->disable_cluster_at_zoom = $this->view->max_zoom - 1;
+ }
+
+ $pattern = "/^([_]{0,1}(host|service))|\(|(object|state)Type/";
+ $urlParameters = $this->filterArray($this->getAllParams(), $pattern);
+
+ if (isset($map)) {
+ $mapParameters = $this->filterArray($mapConfig->getSection($map)->toArray(), $pattern);
+ $urlParameters = array_merge($mapParameters, $urlParameters);
+ }
+
+ array_walk($urlParameters, function (&$a, $b) {
+ $a = $b . "=" . $a;
+ });
+ $this->view->url_parameters = join('&', $urlParameters);
+
+ $this->view->dashletHeight = $config->get('map', 'dashlet_height', '300');
+ }
+
+ function filterArray($array, $pattern)
+ {
+ $matches = preg_grep($pattern, array_keys($array));
+ return array_intersect_key($array, array_flip($matches));
+ }
+}