Merge branch 'monit' of https://github.com/fbrendel/core into fbrendel-monit

This commit is contained in:
Ad Schellevis 2019-01-16 16:20:10 +01:00
commit 70c2e0e45e
6 changed files with 589 additions and 52 deletions

View File

@ -1,7 +1,7 @@
<?php
/**
* Copyright (C) 2017-2018 EURO-LOG AG
* Copyright (C) 2017-2019 EURO-LOG AG
*
* All rights reserved.
*
@ -52,6 +52,134 @@ class SettingsController extends ApiControllerBase
*/
private $nodeTypes = array('general', 'alert', 'service', 'test');
/**
* @var array with syntax information to build test conditions
*/
private $testSyntax = [
'serviceTestMapping' => [
'process' => ['Existence', 'Process Resource', 'Process Disk I/O', 'UID', 'GID', 'PID', 'PPID', 'Uptime', 'Connection', 'Custom'],
'file' => ['Existence', 'File Checksum', 'Timestamp', 'File Size', 'File Content', 'Permisssion', 'UID', 'GID', 'Custom'],
'fifo' => ['Existence', 'Timestamp', 'Permisssion', 'UID', 'GID', 'Custom'],
'filesystem' => ['Existence', 'Filesystem Mount Flags', 'Space Usage', 'Inode Usage', 'Disk I/O', 'Permisssion', 'Custom'],
'directory' => ['Existence', 'Timestamp', 'Permisssion', 'UID', 'GID', 'Custom'],
'host' => ['Network Ping', 'Connection', 'Custom'],
'system' => ['System Resource', 'Uptime', 'Custom'],
'custom' => ['Program Status', 'Custom'],
'network' => ['Network Interface', 'Custom']
],
'operators' => ['greater', 'less', 'equal', 'notequal'],
'units' => [
'timeUnits' => ['seconds', 'minutes', 'hours', 'days'],
'amountUnits' => ['byte', 'kilobyte', 'megabyte', 'gigabyte'],
'spaceAmountUnits' => ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'percent'],
'diskAmountUnits' => ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'operations'],
'netAmountUnits' => ['byte', 'kilobyte', 'megabyte', 'gigabyte', 'packets'],
],
'testConditionMapping' => [
'Existence' => [
'exist',
'not exist'
],
'System Resource' => [
'loadavg (1min)' => ['_OPERATOR' => ['_VALUE' => null]],
'loadavg (5min)' => ['_OPERATOR' => ['_VALUE' => null]],
'loadavg (15min)' => ['_OPERATOR' => ['_VALUE' => null]],
'cpu usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'cpu user usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'cpu system usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'cpu wait usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'memory usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'swap usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']]
],
'Process Resource' => [
'cpu' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'total cpu' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'threads' => ['_OPERATOR' => ['_VALUE' => null]],
'children' => ['_OPERATOR' => ['_VALUE' => null]],
'memory usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'amountUnits']],
'total memory usage' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']]
],
'Process Disk I/O' => [
'disk read rate' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'operations', '_RATE' => '/s']],
'disk write rate' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'operations', '_RATE' => '/s']]
],
'File Checksum' => [
'failed md5 checksum',
'changed md5 checksum',
'failed checksum expect' => ['_VALUE' => null]
],
'Timestamp' => [
'access time' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'timeUnits']],
'modification time' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'timeUnits']],
'change time' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'timeUnits']],
'timestamp' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'timeUnits']],
'changed access time',
'changed modification time',
'changed change time',
'changed timestamp'
],
'File Size' => [
'size' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'amountUnits']],
'changed size'
],
'File Content' => [
'content =' => ['_VALUE' => null],
'content !=' => ['_VALUE' => null]
],
'Filesystem Mount Flags' => [
'changed fsflags'
],
'Space Usage' => [
'space' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'spaceAmountUnits']],
'space free' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'spaceAmountUnits']]
],
'Inode Usage' => [
'inodes' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'amountUnits']],
'inodes free' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'amountUnits']]
],
'Disk I/O' => [
'read rate' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'diskAmountUnits', '_RATE' => '/s']],
'write rate' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'diskAmountUnits', '_RATE' => '/s']],
'service time' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'millisecond']]
],
'Permisssion' => [
'failed permission' => ['_VALUE' => null],
'changed permission'
],
'UID' => [
'failed uid' => ['_VALUE' => null]
],
'GID' => [
'failed uid' => ['_VALUE' => null]
],
'PID' => [
'changed pid'
],
'PPID' => [
'changed ppid'
],
'Uptime' => [
'uptime' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'timeUnits']]
],
'Program Status' => [
'status' => ['_OPERATOR' => ['_VALUE' => null]],
'changed status'
],
'Network Interface' => [
'failed link',
'changed link capacity',
'saturation' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'percent']],
'upload' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'netAmountUnits', '_RATE' => '/s']],
'download' => ['_OPERATOR' => ['_VALUE' => null, '_UNIT' => 'netAmountUnits', '_RATE' => '/s']],
],
'Network Ping' => [
'failed ping4',
'failed ping6'
],
'Custom' => null
]
];
/**
* initialize object properties
*/
@ -75,12 +203,18 @@ class SettingsController extends ApiControllerBase
* query monit settings
* @param $nodeType
* @param $uuid
* @param $syntax
* @return array result
* @throws \Exception
*/
public function getAction($nodeType = null, $uuid = null)
public function getAction($nodeType = null, $uuid = null, $syntax = null)
{
$result = array("result" => "failed");
if ($syntax != null) {
$result['syntax'] = $this->testSyntax;
$result['result'] = 'ok';
return $result;
}
if ($this->request->isGet() && $nodeType != null) {
$this->validateNodeType($nodeType);
if ($nodeType == 'general') {
@ -126,6 +260,17 @@ class SettingsController extends ApiControllerBase
// perform plugin specific validations
if ($nodeType == 'service') {
$tests = explode(',', $monitInfo[$nodeType]['tests']);
foreach ($tests as $testUUID) {
$test = $this->mdlMonit->getNodeByReference('test.' . $testUUID);
if ($test != null) {
$testName = $test->name->__toString();
$testType = $test->type->getNodeData()[$test->type->__toString()]['value'];
if (array_search($testType, $this->testSyntax['serviceTestMapping'][$monitInfo[$nodeType]['type']]) === false) {
$result["validations"]['monit.service.tests'] = "Test " . $testName . ' with type ' . $testType . ' not allowed for service type ' . $monitInfo[$nodeType]['type'];
}
}
}
switch ($monitInfo[$nodeType]['type']) {
case 'process':
if (empty($monitInfo[$nodeType]['pidfile']) && empty($monitInfo[$nodeType]['match'])) {
@ -263,7 +408,7 @@ class SettingsController extends ApiControllerBase
$fields = array("enabled", "name", "type");
break;
case 'test':
$fields = array("name", "condition", "action");
$fields = array("name", "type", "condition", "action");
break;
}
return $grid->fetchBindRequest($this->request, $fields);

View File

@ -5,6 +5,12 @@
<type>text</type>
<help><![CDATA[The name of the test.]]></help>
</field>
<field>
<id>monit.test.type</id>
<label>Type</label>
<type>dropdown</type>
<help><![CDATA[The type of the test.]]></help>
</field>
<field>
<id>monit.test.condition</id>
<label>Condition</label>

View File

@ -0,0 +1,44 @@
<?php
/**
* Copyright (C) 2017-2019 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\Migrations;
use OPNsense\Base\BaseModelMigration;
class M1_0_8 extends BaseModelMigration
{
public function run($model)
{
foreach ($model->getNodeByReference('test')->__items as $test) {
$test->type = 'Custom';
}
}
}

View File

@ -1,6 +1,6 @@
<model>
<mount>//OPNsense/monit</mount>
<version>1.0.7</version>
<version>1.0.8</version>
<description>Monit settings</description>
<items>
<general>
@ -275,6 +275,33 @@
<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, dot and space.</ValidationMessage>
</name>
<type type="OptionField">
<Required>Y</Required>
<OptionValues>
<Existence>Existence</Existence>
<SystemResource>System Resource</SystemResource>
<ProcessResource>Process Resource</ProcessResource>
<ProcessDiskIO>Process Disk I/O</ProcessDiskIO>
<FileChecksum>File Checksum</FileChecksum>
<Timestamp>Timestamp</Timestamp>
<FileSize>File Size</FileSize>
<FileContent>File Content</FileContent>
<FilesystemMountFlags>Filesystem Mount Flags</FilesystemMountFlags>
<SpaceUsage>Space Usage</SpaceUsage>
<InodeUsage>Inode Usage</InodeUsage>
<DiskIO>Disk I/O</DiskIO>
<Permisssion>Permission</Permisssion>
<UID>UID</UID>
<GID>GID</GID>
<PID>PID</PID>
<PPID>PPID</PPID>
<Uptime>Uptime</Uptime>
<ProgramStatus>Program Status</ProgramStatus>
<NetworkInterface>Network Interface</NetworkInterface>
<NetworkPing>Network Ping</NetworkPing>
<Custom>Custom</Custom>
</OptionValues>
</type>
<condition type="TextField">
<Required>Y</Required>
<mask>/^.{1,255}$/u</mask>

View File

@ -1,6 +1,6 @@
{#
Copyright © 2017-2018 by EURO-LOG AG
Copyright © 2017-2019 by EURO-LOG AG
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
@ -28,6 +28,7 @@ POSSIBILITY OF SUCH DAMAGE.
<script>
$( document ).ready(function() {
/**
* get the isSubsystemDirty value and print a notice
*/
@ -100,13 +101,13 @@ POSSIBILITY OF SUCH DAMAGE.
updateServiceControlUI('monit');
});
});
});
});
});
});
/**
* general settings
* general settings and syntax
*/
mapDataToFormUI({'frm_GeneralSettings':"/api/monit/settings/get/general/"}).done(function(){
mapDataToFormUI({'frm_GeneralSettings':"/api/monit/settings/get/general"}).done(function(){
formatTokenizersUI();
$('.selectpicker').selectpicker('refresh');
isSubsystemDirty();
@ -161,22 +162,6 @@ POSSIBILITY OF SUCH DAMAGE.
/**
* alert settings
*/
function openAlertDialog(uuid) {
var editDlg = "DialogEditAlert";
var setUrl = "/api/monit/settings/set/alert/";
var getUrl = "/api/monit/settings/get/alert/";
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/search/alert/',
'get':'/api/monit/settings/get/alert/',
@ -244,14 +229,55 @@ POSSIBILITY OF SUCH DAMAGE.
$('tr[id="row_monit.service.timeout"]').removeClass('hidden');
}
};
$('#DialogEditService').on('shown.bs.modal', function() {ShowHideFields();});
$('#monit\\.service\\.type').on('changed.bs.select', function(e) {ShowHideFields();});
function SelectServiceTests(){
var serviceType = $('#monit\\.service\\.type').val();
$('#monit\\.service\\.tests').html('');
$.each(serviceTests, function(index, value) {
if ($.inArray(value.type, testSyntax.serviceTestMapping[serviceType]) !== -1) {
$('#monit\\.service\\.tests').append('<option value="' + value.uuid + '">' + value.name + '</option>');
}
});
$('.selectpicker').selectpicker('refresh');
}
/**
* get service test definitions
*/
var serviceTests = [];
$('#DialogEditService').on('shown.bs.modal', function() {
$.post("/api/monit/settings/search/test", {current: 1, rowCount: -1}, function(data, status) {
if (status == "success") {
serviceTests = Object.assign({}, data.rows);
var serviceType = $('#monit\\.service\\.type').val();
// filter test option list
$('#monit\\.service\\.tests > option').each(function(index, option){
$.each(serviceTests, function(index, value) {
if (value.uuid === option.value) {
if ($.inArray(value.type, testSyntax.serviceTestMapping[serviceType]) === -1) {
option.remove();
}
return false;
}
});
});
$('.selectpicker').selectpicker('refresh');
}
});
ShowHideFields();
});
$('#monit\\.service\\.type').on('changed.bs.select', function() {
SelectServiceTests();
ShowHideFields();
});
$('#monit\\.service\\.pidfile').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.match').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.path').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.timeout').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.address').on('input', function() {ShowHideFields();});
$('#monit\\.service\\.interface').on('changed.bs.select', function(e) {ShowHideFields();});
$('#monit\\.service\\.interface').on('changed.bs.select', function() {ShowHideFields();});
$("#grid-services").UIBootgrid({
'search':'/api/monit/settings/search/service/',
@ -267,32 +293,297 @@ POSSIBILITY OF SUCH DAMAGE.
* service test settings
*/
// show hide execute field
function ShowHideExecField(){
// parse monit.test.condition and split it into testConditionStages array
// the testConditionStages array is used to build the #monit_test_condition_form
var testConditionStages = [];
function ParseTestCondition(conditionString = null) {
var conditionType = $('#monit\\.test\\.type option:selected').html();
// old behaviour for Custom types needs no parsing
if (conditionType === 'Custom') {
return;
}
if (conditionString === null) {
conditionString = $('#monit\\.test\\.condition').val();
}
// simple array, e.g 'Existence'
if ($.type(testSyntax.testConditionMapping[conditionType]) === 'array') {
// defaults to the first element
if (conditionString === '') {
testConditionStages[0] = testSyntax.testConditionMapping[conditionType][0];
} else {
$.each(testSyntax.testConditionMapping[conditionType], function(index, value) {
var regExp = new RegExp("^" + value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
if (conditionString !== undefined && regExp.test(conditionString)) {
testConditionStages[0] = value;
// first match is sufficient since elements are unique
return false;
}
});
}
}
// objects, e.g. 'System Resource'
if ($.type(testSyntax.testConditionMapping[conditionType]) === 'object') {
if (conditionString === '') {
if ($.type(testSyntax.testConditionMapping[conditionType][0]) === 'string') {
testConditionStages[0] = testSyntax.testConditionMapping[conditionType][0];
} else {
testConditionStages[0] = Object.keys(testSyntax.testConditionMapping[conditionType])[0];
}
} else {
// get the longest key match
var keyLength = 0;
$.each(testSyntax.testConditionMapping[conditionType], function(key, value) {
if ($.isNumeric(key)) {
key = value;
}
// escape metacharacters with replace() e.g. ^loadavg \(1min\)
var regExp = new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
if (regExp.test(conditionString)) {
if (key.length > keyLength) {
keyLength = key.length;
testConditionStages[0] = key;
// no break of the $.each loop because we need the longest match here
}
}
});
}
if ($.type(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]) === 'object') {
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]])[0] === '_OPERATOR') {
if (conditionString === '') {
testConditionStages[1] = testSyntax.operators[0];
} else {
$.each(testSyntax.operators, function(index, value) {
var regExp = new RegExp(value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
if (regExp.test(conditionString)) {
testConditionStages[1] = value;
// first match is sufficient since operators are unique
return false;
}
});
}
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR'])[0] === '_VALUE') {
if (conditionString === '') {
testConditionStages[2] = '';
} else {
if (testConditionStages[1] === undefined) {
testConditionStages[1] = testSyntax.operators[0];
}
var regExp = new RegExp(testConditionStages[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '.*' + testConditionStages[1].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '[^\\d]+(\\d+)');
var regRes = conditionString.match(regExp);
if($.type(regRes) === 'array') {
testConditionStages[2] = regRes[1];
} else {
testConditionStages[2] = '';
}
}
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR'])[1] === '_UNIT') {
if (conditionString === '') {
var unitType = testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR']['_UNIT'];
if (unitType in testSyntax.units) {
testConditionStages[3] = testSyntax.units[unitType][0];
} else {
testConditionStages[3] = unitType;
}
} else {
var regExp = new RegExp(testConditionStages[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '.*' + testConditionStages[1].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '[^\\d]+\\d+\\s+([^\/]+)');
var regRes = conditionString.match(regExp);
var unitType = testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR']['_UNIT'];
testConditionStages[3] = undefined;
if($.type(regRes) === 'array') {
if (unitType in testSyntax.units) {
$.each(testSyntax.units.unitType, function(index, value) {
var regExp = new RegExp(value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i');
if (regExp.test(regRes[1])) {
testConditionStages[3] = value;
// first match is sufficient since units are unique
return false;
}
});
} else {
testConditionStages[3] = unitType;
}
}
if ( testConditionStages[3] === undefined) {
if (unitType in testSyntax.units) {
testConditionStages[3] = testSyntax.units[unitType][0];
} else {
testConditionStages[3] = unitType;
}
}
}
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR'])[2] === '_RATE') {
testConditionStages[4] = testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR']['_RATE'];
}
}
}
} else if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]])[0] === '_VALUE') {
if (conditionString === '') {
testConditionStages[1] = '';
} else {
var regExp = new RegExp(testConditionStages[0].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '.*' + testConditionStages[1].replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + '[^\\s]+(.*)');
var regRes = conditionString.match(regExp);
if($.type(regRes) === 'array') {
testConditionStages[1] = regRes[1];
}
}
}
}
}
};
function setStageSelectOnChange(i) {
var stage = '#monit_test_condition_stage' + i;
$(stage).on('changed.bs.select', function() {
testConditionStages[i-1] = $(stage).val();
UpdateTestConditionForm();
$(stage).focus();
});
};
function setStageInputOnChange(i) {
var stage = '#monit_test_condition_stage' + i;
$(stage).on('input', function() {
testConditionStages[i-1] = $(stage).val();
UpdateTestConditionForm();
$(stage).focus();
});
};
function UpdateTestConditionForm() {
var conditionType = $('#monit\\.test\\.type option:selected').html();
// old behaviour for custom types
if (conditionType === 'Custom') {
$('#monit_test_condition_form').remove();
$('#monit_test_condition_preview').remove();
$('input[id="monit.test.condition"]').removeClass('hidden');
return;
} else {
if (!$('#monit_test_condition_form').length) {
$('input[id="monit.test.condition"]').addClass('hidden');
$('input[id="monit.test.condition"]').after('<div id="monit_test_condition_preview">' + $('#monit\\.test\\.condition').val() + "</div");
$('input[id="monit.test.condition"]').after('<div id="monit_test_condition_form"></div>');
}
}
var newConditionString = '';
// Stage 1 - left operand
$('#monit_test_condition_form').html(
'<div class="dropdown bootsrap-select">' +
' <select id="monit_test_condition_stage1" class="selectpicker"></select>' +
'</div>');
setStageSelectOnChange(1);
if ($.type(testSyntax.testConditionMapping[conditionType]) === 'array') {
$.each(testSyntax.testConditionMapping[conditionType], function(index, value) {
$('#monit_test_condition_stage1').append('<option value="' + value + '">' + value + '</option>');
});
$('#monit_test_condition_stage1').val(testConditionStages[0]);
newConditionString = testConditionStages[0];
}
if ($.type(testSyntax.testConditionMapping[conditionType]) === 'object') {
$.each(testSyntax.testConditionMapping[conditionType], function(key, value) {
// for arrays use the value as option
if ($.isNumeric(key)) {
key = value;
}
$('#monit_test_condition_stage1').append('<option value="' + key + '">' + key + '</option>');
});
$('#monit_test_condition_stage1').val(testConditionStages[0]);
newConditionString = testConditionStages[0];
// Stage 2 - operator/value
if ($.type(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]) === 'object') {
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]])[0] === '_OPERATOR') {
// add new dropdown
$('#monit_test_condition_stage1').after('<select id="monit_test_condition_stage2" class="selectpicker"></select>');
setStageSelectOnChange(2);
$.each(testSyntax.operators, function(index, value) {
$('#monit_test_condition_stage2').append('<option value="' + value + '">' + value + '</option>');
});
if (testConditionStages[1] === undefined) {
ParseTestCondition(newConditionString);
}
$('#monit_test_condition_stage2').val(testConditionStages[1]);
newConditionString += ' ' + testConditionStages[1];
// Stage 3 - right operand
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR'])[0] === '_VALUE') {
$('#monit_test_condition_stage2').after('<input type="text" class="form-control" id="monit_test_condition_stage3">');
setStageInputOnChange(3);
$('#monit_test_condition_stage3').val(testConditionStages[2]);
newConditionString += ' ' + testConditionStages[2];
// Stage 4 - unit
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR'])[1] === '_UNIT') {
var unitType = testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR']['_UNIT'];
if (testConditionStages[3] === undefined) {
ParseTestCondition(newConditionString);
}
if (unitType in testSyntax.units) {
$('#monit_test_condition_stage3').after('<select id="monit_test_condition_stage4" class="selectpicker"></select>');
setStageSelectOnChange(4);
$.each(testSyntax.units[unitType], function(index, value) {
$('#monit_test_condition_stage4').append('<option value="' + value + '">' + value + '</option>');
});
if($.inArray(testConditionStages[3], testSyntax.units[unitType]) === -1) {
ParseTestCondition(newConditionString);
}
$('#monit_test_condition_stage4').val(testConditionStages[3]);
newConditionString += ' ' + testConditionStages[3];
} else {
newConditionString += ' ' + unitType;
}
// Stage 5 - rate
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]]['_OPERATOR'])[2] === '_RATE') {
newConditionString += testConditionStages[4];
}
}
}
}
if (Object.keys(testSyntax.testConditionMapping[conditionType][testConditionStages[0]])[0] === '_VALUE') {
$('#monit_test_condition_stage1').after('<input type="text" class="form-control" id="monit_test_condition_stage2">');
setStageInputOnChange(2);
if (testConditionStages[1] === undefined) {
testConditionStages[1] = '';
}
$('#monit_test_condition_stage2').val(testConditionStages[1]);
newConditionString += ' ' + testConditionStages[1];
}
}
}
$('#monit\\.test\\.condition').val(newConditionString);
$('#monit_test_condition_preview').html($('#monit\\.test\\.condition').val());
$('.selectpicker').selectpicker('refresh');
};
$('#DialogEditTest').on('shown.bs.modal', function() {
ParseTestCondition();
UpdateTestConditionForm();
});
$('#DialogEditTest').on('hide.bs.modal', function() {
$('#monit_test_condition_form').remove();
$('#monit_test_condition_preview').remove();
});
$('#monit\\.test\\.type').on('changed.bs.select', function() {
$('#monit\\.test\\.condition').val('');
testConditionStages = [];
ParseTestCondition();
UpdateTestConditionForm();
$('#monit\\.test\\.type').focus();
});
$('#monit\\.test\\.action').on('changed.bs.select', function() {
var actiontype = $('#monit\\.test\\.action').val();
$('tr[id="row_monit.test.path"]').addClass('hidden');
if (actiontype === 'exec') {
$('tr[id="row_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/set/test/";
var getUrl = "/api/monit/settings/get/test/";
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/search/test/',
@ -302,6 +593,13 @@ POSSIBILITY OF SUCH DAMAGE.
'del':'/api/monit/settings/del/test/'
});
var testSyntax = {};
ajaxGet("/api/monit/settings/get/0/0/1", {}, function(data,status) {
if (status == "success") {
testSyntax = Object.assign({}, data.syntax);
}
});
});
</script>
@ -389,6 +687,7 @@ POSSIBILITY OF SUCH DAMAGE.
<thead>
<tr>
<th data-column-id="name" data-type="string">{{ lang._('Name') }}</th>
<th data-column-id="type" data-type="string">{{ lang._('Type') }}</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>

View File

@ -1,7 +1,7 @@
<?php
/*
* Copyright (C) 2018 EURO-LOG AG
* Copyright (C) 2019 EURO-LOG AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -202,8 +202,9 @@ class MonitTest extends \PHPUnit\Framework\TestCase
$_SERVER['REQUEST_METHOD'] = 'POST';
$_POST = array('monit' => ['test' => [
'name' => 'CPUUsage',
'type' => 'SystemResource',
'condition' => 'cpu usage is greater than 75%',
'action' => 'alert'
'action' => 'alert'
]
]);
$response = self::$setMonit->setAction('test');
@ -211,6 +212,7 @@ class MonitTest extends \PHPUnit\Framework\TestCase
$_POST = array('monit' => ['test' => [
'name' => 'Ping',
'type' => 'NetworkPing',
'condition' => 'failed ping',
'action' => 'alert'
]
@ -239,10 +241,24 @@ class MonitTest extends \PHPUnit\Framework\TestCase
$_POST = array('monit' => ['service' => [
'enabled' => 1,
'name' => 'Localhost',
'type' => 'host',
'type' => 'system',
'tests' => $testConfig['test']['Ping']
]
]);
$response = self::$setMonit->setAction('service');
$this->assertCount(1, $response['validations']);
$this->assertEquals($response['result'], 'failed');
$this->assertNotEmpty($response['validations']['monit.service.tests']);
$this->cleanupNodes('service');
$_POST = array('monit' => ['service' => [
'enabled' => 1,
'name' => 'Localhost',
'type' => 'host',
'tests' => $testConfig['test']['Ping']
]
]);
$response = self::$setMonit->setAction('service');
$this->assertCount(1, $response['validations']);
$this->assertEquals($response['result'], 'failed');