new plugin Monit (#81)

* new plugin Monit

* fix missing events in monitrc template
This commit is contained in:
fbrendel
2017-03-02 09:24:29 +01:00
committed by Franco Fichtner
parent 0adcbdce9c
commit f2ed6f5d87
25 changed files with 2008 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
PLUGIN_NAME= monit
PLUGIN_VERSION= 0.1
PLUGIN_COMMENT= Proactive system monitoring
PLUGIN_MAINTAINER= frank.brendel@eurolog.com
PLUGIN_DEPENDS= monit
.include "../../Mk/plugins.mk"
@@ -0,0 +1,48 @@
<?php
/*
Copyright (C) 2017 EURO-LOG AG
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
/**
* register service
* @return array
*/
function monit_services()
{
global $config;
$services = array();
if (isset($config['OPNsense']['monit']['general']['enabled']) && $config['OPNsense']['monit']['general']['enabled'] == 1) {
$services[] = array(
'description' => gettext('Monit System Monitoring'),
'configd' => array(
'restart' => array('monit restart'),
'start' => array('monit start'),
'stop' => array('monit stop'),
),
'name' => 'monit',
);
}
return $services;
}
@@ -0,0 +1,172 @@
<?php
/**
* Copyright (C) 2017 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Monit\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Backend;
use \OPNsense\Monit\Monit;
/**
* Class ServiceController
* @package OPNsense\Monit
*/
class ServiceController extends ApiControllerBase
{
/**
* test monit configuration
* @return array
*/
public function configtestAction()
{
if ($this->request->isPost()) {
$this->sessionClose();
}
$result['function'] = "configtest";
$result['template'] = $this->callBackend('template');
if ($result['template'] != 'OK')
{
$result['result'] = "Template error: " . $result['template'];
return $result;
}
$result['result'] = $this->callBackend('configtest');
return $result;
}
/**
* reload monit with new configuration
* @return array
*/
public function reloadAction()
{
if ($this->request->isPost()) {
$this->sessionClose();
}
$result['function'] = "reload";
$result['template'] = $this->callBackend('template');
if ($result['template'] != 'OK')
{
$result['result'] = "Template error: " . $result['template'];
return $result;
}
$status = $this->callBackend('status');
if (substr($status, 0, 16) != 'monit is running') {
$result['result'] = "Monit is not running";
return $result;
}
$result['result'] = $this->callBackend('reload');
return $result;
}
/**
* get status of monit process
* @return array
*/
public function statusAction()
{
if ($this->request->isPost()) {
$this->sessionClose();
}
$result['function'] = "status";
$result['result'] = "failed";
$result['status'] = 'stopped';
$status = $this->callBackend('status');
if (substr($status, 0, 16) == 'monit is running') {
$result['result'] = "ok";
$result['status'] = 'running';
} else {
$result['error'] = $status;
}
return $result;
}
/**
* start monit service
* @return array
*/
public function startAction()
{
$result = array("result" => "failed", "function" => "start");
if ($this->request->isPost()) {
$this->sessionClose();
$result['result'] = $this->callBackend('start');
}
return $result;
}
/**
* stop monit service
* @return array
*/
public function stopAction()
{
$result = array("result" => "failed", "function" => "stop");
if ($this->request->isPost()) {
$this->sessionClose();
$result['result'] = $this->callBackend('stop');
}
return $result;
}
/**
* restart monit service
* @return array
*/
public function restartAction()
{
$result = array("result" => "failed", "function" => "restart");
if ($this->request->isPost()) {
$this->sessionClose();
$result['result'] = $this->callBackend('restart');
}
return $result;
}
/**
* call backend functions
* @param action
* @return string
*/
protected function callBackend($action)
{
$backend = new Backend();
if ($action == 'template') {
return trim($backend->configdRun('template reload OPNsense/Monit'));
} else {
return trim($backend->configdRun('monit ' . $action));
}
}
}
@@ -0,0 +1,463 @@
<?php
/**
* Copyright (C) 2017 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Monit\Api;
use \OPNsense\Base\ApiControllerBase;
use \OPNsense\Core\Config;
use \OPNsense\Monit\Monit;
use \OPNsense\Base\UIModelGrid;
/**
* Class SettingsController
* @package OPNsense\Monit
*/
class SettingsController extends ApiControllerBase
{
//// GENRAL SETTINGS ////
/**
* retrieve monit general settings or return defaults
* @return array
*/
public function getGeneralAction()
{
return $this->get('general');
}
/**
* update monit general settings with given properties
* @return array
*/
public function setGeneralAction()
{
return $this->set('general');
}
//// ALERT SETTINGS ////
/**
* search alert
* @return array
*/
public function searchAlertAction()
{
$fields = array("enabled", "recipient", "noton", "events", "description");
return $this->search('alert', $fields);
}
/**
* retrieve monit alert settings or return defaults
* @param $uuid item unique id
* @return array
*/
public function getAlertAction($uuid = null)
{
return $this->get('alert', $uuid);
}
/**
* set monit alert parameter
* @param $uuid item unique id
* @return array
*/
public function setAlertAction($uuid = null)
{
if ($uuid != null) {
return $this->set('alert', $uuid);
}
return array("result" => "failed");
}
/**
* add monit alert parameter
* @return array
*/
public function addAlertAction()
{
return $this->set('alert', null, true);
}
/**
* delete monit alert parameter
* @param $uuid item unique id
* @return array
*/
public function delAlertAction($uuid = null)
{
if ($uuid != null) {
return $this->del('alert', $uuid);
}
return array("result" => "failed");
}
/**
* toggle monit alert by uuid (enable/disable)
* @param $uuid item unique id
* @return array
*/
public function toggleAlertAction($uuid)
{
if ($uuid != null) {
return $this->toggle('alert', $uuid);
}
return array("result" => "failed");
}
//// SERVICE SETTINGS ////
/**
* search service
* @return array
*/
public function searchServiceAction()
{
$fields = array("enabled", "name", "type", "description");
return $this->search('service', $fields);
}
/**
* retrieve monit service settings or return defaults
* @param $uuid item unique id
* @return array
*/
public function getServiceAction($uuid = null)
{
return $this->get('service', $uuid);
}
/**
* set monit service parameter
* @param $uuid item unique id
* @return array
*/
public function setServiceAction($uuid = null)
{
if ($uuid != null) {
return $this->set('service', $uuid);
}
return array("result" => "failed");
}
/**
* add monit service parameter
* @return array
*/
public function addServiceAction()
{
return $this->set('service', null, true);
}
/**
* delete monit service parameter
* @param $uuid item unique id
* @return array
*/
public function delServiceAction($uuid = null)
{
if ($uuid != null) {
return $this->del('service', $uuid);
}
return array("result" => "failed");
}
/**
* toggle monit service by uuid (enable/disable)
* @param $uuid item unique id
* @return array
*/
public function toggleServiceAction($uuid)
{
if ($uuid != null) {
return $this->toggle('service', $uuid);
}
return array("result" => "failed");
}
//// SERVICE TEST SETTINGS ////
/**
* search test
* @return array
*/
public function searchTestAction()
{
$fields = array("name", "condition", "action");
return $this->search('test', $fields);
}
/**
* retrieve monit service test settings or return defaults
* @param $uuid item unique id
* @return array
*/
public function getTestAction($uuid = null)
{
return $this->get('test', $uuid);
}
/**
* set monit service test parameter
* @param $uuid item unique id
* @return array
*/
public function setTestAction($uuid = null)
{
if ($uuid != null) {
return $this->set('test', $uuid);
}
return array("result" => "failed");
}
/**
* add monit service test parameter
* @return array
*/
public function addTestAction()
{
return $this->set('test', null, true);
}
/**
* delete monit service test parameter
* @param $uuid item unique id
* @return array
*/
public function delTestAction($uuid = null)
{
if ($uuid != null) {
return $this->del('test', $uuid);
}
return array("result" => "failed");
}
//// ABSTRACT FUNCTIONS ////
/**
* retrieve monit settings
* @param $nodeType
* @param $uuid
* @return result array
*/
private function get($nodeType = null, $uuid = null)
{
$result = array("result" => "failed");
if($this->request->isGet() && $nodeType != null) {
$mdlMonit = new Monit();
if ($uuid != null) {
$node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid);
} else {
if ($nodeType == 'general') {
$node = $mdlMonit->getNodeByReference($nodeType);
} else {
$node = $mdlMonit->$nodeType->Add();
}
}
if ($node != null) {
$result[$nodeType] = $node->getNodes();
$result["result"] = "ok";
}
}
return $result;
}
/**
* set monit properties
* @param $nodeType
* @param $uuid
* @parm $action set or add node
* @return result array
*/
private function set($nodeType = null, $uuid = null, $add = false)
{
$result = array("result" => "failed");
if ($this->request->isPost() && $this->request->hasPost("monit") && $nodeType != null) {
$mdlMonit = new Monit();
if($add == false) { // set node
if ($uuid != null) {
$node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid);
} else {
if ($nodeType == 'general') {
$node = $mdlMonit->getNodeByReference($nodeType);
} else {
$node = $mdlMonit->$nodeType->Add();
}
}
} else {
$node = $mdlMonit->$nodeType->Add();
}
if ($node != null) {
$monitInfo = $this->request->getPost("monit");
// perform plugin specific validations
if ($nodeType == 'service') {
switch ($monitInfo[$nodeType]['type']) {
case 'process':
if (empty($monitInfo[$nodeType]['pidfile']) && empty($monitInfo[$nodeType]['match'])) {
$result["validations"]['monit.service.pidfile'] = "Please set at least one of Pidfile or Match.";
$result["validations"]['monit.service.match'] = $result["validations"]['monit.service.pidfile'];
}
break;
case 'host':
if (empty($monitInfo[$nodeType]['address'])) {
$result["validations"]['monit.service.address'] = "Address is mandatory for 'Remote Host' checks.";
}
break;
case 'network':
if (empty($monitInfo[$nodeType]['address']) && empty($monitInfo[$nodeType]['interface'])) {
$result["validations"]['monit.service.address'] = "Please set at least one of Address or Interface.";
$result["validations"]['monit.service.interface'] = $result["validations"]['monit.service.address'];
}
break;
case 'system':
break;
default:
if (empty($monitInfo[$nodeType]['path'])) {
$result["validations"]['monit.service.path'] = "Path is mandatory.";
}
}
}
$node->setNodes($monitInfo[$nodeType]);
$valMsgs = $mdlMonit->performValidation();
foreach ($valMsgs as $field => $msg) {
$fieldnm = str_replace($node->__reference, "monit." . $nodeType, $msg->getField());
$result["validations"][$fieldnm] = $msg->getMessage();
}
if ($valMsgs->count() == 0) {
$mdlMonit->serializeToConfig();
Config::getInstance()->save();
$result["result"] = "saved";
}
}
}
return $result;
}
/**
* delete monit properties
* @param $nodeType
* @param $uuid
* @return result array
*/
private function del($nodeType = null, $uuid = null)
{
$result = array("result" => "failed");
if ($this->request->isPost() && $nodeType != null) {
$mdlMonit = new Monit();
if ($uuid != null) {
$node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid);
if ($node != null) {
if ($mdlMonit->$nodeType->del($uuid) == true) {
// remove test from services
if ($nodeType == 'test') {
// get a list of all services
$services = $mdlMonit->service->getNodes();
foreach ($services as $serviceUuid => $service) {
foreach ($service['tests'] as $testUuid => $test) {
// service has a reference to a test
if ($testUuid == $uuid) {
// get service model and remove $uuid from tests
$ref = 'service.' . $serviceUuid . '.tests';
$tstNode = $mdlMonit->getNodeByReference($ref);
$svcTests = str_replace($uuid, '', $tstNode->__toString());
$svcTests = str_replace(',,', ',', $svcTests);
$svcTests = rtrim($svcTests, ',');
$svcTests = ltrim($svcTests, ',');
$mdlMonit->setNodeByReference($ref, $svcTests);
}
}
}
}
$mdlMonit->serializeToConfig();
Config::getInstance()->save();
$svcMonit = new ServiceController();
$result = $svcMonit->reloadAction();
}
} else {
$result['result'] = "not found";
}
} else {
$result['result'] = "uuid not given";
}
}
return $result;
}
/**
* toggle monit items (enable/disable)
* @param $nodeType
* @param $uuid
* @return result array
*/
private function toggle($nodeType = null, $uuid = null)
{
$result = array("result" => "failed");
if ($this->request->isPost() && $nodeType != null) {
$mdlMonit = new Monit();
if ($uuid != null) {
$node = $mdlMonit->getNodeByReference($nodeType . '.' . $uuid);
if ($node != null) {
if ($node->enabled->__toString() == "1") {
$node->enabled = "0";
} else {
$node->enabled = "1";
}
$mdlMonit->serializeToConfig();
Config::getInstance()->save();
$svcMonit = new ServiceController();
$result= $svcMonit->reloadAction();
} else {
$result['result'] = "not found";
}
} else {
$result['result'] = "uuid not given";
}
}
return $result;
}
/**
* search monit settings
* @param $nodeType
* @param requested field list
* @return array
*/
private function search($nodeType = null, &$fields = null)
{
$this->sessionClose();
if($nodeType != null) {
$mdlMonit = new Monit();
$grid = new UIModelGrid($mdlMonit->$nodeType);
return $grid->fetchBindRequest($this->request, $fields);
}
}
}
@@ -0,0 +1,134 @@
<?php
/**
* Copyright (C) 2017 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Monit\Api;
use \OPNsense\Base\ApiControllerBase;
/**
* Class StatusController
* @package OPNsense\Monit
*/
class StatusController extends ApiControllerBase
{
/**
* get monit status page
* see monit(1)
* @return array
*/
public function getAction()
{
$result = array("result" => "failed", "function" => "getStatus");
// connect monit httpd socket defined in monitrc by 'set httpd ...'
if (file_exists("/var/run/monit.sock") && filetype("/var/run/monit.sock") == "socket" ) {
// throws an exception therefore no error handling
$socket = stream_socket_client("unix:///var/run/monit.sock", $errno, $errstr);
// get monit status page
$request = "GET /_status?format=text HTTP/1.0\r\n";
$request .= "\r\n";
$count = fwrite($socket, $request);
$result['count'] = $count;
$result['status'] = '';
$result['orig'] = '';
$result['httpstatus'] = preg_replace( "/\r|\n/", "", fgets($socket));
$ignorelines = 1;
if ($result['httpstatus'] == 'HTTP/1.0 200 OK') {
while (!feof($socket)) {
$line = fgets($socket);
$result['orig'] .= $line;
// ignore lines (mostly HTTP headers) until a line starts with 'Monit' e.g. 'Monit 5.20.0 uptime: 2d 23h 2m'
if (substr($line, 0, 5) == 'Monit') {
$ignorelines = 0;
}
if ($ignorelines) {
continue;
}
$result['status'] .= $line;
}
$result['result'] = "ok";
}
fclose($socket);
// response contains shell color escape codes; convert them to CSS
$result['status'] = '<pre style="color:WhiteSmoke;background-color:DimGrey">' . $this->bashColorToCSS($result['status']) . '</pre>';
} else {
$result['status'] = '<pre style="color:WhiteSmoke;background-color:DimGrey">
Either the file /var/run/monit.sock does not exists or it is not a unix socket.
Please check if the Monit service is running.
If you have started Monit recently, wait for StartDelay seconds and refresh this page.</pre>';
}
return $result;
}
/**
* convert bash color escape codes to CSS
* @param $string
* @return string
*/
private function bashColorToCSS($string) {
$colors = [
'/\x1b\[0;30m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold">$1</span>',
'/\x1b\[0;30m(.*?)\x1b\[0m/s' => '<span style="color:Black;">$1</span>',
'/\x1b\[0;31m(.*?)\x1b\[0m/s' => '<span style="color:Red;">$1</span>',
'/\x1b\[0;32m(.*?)\x1b\[0m/s' => '<span style="color:Green;">$1</span>',
'/\x1b\[0;33m(.*?)\x1b\[0m/s' => '<span style="color:Yellow;">$1</span>',
'/\x1b\[0;34m(.*?)\x1b\[0m/s' => '<span style="color:Blue;">$1</span>',
'/\x1b\[0;35m(.*?)\x1b\[0m/s' => '<span style="color:Magents;">$1</span>',
'/\x1b\[0;36m(.*?)\x1b\[0m/s' => '<span style="color:Cyan;">$1</span>',
'/\x1b\[0;37m(.*?)\x1b\[0m/s' => '<span style="color:WhiteSmoke;">$1</span>',
'/\x1b\[0;39m(.*?)\x1b\[0m/s' => '<span>$1</span>',
'/\x1b\[1;30m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:Black;">$1</span>',
'/\x1b\[1;31m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:Red;">$1</span>',
'/\x1b\[1;32m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:Green;">$1</span>',
'/\x1b\[1;33m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:Yellow;">$1</span>',
'/\x1b\[1;34m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:Blue;">$1</span>',
'/\x1b\[1;35m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:Magenta;">$1</span>',
'/\x1b\[1;36m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:Cyan;">$1</span>',
'/\x1b\[1;37m(.*?)\x1b\[0m/s' => '<span style="font-weight:bold; color:White:">$1</span>',
'/\x1b\[0;90m(.*?)\x1b\[0m/s' => '<span style="color:DargGrey">$1</span>',
'/\x1b\[0;91m(.*?)\x1b\[0m/s' => '<span style="color:LightCoral">$1</span>',
'/\x1b\[0;92m(.*?)\x1b\[0m/s' => '<span style="color:LightGreen;">$1</span>',
'/\x1b\[0;93m(.*?)\x1b\[0m/s' => '<span style="color:LightYellow;">$1</span>',
'/\x1b\[0;94m(.*?)\x1b\[0m/s' => '<span style="color:LightSkyBlue;">$1</span>',
'/\x1b\[0;95m(.*?)\x1b\[0m/s' => '<span style="color:LightPink;">$1</span>',
'/\x1b\[0;96m(.*?)\x1b\[0m/s' => '<span style="color:LightCyan;">$1</span>',
'/\x1b\[0;97m(.*?)\x1b\[0m/s' => '<span style="color:White;">$1</span>'
];
return preg_replace(array_keys($colors), $colors, $string);
}
}
@@ -0,0 +1,52 @@
<?php
/**
* Copyright (C) 2017 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Monit;
/**
* Class IndexController
* @package OPNsense\FtpProxy
*/
class IndexController extends \OPNsense\Base\IndexController
{
/**
* monit index page
* @throws \Exception
*/
public function indexAction()
{
$this->view->title = gettext('Monit System Monitoring - Settings');
$this->view->formGeneralSettings = $this->getForm("general");
$this->view->formDialogEditAlert = $this->getForm("alerts");
$this->view->formDialogEditService = $this->getForm("services");
$this->view->formDialogEditTest = $this->getForm("tests");
$this->view->pick('OPNsense/Monit/index');
}
}
@@ -0,0 +1,40 @@
<?php
/**
* Copyright (C) 2016 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Monit;
/**
* Class ItemController
* @package OPNsense\Monit
*/
class ItemController extends \OPNsense\Base\IndexController
{
}
@@ -0,0 +1,47 @@
<?php
/**
* Copyright (C) 2017 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Monit;
/**
* Class StatusController
* @package OPNsense\Monit
*/
class StatusController extends \OPNsense\Base\IndexController
{
/**
* monit status page
* @throws \Exception
*/
public function indexAction()
{
$this->view->title = gettext('Monit System Monitoring - Status');
$this->view->pick('OPNsense/Monit/status');
}
}
@@ -0,0 +1,48 @@
<form>
<field>
<id>monit.alert.enabled</id>
<label>Enable alert</label>
<type>checkbox</type>
<help><![CDATA[Enable or disable alert.]]></help>
</field>
<field>
<id>monit.alert.recipient</id>
<label>Recipient</label>
<type>text</type>
<style>tokenize</style>
<help><![CDATA[The email address to send alerts to.]]></help>
</field>
<field>
<id>monit.alert.noton</id>
<label>Not on</label>
<type>checkbox</type>
<help><![CDATA[Do not send alerts for the following events but on all others.]]></help>
</field>
<field>
<id>monit.alert.events</id>
<label>Events</label>
<type>select_multiple</type>
<nbDropdownElements>28</nbDropdownElements>
<style>tokenize</style>
<help><![CDATA[List with events. Leave it empty for all events.]]></help>
</field>
<field>
<id>monit.alert.format</id>
<label>Mail format</label>
<type>text</type>
<style>tokenize</style>
<help><![CDATA[The email format for alerts.<br><i>Subject: $SERVICE on $HOST failed</i>]]></help>
</field>
<field>
<id>monit.alert.reminder</id>
<label>Reminder</label>
<type>text</type>
<help><![CDATA[]]></help>
<help>Send a reminder after some cycles</help>
</field>
<field>
<id>monit.alert.description</id>
<label>Description</label>
<type>text</type>
</field>
</form>
@@ -0,0 +1,26 @@
<form>
<field>
<id>monit.general.enabled</id>
<label>Enable monit</label>
<type>checkbox</type>
<help>Enable or disable monit.</help>
</field>
<field>
<id>monit.general.interval</id>
<label>Polling Interval</label>
<type>text</type>
<help>Polling interval in seconds</help>
</field>
<field>
<id>monit.general.startdelay</id>
<label>Start Delay</label>
<type>text</type>
<help>On system boot wait before Monit starts checking services.</help>
</field>
<field>
<id>monit.general.mailserver</id>
<label>Mail Server</label>
<type>text</type>
<help>Comma separated list of SMTP servers for alert delivery.</help>
</field>
</form>
@@ -0,0 +1,75 @@
<form>
<field>
<id>monit.service.enabled</id>
<label>Enable service checks</label>
<type>checkbox</type>
<help><![CDATA[Enable or disable service checks.]]></help>
</field>
<field>
<id>monit.service.name</id>
<label>Name</label>
<type>text</type>
<help><![CDATA[The name of the service.]]></help>
</field>
<field>
<id>monit.service.type</id>
<label>Type</label>
<type>dropdown</type>
<help><![CDATA[The service check type.]]></help>
</field>
<field>
<id>monit.service.pidfile</id>
<label>PID File</label>
<type>text</type>
<help><![CDATA[The PID file of the process.]]></help>
</field>
<field>
<id>monit.service.match</id>
<label>Match</label>
<type>text</type>
<help><![CDATA[Find the process by regular expression. Test your pattern with <br><b>monit procmatch &lt;PATTERN&gt;</b>]]></help>
</field>
<field>
<id>monit.service.path</id>
<label>Path</label>
<type>text</type>
<help><![CDATA[According to the service type path can be a file or a directory.]]></help>
</field>
<field>
<id>monit.service.address</id>
<label>Address</label>
<type>text</type>
<help><![CDATA[The target IP address for 'Remote Host' and 'Network' checks.]]></help>
</field>
<field>
<id>monit.service.interface</id>
<label>Interface</label>
<type>dropdown</type>
<help><![CDATA[The Interface for 'Network' checks.]]></help>
</field>
<field>
<id>monit.service.start</id>
<label>Start</label>
<type>text</type>
<help><![CDATA[The start skript of the service.]]></help>
</field>
<field>
<id>monit.service.stop</id>
<label>Stop</label>
<type>text</type>
<help><![CDATA[The stop skript of the service.]]></help>
</field>
<field>
<id>monit.service.tests</id>
<label>Tests</label>
<type>select_multiple</type>
<style>tokenize</style>
<help><![CDATA[This is a list with service tests.]]></help>
</field>
<field>
<id>monit.service.description</id>
<label>Description</label>
<type>text</type>
</field>
</form>
@@ -0,0 +1,26 @@
<form>
<field>
<id>monit.test.name</id>
<label>Name</label>
<type>text</type>
<help><![CDATA[The name of the test.]]></help>
</field>
<field>
<id>monit.test.condition</id>
<label>Condition</label>
<type>text</type>
<help><![CDATA[The test condition. E.g.<br><i>cpu is greater than 50%</i><br><i>failed host 127.0.0.1 port 22 protocol ssh</i><br>]]></help>
</field>
<field>
<id>monit.test.action</id>
<label>Action</label>
<type>dropdown</type>
<help><![CDATA[Simply <i>alert</i> or <i>restart</i> the service or <i>execute</i> a program.]]></help>
</field>
<field>
<id>monit.test.path</id>
<label>Path</label>
<type>text</type>
<help><![CDATA[Make sure the script is executable by the Monit service.]]></help>
</field>
</form>
@@ -0,0 +1,10 @@
<acl>
<page-services-monit>
<name>WebCfg - Services: Monit System Monitoring page</name>
<description>Allow access to the 'Services: Monit System Monitoring' page.</description>
<patterns>
<pattern>ui/monit/*</pattern>
<pattern>api/monit/*</pattern>
</patterns>
</page-services-monit>
</acl>
@@ -0,0 +1,8 @@
<menu>
<Services>
<Monit VisibleName="Monit" cssClass="fa fa-heartbeat fa-fw">
<Settings url="/ui/monit/"/>
<Status url="/ui/monit/status/"/>
</Monit>
</Services>
</menu>
@@ -0,0 +1,41 @@
<?php
/**
* Copyright (C) 2016 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
namespace OPNsense\Monit;
use OPNsense\Base\BaseModel;
/**
* Class Monit
* @package OPNsense\Monit
*/
class Monit extends BaseModel
{
}
@@ -0,0 +1,200 @@
<model>
<mount>//OPNsense/monit</mount>
<version>1.0.0</version>
<description>Monit settings</description>
<items>
<general>
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
<interval type="IntegerField">
<default>120</default>
<Required>Y</Required>
<MinimumValue>0</MinimumValue>
<MaximumValue>86400</MaximumValue>
<ValidationMessage>Polling Interval needs to be an integer value between 0 and 86400</ValidationMessage>
</interval>
<startdelay type="IntegerField">
<default>120</default>
<Required>Y</Required>
<MinimumValue>0</MinimumValue>
<MaximumValue>86400</MaximumValue>
<ValidationMessage>Start Delay needs to be an integer value between 0 and 86400</ValidationMessage>
</startdelay>
<mailserver type="TextField">
<Required>Y</Required>
<default>127.0.0.1</default>
<Required>Y</Required>
<mask>/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-4]|2[0-5][0-9]|[01]?[0-9][0-9]?)$/</mask>
<ValidationMessage>Mail Server must be a valid IPv4 address</ValidationMessage>
</mailserver>
</general>
<alert type="ArrayField">
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
<recipient type="EmailField">
<default>root@localhost.local</default>
<Required>Y</Required>
<ValidationMessage>Please enter a valid email address.</ValidationMessage>
</recipient>
<noton type="BooleanField">
<Required>Y</Required>
<default>0</default>
</noton>
<events type="CSVListField">
<Required>N</Required>
<SelectOptions>
<action>Action done</action>
<checksum>Checksum failed</checksum>
<bytein>Download bytes exceeded</bytein>
<byteout>Upload bytes exceeded</byteout>
<connection>Connection failed</connection>
<content>Content failed</content>
<data>Data access error</data>
<exec>Execution failed</exec>
<fsflags>Filesystem flags failed</fsflags>
<gid>GID failed</gid>
<icmp>Ping failed</icmp>
<instance>Monit instance changed</instance>
<invalid>Invalid type</invalid>
<nonexist>Does not exist</nonexist>
<packetin>Download packets exceeded</packetin>
<packetout>Upload packets exceeded</packetout>
<permission>Permission failed</permission>
<pid>PID failed</pid>
<ppid>PPID failed</ppid>
<resource>Resource limit matched</resource>
<saturation>Saturation exceeded</saturation>
<size>Size failed</size>
<speed>Speed failed</speed>
<status>Status failed</status>
<timeout>Timeout</timeout>
<timestamp>Timestamp failed</timestamp>
<uid>UID failed</uid>
<uptime>Uptime failed</uptime>
</SelectOptions>
</events>
<format type="TextField">
<Required>N</Required>
<mask>/^([ 0-9a-zA-Z.,_\x{00A0}-\x{FFFF}]){1,255}$/u</mask>
<ValidationMessage>Message format should be a string between 1 and 255 characters.</ValidationMessage>
</format>
<reminder type="IntegerField">
<default>10</default>
<Required>N</Required>
<MinimumValue>0</MinimumValue>
<MaximumValue>86400</MaximumValue>
<ValidationMessage>Reminder needs to be an integer value between 0 and 86400</ValidationMessage>
</reminder>
<description type="TextField">
<Required>N</Required>
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.,_\x{00A0}-\x{FFFF}]){1,255}$/u</mask>
<ValidationMessage>Enter a description.</ValidationMessage>
</description>
</alert>
<service type="ArrayField">
<enabled type="BooleanField">
<default>0</default>
<Required>Y</Required>
</enabled>
<name type="TextField">
<Required>Y</Required>
<mask>/^([0-9a-zA-Z\._-]){1,255}$/u</mask>
<ValidationMessage>Should be a string between 1 and 255 characters. Allowed characters are letters and numbers as well as underscore, minus and dot.</ValidationMessage>
</name>
<type type="OptionField">
<Required>Y</Required>
<OptionValues>
<process>Process</process>
<file>File</file>
<fifo>Fifo</fifo>
<filesystem>Filesystem</filesystem>
<directory>Directory</directory>
<host>Remote Host</host>
<system>System</system>
<custom>Custom</custom>
<network>Network</network>
</OptionValues>
</type>
<pidfile type="TextField">
<Required>N</Required>
<mask>/^(\/[^\/ ]*)+\/?$/</mask>
<ValidationMessage>Should be a valid absolute path to the PID file of the process.</ValidationMessage>
</pidfile>
<match type="TextField">
<Required>N</Required>
</match>
<path type="TextField">
<Required>N</Required>
<mask>/^(\/[^\/ ]*)+\/?$/</mask>
<ValidationMessage>Should be a valid absolute file or folder path.</ValidationMessage>
</path>
<address type="TextField">
<Required>N</Required>
<mask>/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-4]|2[0-5][0-9]|[01]?[0-9][0-9]?)$/</mask>
<ValidationMessage>Address must be a valid IPv4 address</ValidationMessage>
</address>
<interface type="InterfaceField">
<Required>N</Required>
<multiple>N</multiple>
<filters>
<enable>/^(?!0).*$/</enable>
<ipaddr>/^((?!dhcp).)*$/</ipaddr>
</filters>
</interface>
<start type="TextField">
<Required>N</Required>
<mask>/^(\/[^\/ ]*)+\/? .*$/</mask>
<ValidationMessage>Should be a valid absolute path to the executable with its arguments.</ValidationMessage>
</start>
<stop type="TextField">
<Required>N</Required>
<mask>/^(\/[^\/ ]*)+\/? .*$/</mask>
<ValidationMessage>Should be a valid absolute path to the executable with its arguments.</ValidationMessage>
</stop>
<tests type="ModelRelationField">
<Model>
<template>
<source>OPNsense.monit.monit</source>
<items>test</items>
<display>name</display>
</template>
</Model>
<ValidationMessage>Related item not found</ValidationMessage>
<multiple>Y</multiple>
<Required>N</Required>
</tests>
</service>
<test type="ArrayField">
<name type="TextField">
<Required>Y</Required>
<mask>/^([0-9a-zA-Z._ ]){1,255}$/u</mask>
<ValidationMessage>Should be a string between 1 and 255 characters.</ValidationMessage>
</name>
<condition type="TextField">
<Required>Y</Required>
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.:\-,_()%\x{00A0}-\x{FFFF}]){1,255}$/u</mask>
<ValidationMessage>Should be a string between 1 and 255 characters.</ValidationMessage>
</condition>
<action type="OptionField">
<Required>Y</Required>
<OptionValues>
<alert>Alert</alert>
<restart>Restart</restart>
<start>Start</start>
<stop>Stop</stop>
<exec>Execute</exec>
<unmonitor>Unmonitor</unmonitor>
</OptionValues>
</action>
<path type="TextField">
<Required>N</Required>
<mask>/^(\/[^\/ ]*)+?$/</mask>
<ValidationMessage>Should be a valid absolute file path.</ValidationMessage>
</path>
</test>
</items>
</model>
@@ -0,0 +1,323 @@
{#
Copyright © 2017 by EURO-LOG AG
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
#}
<script type="text/javascript">
$( document ).ready(function() {
/**
* UI functions
*/
$('#btn_configtest').unbind('click').click(function(){
$('#btn_configtest_progress').addClass("fa fa-spinner fa-pulse");
ajaxCall(url="/api/monit/service/configtest", sendData={}, callback=function(data,status) {
$('#btn_configtest_progress').removeClass("fa fa-spinner fa-pulse");
$('#btn_configtest').blur();
$("#responseMsg").removeClass("hidden");
$("#responseMsg").html(data['result']);
});
});
$('#btn_reload').unbind('click').click(function(){
$('#btn_reload_progress').addClass("fa fa-spinner fa-pulse");
ajaxCall(url="/api/monit/service/reload", sendData={}, callback=function(data,status) {
$('#btn_reload_progress').removeClass("fa fa-spinner fa-pulse");
$('#btn_reload').blur();
$("#responseMsg").removeClass("hidden");
$("#responseMsg").html(data['result']);
ajaxCall(url="/api/monit/service/status", sendData={}, callback=function(data,status) {
updateServiceStatusUI(data['status']);
});
});
});
/**
* general settings
*/
// load data
mapDataToFormUI({'frm_GeneralSettings':"/api/monit/settings/getGeneral"}).done(function(){
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
ajaxCall(url="/api/monit/service/status", sendData={}, callback=function(data,status) {
updateServiceStatusUI(data['status']);
});
});
$('#btn_ApplyGeneralSettings').unbind('click').click(function(){
$("#frm_GeneralSettings_progress").addClass("fa fa-spinner fa-pulse");
saveFormToEndpoint(
url = "/api/monit/settings/setGeneral",
formid = "frm_GeneralSettings"
);
$("#frm_GeneralSettings_progress").removeClass("fa fa-spinner fa-pulse");
$("#btn_ApplyGeneralSettings").blur();
});
/**
* alert settings
*/
function openAlertDialog(uuid) {
var editDlg = "DialogEditAlert";
var setUrl = "/api/monit/settings/setAlert/";
var getUrl = "/api/monit/settings/getAlert/";
var urlMap = {};
urlMap['frm_' + editDlg] = getUrl + uuid;
mapDataToFormUI(urlMap).done(function () {
$('.selectpicker').selectpicker('refresh');
clearFormValidation('frm_' + editDlg);
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
$('#'+editDlg).on('hidden.bs.modal', function () {
parent.history.back();
});
});
};
$("#grid-alerts").UIBootgrid({
'search':'/api/monit/settings/searchAlert',
'get':'/api/monit/settings/getAlert/',
'set':'/api/monit/settings/setAlert/',
'add':'/api/monit/settings/addAlert/',
'del':'/api/monit/settings/delAlert/',
'toggle':'/api/monit/settings/toggleAlert/'
});
/**
* service settings
*/
// show hide fields according to selected service type
function ShowHideFields(){
var servicetype = $('#monit\\.service\\.type').val();
$('tr[for="monit.service.pidfile"]').addClass('hidden');
$('tr[for="monit.service.match"]').addClass('hidden');
$('tr[for="monit.service.path"]').addClass('hidden');
$('tr[for="monit.service.address"]').addClass('hidden');
$('tr[for="monit.service.interface"]').addClass('hidden');
$('tr[for="monit.service.start"]').removeClass('hidden');
$('tr[for="monit.service.stop"]').removeClass('hidden');
switch (servicetype) {
case 'process':
var pidfile = $('#monit\\.service\\.pidfile').val();
var match = $('#monit\\.service\\.match').val();
if (pidfile !== '') {
$('tr[for="monit.service.pidfile"]').removeClass('hidden');
$('tr[for="monit.service.match"]').addClass('hidden');
} else if (match !== '') {
$('tr[for="monit.service.pidfile"]').addClass('hidden');
$('tr[for="monit.service.match"]').removeClass('hidden');
} else {
$('tr[for="monit.service.pidfile"]').removeClass('hidden');
$('tr[for="monit.service.match"]').removeClass('hidden');
}
break;
case 'host':
$('tr[for="monit.service.address"]').removeClass('hidden');
break;
case 'network':
var address = $('#monit\\.service\\.address').val();
var interface = $('#monit\\.service\\.interface').val();
console.log('-' + address + '-' + interface + '-');
if (address !== '') {
$('tr[for="monit.service.address"]').removeClass('hidden');
$('tr[for="monit.service.interface"]').addClass('hidden');
} else if (interface !== '') {
$('tr[for="monit.service.address"]').addClass('hidden');
$('tr[for="monit.service.interface"]').removeClass('hidden');
} else {
$('tr[for="monit.service.address"]').removeClass('hidden');
$('tr[for="monit.service.interface"]').removeClass('hidden');
}
break;
case 'system':
$('tr[for="monit.service.start"]').addClass('hidden');
$('tr[for="monit.service.stop"]').addClass('hidden');
break;
default:
$('tr[for="monit.service.path"]').removeClass('hidden');
}
};
$('#DialogEditService').on('shown.bs.modal', function() {ShowHideFields();});
$('#monit\\.service\\.type').on('changed.bs.select', function(e) {ShowHideFields();});
$('#monit\\.service\\.pidfile').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.match').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.path').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.address').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.interface').on('changed.bs.select', function(e) {ShowHideFields();});
$("#grid-services").UIBootgrid({
'search':'/api/monit/settings/searchService',
'get':'/api/monit/settings/getService/',
'set':'/api/monit/settings/setService/',
'add':'/api/monit/settings/addService/',
'del':'/api/monit/settings/delService/',
'toggle':'/api/monit/settings/toggleService/'
});
/**
* service test settings
*/
// show hide execute field
function ShowHideExecField(){
var actiontype = $('#monit\\.test\\.action').val();
$('tr[for="monit.test.path"]').addClass('hidden');
if (actiontype === 'exec') {
$('tr[for="monit.test.path"]').removeClass('hidden');
}
};
$('#DialogEditTest').on('shown.bs.modal', function() {ShowHideExecField();});
$('#monit\\.test\\.action').on('changed.bs.select', function(e) {ShowHideExecField();});
function openTestDialog(uuid) {
var editDlg = "TestEditAlert";
var setUrl = "/api/monit/settings/setTest/";
var getUrl = "/api/monit/settings/getTest/";
var urlMap = {};
urlMap['frm_' + editDlg] = getUrl + uuid;
mapDataToFormUI(urlMap).done(function () {
$('.selectpicker').selectpicker('refresh');
clearFormValidation('frm_' + editDlg);
$('#'+editDlg).modal({backdrop: 'static', keyboard: false});
$('#'+editDlg).on('hidden.bs.modal', function () {
parent.history.back();
});
});
};
$("#grid-tests").UIBootgrid({
'search':'/api/monit/settings/searchTest',
'get':'/api/monit/settings/getTest/',
'set':'/api/monit/settings/setTest/',
'add':'/api/monit/settings/addTest/',
'del':'/api/monit/settings/delTest/'
});
});
</script>
<div class="alert alert-info hidden" role="alert" id="responseMsg">
</div>
<ul class="nav nav-tabs" role="tablist" id="maintabs">
<li class="active"><a data-toggle="tab" href="#general">{{ lang._('General Settings') }}</a></li>
<li><a data-toggle="tab" href="#alerts">{{ lang._('Alert Settings') }}</a></li>
<li><a data-toggle="tab" href="#services">{{ lang._('Service Settings') }}</a></li>
<li><a data-toggle="tab" href="#tests">{{ lang._('Service Tests Settings') }}</a></li>
</ul>
<div class="tab-content content-box tab-content">
<div id="general" class="tab-pane fade in active">
<!-- monit geral settings -->
{{ partial("layout_partials/base_form",['fields':formGeneralSettings,'id':'frm_GeneralSettings','apply_btn_id':'btn_ApplyGeneralSettings'])}}
</div>
<div id="alerts" class="tab-pane fade in">
<table id="grid-alerts" class="table table-condensed table-hover table-striped table-responsive" data-editDialog="DialogEditAlert">
<thead>
<tr>
<th data-column-id="enabled" data-width="6em" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="recipient" data-width="12em" data-type="string">{{ lang._('Recipient') }}</th>
<th data-column-id="noton" data-width="2em" data-type="string" data-align="right" data-formatter="boolean"></th>
<th data-column-id="events" data-type="string">{{ lang._('Events') }}</th>
<th data-column-id="description" data-type="string">{{ lang._('Description') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Edit') }} | {{ lang._('Delete') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
<div id="services" class="tab-pane fade in">
<table id="grid-services" class="table table-condensed table-hover table-striped table-responsive" data-editDialog="DialogEditService">
<thead>
<tr>
<th data-column-id="enabled" data-width="6em" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
<th data-column-id="name" data-type="string">{{ lang._('Name') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Edit') }} | {{ lang._('Delete') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
<div id="tests" class="tab-pane fade in">
<table id="grid-tests" class="table table-condensed table-hover table-striped table-responsive" data-editDialog="DialogEditTest">
<thead>
<tr>
<th data-column-id="name" data-type="string">{{ lang._('Name') }}</th>
<th data-column-id="condition" data-type="string">{{ lang._('Condition') }}</th>
<th data-column-id="action" data-type="string">{{ lang._('Action') }}</th>
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Edit') }} | {{ lang._('Delete') }}</th>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
<td></td>
<td>
<button data-action="add" type="button" class="btn btn-xs btn-default"><span class="fa fa-plus"></span></button>
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
</td>
</tr>
</tfoot>
</table>
</div>
<div class="col-md-12">
<hr/>
<button class="btn btn-primary" id="btn_configtest" type="button"><b>{{ lang._('Test Configuration') }}</b><i id="configtest_progress" class=""></i></button>
<button class="btn btn-primary" id="btn_reload" type="button"><b>{{ lang._('Reload Configuration') }}</b><i id="reload_progress" class=""></i></button>
<br/>
<br/>
</div>
</div>
{# include dialogs #}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditAlert,'id':'DialogEditAlert','label':'Edit Alert&nbsp;&nbsp;<small>NOTE: For a detailed description see monit(1) section "ALERT MESSAGES".</small>'])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditService,'id':'DialogEditService','label':'Edit Service'])}}
{{ partial("layout_partials/base_dialog",['fields':formDialogEditTest,'id':'DialogEditTest','label':'Edit Test&nbsp;&nbsp;<small>NOTE: For a detailed description see monit(1) section "SERVICE TESTS".</small>'])}}
@@ -0,0 +1,45 @@
{#
Copyright © 2017 by EURO-LOG AG
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
#}
<script type="text/javascript">
$( document ).ready(function() {
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
ajaxCall(url="/api/monit/status/get", sendData={}, callback=function(data,status) {
$("#status").html(decodeEntities(data['status']));
});
});
</script>
<div id="status" class="content-box tab-content">
Loading...
</div>
@@ -0,0 +1 @@
/usr/local/bin/php /usr/local/opnsense/scripts/OPNsense/Monit/post-install.php
@@ -0,0 +1,121 @@
<?php
/**
* Copyright (C) 2017 EURO-LOG AG
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
require_once("config.inc");
use OPNsense\Core\Config;
use OPNsense\Core\Shell;
use OPNsense\Monit\Monit;
$mdlMonit = new OPNsense\Monit\Monit;
$nodes = $mdlMonit->getNodes();
// test if Monit is already configured
if(count($nodes['service']) != 0 || count($nodes['test']) != 0) {
exit;
}
$cfg = Config::getInstance();
$cfgObj = $cfg->object();
$shellObj = new OPNsense\Core\Shell;
// get number of cpus and calculate load average limits
$nCPU = array();
$shellObj->exec('/sbin/sysctl -n kern.smp.cpus', false, $nCPU);
$LoadAvg1 = $nCPU[0] * 2;
$LoadAvg5 = $nCPU[0] + ($nCPU[0] / 2);
$LoadAvg15 = $nCPU[0];
// get FQDN
$hostName = $cfgObj->system->hostname;
$domainName = $cfgObj->system->domain;
// define some tests
$defaultTests = array(
array("name" => "Ping", "condition" => "failed ping", "action" => "alert"),
array("name" => "NetworkLink", "condition" => "failed link", "action" => "alert"),
array("name" => "NetworkSaturation", "condition" => "saturation is greater than 75%", "action" => "alert"),
array("name" => "MemoryUsage", "condition" => "memory usage is greater than 75%", "action" => "alert"),
array("name" => "CPUUsage", "condition" => "cpu usage is greater than 75%", "action" => "alert"),
array("name" => "LoadAvg1", "condition" => "loadavg (1min) is greater than $LoadAvg1", "action" => "alert"),
array("name" => "LoadAvg5", "condition" => "loadavg (5min) is greater than $LoadAvg5", "action" => "alert"),
array("name" => "LoadAvg15", "condition" => "loadavg (15min) is greater than $LoadAvg15", "action" => "alert"),
array("name" => "SpaceUsage", "condition" => "space usage is greater than 75%", "action" => "alert")
);
// define system service
$systemService = array(
"enabled" => 1,
"name" => $hostName . "." . $domainName,
"type" => "system",
"tests" => ""
);
// define root filesystem service
$rootFsService = array(
"enabled" => 1,
"name" => "RootFs",
"type" => "filesystem",
"path" => "/",
"tests" => ""
);
foreach ($defaultTests as $defaultTest) {
$testNode = $mdlMonit->test->Add();
$testNode->setNodes($defaultTest);
if ($defaultTest['name'] == "MemoryUsage" ||
$defaultTest['name'] == "CPUUsage" ||
$defaultTest['name'] == "LoadAvg1" ||
$defaultTest['name'] == "LoadAvg5" ) {
$systemService['tests'] .= $testNode->getAttributes()['uuid'] . ",";
}
if ($defaultTest['name'] == "SpaceUsage") {
$rootFsService['tests'] .= $testNode->getAttributes()['uuid'] . ",";
}
}
// remove last comma from tests csv
$systemService['tests'] = substr($systemService['tests'], 0, -1);
$rootFsService['tests'] = substr($rootFsService['tests'], 0, -1);
// add an alert with default settings
$mdlMonit->alert->Add();
// add system service
$serviceNode = $mdlMonit->service->Add();
$serviceNode->setNodes($systemService);
// add root filesystem service
$rootFsNode = $mdlMonit->service->Add();
$rootFsNode->setNodes($rootFsService);
// ignore validations because ModelRelationField does not work
$mdlMonit->serializeToConfig(false, true);
$cfg->save();

Some files were not shown because too many files have changed in this diff Show More