diff options
Diffstat (limited to 'application')
-rw-r--r-- | application/controllers/ConfigController.php | 66 | ||||
-rw-r--r-- | application/controllers/IndexController.php | 269 | ||||
-rw-r--r-- | application/forms/Config/SettingConfigForm.php | 137 | ||||
-rw-r--r-- | application/views/scripts/config/index.phtml | 11 | ||||
-rw-r--r-- | application/views/scripts/index/index.phtml | 84 |
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">✔ = Acknowledged</span> + <span class="legendtext">⌚ = In Downtime</span> + <span class="legendtext">↸ = 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=" "; + $returncode=$host->{'host_state_text'}; + if ($host->{'host_acknowledged'}==1 ){ + $returncode.="-ack"; + $content= "✔"; + $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=" "; + $returncode=$service->{'service_state_text'}; + if ($service->{'service_in_downtime'}==1 or $service->{'host_in_downtime'}==1 ){ + $returncode.="-downtime"; + $content= "⌚"; + $title.=" (Scheduled Maintenance)"; + }elseif ($service->{'service_acknowledged'}==1 ){ + $returncode.="-ack"; + $content= "✔"; + $title.=" (Acknowledged)"; + }elseif ($service->{'service_state_text'} != "ok" && $service->{'host_acknowledged'} == 1 ){ + $returncode.="-ack"; + $content= "↸"; + $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> |