summaryrefslogtreecommitdiffstats
path: root/application
diff options
context:
space:
mode:
Diffstat (limited to 'application')
-rw-r--r--application/controllers/ConfigController.php66
-rw-r--r--application/controllers/IndexController.php269
-rw-r--r--application/forms/Config/SettingConfigForm.php137
-rw-r--r--application/views/scripts/config/index.phtml11
-rw-r--r--application/views/scripts/index/index.phtml84
5 files changed, 567 insertions, 0 deletions
diff --git a/application/controllers/ConfigController.php b/application/controllers/ConfigController.php
new file mode 100644
index 0000000..3974497
--- /dev/null
+++ b/application/controllers/ConfigController.php
@@ -0,0 +1,66 @@
+<?php
+
+use Icinga\Web\Notification;
+use Icinga\Data\ResourceFactory;
+use Icinga\Forms\ConfirmRemovalForm;
+use Icinga\Web\Controller;
+use Icinga\Module\Monitoring\Forms\Config\BackendConfigForm;
+use Icinga\Module\Monitoring\Forms\Config\InstanceConfigForm;
+use Icinga\Module\Monitoring\Forms\Config\SecurityConfigForm;
+use Icinga\Module\Boxydash\Forms\Config\SettingConfigForm;
+
+class BoxyDash_ConfigController extends Controller
+{
+ public function indexAction()
+ {
+ $this->view->settingsConfig = $this->Config('settings');
+
+ $form = new SettingConfigForm();
+ $this->view->form = $form;
+ $form->setTitle($this->translate('Edit Existing Instance'));
+ $form->setIniConfig($this->Config('config'));
+ $form->setRedirectUrl('boxydash');
+ $form->handleRequest();
+
+ $this->view->form = $form;
+
+ $this->getTabs()->activate('config');
+ }
+
+ public function editSettingsAction()
+ {
+ $form = new SettingConfigForm();
+
+ $form->setTitle($this->translate('Edit Settings'));
+ $form->setIniConfig($this->Config('settings'));
+ $form->setRedirectUrl('boxydash');
+ $form->handleRequest();
+
+
+ $this->view->form = $form;
+ }
+
+
+
+ public function getTabs()
+ {
+ $tabs = parent::getTabs();
+ $tabs->add(
+ 'dashboard',
+ array(
+ 'title' => 'Dashboard',
+ 'url' => 'boxydash'
+ )
+ );
+ $tabs->add(
+ 'config',
+ array(
+ 'title' => 'Configure',
+ 'url' => 'boxydash/config'
+ )
+ );
+
+ return $tabs;
+ }
+}
+
diff --git a/application/controllers/IndexController.php b/application/controllers/IndexController.php
new file mode 100644
index 0000000..59a8f8e
--- /dev/null
+++ b/application/controllers/IndexController.php
@@ -0,0 +1,269 @@
+<?php
+/*
+TODO Things that need to be added:
+
+- Option to show only hard or soft states
+- The ability to configure box size, or set it to dynamically fill the screen
+
+- Add a filter and custom label so two dashboards could provide different labeled views.
+(you may have two boxy dashboards with two different filters open- one for each dev team/environment/project)
+
+*/
+
+
+use Icinga\Data\Filter\Filter;
+use Icinga\Module\Monitoring\Controller;
+use Icinga\Module\Monitoring\Object\Host;
+use Icinga\Module\Monitoring\Object\Service;
+use Icinga\Web\Url;
+use Icinga\Application\Logger;
+
+#FIXME should this be Controller or ModuleActionController? The documentation was unclear.
+class BoxyDash_IndexController extends Controller
+{
+ protected $default_requiresAuthentication = true;
+ protected $default_include_softstate = false;
+ protected $default_boxsize = 20;
+ protected $default_refresh = 10;
+ protected $default_showlegend = true;
+ protected $default_path_prefix = '';
+
+ public function indexAction()
+ {
+ $this->getTabs()->activate('dashboard');
+ $this->config = $this->Config('config');
+
+ $this->determine_refresh();
+ $this->determine_showlegend();
+ $this->determine_boxsize();
+ $this->determine_path_prefix();
+ $this->determine_include_softstate();
+
+
+ $isrequired = $this->config->get( 'settings', 'requires_authentication', $this->default_requiresAuthentication );
+
+ $this->_request->getParams();
+
+ $this->getServiceData();
+ $this->getHostData();
+ }
+
+ protected function requiresLogin()
+ {
+ #Logger::error("running requiresLogin");
+ $this->requiresAuthentication = (bool) $this->Config()->get(
+ 'settings',
+ 'requires_authentication',
+ $this->default_requiresAuthentication
+ );
+
+ return parent::requiresLogin();
+ }
+
+ public function determine_showlegend()
+ {
+ if ($this->_hasParam("showlegend")){
+ $this->view->showlegend = (boolean) $this->_getParam("showlegend");
+ #Failing that, check to see if it's already in the configuration or use the default legend
+ }else{
+ $this->view->showlegend = (boolean) $this->config->get('settings','show_legend',$this->default_showlegend);
+ }
+ }
+
+ public function determine_refresh()
+ {
+ if (intval($this->_getParam("refresh")) >=1){
+ $this->refresh = intval($this->_getParam("refresh"));
+
+ #Failing that, check to see if it's already in the configuration
+ }elseif (is_numeric( $this->config->get('settings','setting_refresh','missing'))) {
+ # Note that $default_refresh should never be hit on this line.
+ $this->refresh = intval($this->config->get('settings','setting_refresh',$this->default_refresh));
+ }else{
+ #failing THAT, use our default.
+ $this->refresh = $this->default_refresh ;
+ }
+ $this->setAutorefreshInterval( $this->refresh );
+ }
+
+ public function determine_boxsize()
+ {
+ if (is_numeric($this->_getParam("boxsize"))){
+ $this->view->boxsize = intval($this->_getParam("boxsize"));
+
+ #Failing that, check to see if it's already in the configuration
+ }elseif (is_numeric( $this->config->get('settings','setting_boxsize','missing'))) {
+ # Note that $default_boxsize should never be hit on this line.
+ $this->view->boxsize = $this->config->get('settings','setting_boxsize',$this->default_boxsize);
+ }else{
+ #failing THAT, use our default.
+ $this->view->boxsize = $this->default_boxsize;
+ }
+ }
+ public function determine_include_softstate()
+ {
+
+ # First determine if uri override is being passed
+ if ( $this->_hasParam("include_softstate")){
+ $this->view->include_softstate = (boolean) $this->_getParam("include_softstate");
+ }else{
+ #Failing that, check to see if it's already in the configuration or use the default
+ $this->view->include_softstate = $this->config->get('settings','include_softstate',$this->default_include_softstate);
+# $this->view->debug=intval($this->view->include_softstate);
+ }
+
+# $this->view->debug= intval( (bool)$this->view->include_softstate);
+ }
+
+ public function determine_path_prefix()
+ {
+ $this->view->path_prefix = $this->config->get('settings', 'path_prefix', $this->default_path_prefix);
+ }
+
+
+ # Create the tabs for the dashboard and the configuration tab.
+ public function getTabs()
+ {
+ $tabs = parent::getTabs();
+ $tabs->add(
+ 'dashboard',
+ array(
+ 'title' => $this->translate('Dashboard'),
+ 'url' => 'boxydash',
+ 'tip' => $this->translate('Overview')
+ )
+ );
+ if($this->Auth()->isAuthenticated()){
+ $tabs->add(
+ 'config',
+ array(
+ 'title' => $this->translate('Configure'),
+ 'url' => 'boxydash/config',
+ 'tip' => $this->translate('Configure')
+ )
+ );
+ }
+
+ return $tabs;
+ }
+
+
+ # get the status of each host
+ public function getHostData()
+ {
+ $columns = array(
+ 'host_name',
+ 'host_display_name',
+ 'host_state',
+ 'host_acknowledged',
+ 'host_in_downtime',
+ 'host_output',
+ # Most of these may not be needed; included it for future integration/use (yeah, right)
+ 'host_icon_image',
+ 'host_handled',
+ 'host_attempt',
+ 'host_state_type',
+ 'host_hard_state',
+ 'host_last_check',
+ 'host_notifications_enabled',
+ 'host_action_url',
+ 'host_notes_url',
+ 'host_active_checks_enabled',
+ 'host_passive_checks_enabled',
+ 'host_current_check_attempt',
+ 'host_max_check_attempts'
+
+ );
+ $query = $this->backend->select()->from('hostStatus', $columns);
+ $this->applyRestriction('monitoring/filter/objects', $query); // follow filter object restrictions
+ $query->order('host_name', 'desc');
+
+ # This might be very very bad for very very large environments. I just don't know how well it'll perform.
+ $this->view->hosts = $query->getQuery()->fetchAll();
+
+ foreach ($this->view->hosts as $host) {
+ #FIXME: using Service function for a host state. that's kinda ugly
+
+ # If we allow statetypes, or it's ack'd OR the state type is already HARD
+ if ( $this->view->include_softstate or $host->{'host_acknowledged'} ){
+ $host->{'host_state_text'}=Service::getStateText($host->{'host_state'});
+ }else{
+ $host->{'host_state_text'}=Service::getStateText($host->{'host_hard_state'});
+ }
+
+ }
+
+ }
+ # get the status of each service
+ public function getServiceData()
+ {
+ $columns = array(
+ 'host_name',
+ 'host_display_name',
+ 'host_in_downtime',
+ 'host_acknowledged',
+ 'host_state',
+ 'host_hard_state',
+ 'service_hard_state',
+ 'service_description',
+ 'service_display_name',
+ 'service_state',
+ 'service_in_downtime',
+ 'service_acknowledged',
+ 'service_output',
+ # Most of these may not be needed; included it for future integration/use (yeah, right)
+ 'host_last_state_change',
+ 'service_attempt',
+ 'service_last_state_change',
+ 'service_is_flapping',
+ 'service_state_type',
+ 'service_last_check',
+ 'current_check_attempt' => 'service_current_check_attempt',
+ 'max_check_attempts' => 'service_max_check_attempts'
+ );
+ $query = $this->backend->select()->from('serviceStatus', $columns);
+ $this->applyRestriction('monitoring/filter/objects', $query); // follow filter object restrictions
+ $query->order('host_name', 'desc');
+
+ $this->view->services = $query->getQuery()->fetchAll();
+
+ foreach ($this->view->services as $service) {
+ #Loop through and make sure there's a field that says "OK" so we can grab the right css class
+ $service->{'service_state_text'}=Service::getStateText($service->{'service_state'});
+ $service->{'host_state_text'}=Service::getStateText($service->{'host_state'});
+
+ # If we allow statetypes, or it's ack'd OR the state type is already HARD
+ if ( $this->view->include_softstate or $service->{'service_acknowledged'} ){
+ $service->{'service_state_text'}=Service::getStateText($service->{'service_state'});
+ }else{
+ $service->{'service_state_text'}=Service::getStateText($service->{'service_hard_state'});
+ }
+
+
+ }
+ }
+
+/* This function may be useful if I can figure out an overall way to show it that integrates well.
+ public function statusSummary(){
+ $this->view->stats = $this->backend->select()->from('statusSummary', array(
+ 'services_total',
+ 'services_ok',
+ 'services_problem',
+ 'services_problem_handled',
+ 'services_problem_unhandled',
+ 'services_critical',
+ 'services_critical_unhandled',
+ 'services_critical_handled',
+ 'services_warning',
+ 'services_warning_unhandled',
+ 'services_warning_handled',
+ 'services_unknown',
+ 'services_unknown_unhandled',
+ 'services_unknown_handled',
+ 'services_pending',
+ ))->getQuery()->fetchRow();
+
+ }
+*/
+}
+
diff --git a/application/forms/Config/SettingConfigForm.php b/application/forms/Config/SettingConfigForm.php
new file mode 100644
index 0000000..3e26b04
--- /dev/null
+++ b/application/forms/Config/SettingConfigForm.php
@@ -0,0 +1,137 @@
+<?php
+/* Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
+
+namespace Icinga\Module\Boxydash\Forms\Config;
+
+use Exception;
+use Icinga\Data\ConfigObject;
+use Icinga\Data\ResourceFactory;
+use Icinga\Web\Form;
+use InvalidArgumentException;
+use Icinga\Application\Config;
+use Icinga\Exception\ConfigurationError;
+use Icinga\Forms\ConfigForm;
+use Icinga\Web\Notification;
+
+/**
+ * Form class for creating/modifying monitoring Settings
+ */
+class SettingConfigForm extends ConfigForm
+{
+ protected $resources;
+
+ public function init()
+ {
+ $this->setName('form_config_boxydash_settings');
+ $this->setSubmitLabel($this->translate('Save Changes'));
+ }
+
+ public function createElements(array $formData)
+ {
+ $this->addElement(
+ 'text',
+ 'setting_refresh',
+ array(
+ 'label' => $this->translate('Dashboard Refresh'),
+ 'description' => $this->translate('How quickly the dashboard should refresh (between 1 second and 20 minutes)'),
+ 'value' => '10',
+ 'validators' => array(
+ array(
+ 'Between',
+ false,
+ array(
+ 'min' => '1',
+ 'max' => '1200',
+ 'inclusive' => true,
+ )
+ )
+ )
+ )
+ );
+ $this->addElement(
+ 'text',
+ 'setting_boxsize',
+ array(
+ 'label' => $this->translate('Box Size'),
+ 'description' => $this->translate('The size of displayed boxes in pixels'),
+ 'value' => '10',
+ 'validators' => array(
+ array(
+ 'Regex',
+ false,
+ array(
+ 'pattern' => '/^[\d]+$/',
+ 'messages' => array(
+ 'regexNotMatch' => $this->translate(
+ 'The application prefix must be a positive integer.'
+ )
+ )
+ )
+ )
+ )
+ )
+ );
+ $this->addElement(
+ 'checkbox',
+ 'include_softstate',
+ array(
+ 'required' => true,
+ 'value' => true,
+ 'label' => $this->translate('Include Soft Status'),
+ 'description' => $this->translate('Enable this to have soft status included')
+ )
+ );
+ $this->addElement(
+ 'checkbox',
+ 'requires_authentication',
+ array(
+ 'required' => true,
+ 'value' => true,
+ 'label' => $this->translate('Require Authentication?'),
+ 'description' => $this->translate('Does Boxydash require Authentication? Warning, this may expose sensitive network information.')
+ )
+ );
+ $this->addElement(
+ 'checkbox',
+ 'show_legend',
+ array(
+ 'required' => true,
+ 'value' => true,
+ 'label' => $this->translate('Show the Legend'),
+ 'description' => $this->translate('Do you want to show the legend?')
+ )
+ );
+ $this->addElement(
+ 'text',
+ 'path_prefix',
+ array(
+ 'label' => $this->translate('URL path prefix'),
+ 'description' => $this->translate('Prefix prepended to all links, eg "/icingaweb2". Required in case Icinga Web 2 is installed in a subfolder (eg "http://your-domain.tld/icingaweb2").'),
+ 'value' => '',
+ )
+ );
+
+ }
+
+ public function onSuccess()
+ {
+ $this->config->setSection('settings', $this->getValues());
+
+ if ($this->save()) {
+ Notification::success($this->translate('New setings have successfully been stored'));
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * @see Form::onRequest()
+ */
+ public function onRequest()
+ {
+ $this->populate($this->config->getSection('settings')->toArray());
+ }
+
+
+
+}
diff --git a/application/views/scripts/config/index.phtml b/application/views/scripts/config/index.phtml
new file mode 100644
index 0000000..053bf8d
--- /dev/null
+++ b/application/views/scripts/config/index.phtml
@@ -0,0 +1,11 @@
+
+<?php if (! $this->compact): ?>
+<div class="controls">
+ <?= $tabs; ?>
+</div>
+<?php endif ?>
+<div class="content">
+ <h1>Boxy Dashboard Configuration</h1>
+ <?=$this->form; ?>
+</div>
+
diff --git a/application/views/scripts/index/index.phtml b/application/views/scripts/index/index.phtml
new file mode 100644
index 0000000..6ae2282
--- /dev/null
+++ b/application/views/scripts/index/index.phtml
@@ -0,0 +1,84 @@
+<?
+use Icinga\Module\Monitoring\Object\Service;
+use Icinga\Module\Monitoring\Object\Host;
+
+
+?>
+
+<div class="controls">
+ <?php if (! $this->compact): ?>
+ <?= $tabs; ?>
+ <?php endif ?>
+</div>
+
+
+<div class="content">
+
+ <h1>Boxy Dashboard</h1>
+ <? if ($this->showlegend){ ?>
+ <div class="boxy_legend">
+ <span class="boxy_sublegend">
+ <span class="legendtext">&#10004; = Acknowledged</span>
+ <span class="legendtext">&#8986; = In Downtime</span>
+ <span class="legendtext">&#8632; = Host Issue Acknowledged</span>
+ </span>
+ <span class="boxy_sublegend">
+ <span class="legendtext">Status:</span>
+ <span class="boxy_legend_box ok" >ok</span>
+ <span class="boxy_legend_box warning" >warning</span>
+ <span class="boxy_legend_box critical" >critical</span>
+ <span class="boxy_legend_box unknown" >unknown</span>
+ </span>
+ <span class="boxy_sublegend">
+ <span class="legendtext" >Acknowledged:</span>
+ <span class="boxy_legend_box warning-ack" >warning</span>
+ <span class="boxy_legend_box critical-ack" >critical</span>
+ <span class="boxy_legend_box unknown-ack" >unknown</span>
+ </span>
+ </div>
+ <? } ?>
+<h2>Host Info</h2>
+<?
+foreach ($this->hosts as $host){
+ $title = htmlspecialchars($host->{'host_display_name'});
+ $size=$this->boxsize;
+ $content="&nbsp;";
+ $returncode=$host->{'host_state_text'};
+ if ($host->{'host_acknowledged'}==1 ){
+ $returncode.="-ack";
+ $content= "&#10004;";
+ $title.=" (Acknowledged)";
+ }?>
+ <a href='<?= $this->path_prefix ?>/monitoring/host/show?host=<?=$host->{'host_name'}?>' class='boxy_box state <?=$returncode?>' style='width:<?=$size?>px; height:<?=$size?>px; font-size:<?=$size?>px;' title="<?=$title?>"><?=$content?></a>
+<? } ?>
+
+<br clear="all"/>
+<h2>Service Info</h2>
+
+<? foreach ($this->services as $service){
+ $service->{'service_hard_state'} = ($service->{'service_hard_state'}) ? "hard" : "soft";
+ $title = $service->{'host_display_name'}.": ".$service->{'service_description'};
+ #."(".$service->{'current_check_attempt'} .",".$service->{'max_check_attempts'} .")(". $service->{'service_hard_state'}.")+acked:".$service->{'service_acknowledged'} ;
+ $size=$this->boxsize;
+ $content="&nbsp;";
+ $returncode=$service->{'service_state_text'};
+ if ($service->{'service_in_downtime'}==1 or $service->{'host_in_downtime'}==1 ){
+ $returncode.="-downtime";
+ $content= "&#8986;";
+ $title.=" (Scheduled Maintenance)";
+ }elseif ($service->{'service_acknowledged'}==1 ){
+ $returncode.="-ack";
+ $content= "&#10004;";
+ $title.=" (Acknowledged)";
+ }elseif ($service->{'service_state_text'} != "ok" && $service->{'host_acknowledged'} == 1 ){
+ $returncode.="-ack";
+ $content= "&#8632;";
+ $title.=" (Host Issue Acknowledged)";
+ }
+ $title=htmlspecialchars($title."\n ".$service->{'service_output'});?>
+ <a href='<?= $this->path_prefix ?>/monitoring/service/show?host=<?=$service->{'host_name'}?>&service=<?=$service->{'service_description'}?>' class='boxy_box state <?=$returncode?>' style='width:<?=$size?>px; height:<?=$size?>px; font-size:<?=$size?>px;' title="<?=$title?>"><?=$content?></a>
+
+<? } ?>
+<br clear=all>
+<pre style="font-size:20px"><?=$this->debug?></pre>
+</div>