diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php index afd0bfa88..765379433 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/ServiceController.php @@ -2,7 +2,7 @@ /** * Copyright (C) 2017-2018 EURO-LOG AG - * + * Copyright (c) 2019 Deciso B.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,7 +32,6 @@ namespace OPNsense\Monit\Api; use \OPNsense\Base\ApiMutableServiceControllerBase; use \OPNsense\Core\Backend; -use \OPNsense\Monit\Monit; /** * Class ServiceController @@ -45,15 +44,6 @@ class ServiceController extends ApiMutableServiceControllerBase protected static $internalServiceTemplate = 'OPNsense/Monit'; protected static $internalServiceName = 'monit'; - /** - * initialize object properties - */ - public function onConstruct() - { - // initialize the model via parent to avoid selflock by circular references - $this->getModel(); - } - /** * test monit configuration * @return array diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php index 6829a57e0..714dc75e3 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/Api/SettingsController.php @@ -2,7 +2,7 @@ /** * Copyright (C) 2017-2019 EURO-LOG AG - * + * Copyright (c) 2019 Deciso B.V. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,163 +30,18 @@ namespace OPNsense\Monit\Api; -use \OPNsense\Base\ApiControllerBase; +use \OPNsense\Base\ApiMutableModelControllerBase; use \OPNsense\Core\Config; -use \OPNsense\Monit\Monit; use \OPNsense\Base\UIModelGrid; /** * Class SettingsController * @package OPNsense\Monit */ -class SettingsController extends ApiControllerBase +class SettingsController extends ApiMutableModelControllerBase { - - /** - * @var null|object the monit model object - */ - public $mdlMonit = null; - - /** - * @var array list with valid model node types - */ - 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 - */ - public function onConstruct() - { - $this->mdlMonit = new Monit(); - } + protected static $internalModelName = 'monit'; + protected static $internalModelClass = 'OPNsense\Monit\Monit'; /** * check if changes to the monit settings were made @@ -195,224 +50,216 @@ class SettingsController extends ApiControllerBase public function dirtyAction() { $result = array('status' => 'ok'); - $result['monit']['dirty'] = $this->mdlMonit->configChanged(); + $result['monit']['dirty'] = $this->getModel()->configChanged(); return $result; } /** - * query monit settings - * @param $nodeType - * @param $uuid - * @param $syntax - * @return array result - * @throws \Exception + * Retrieve alert settings or return defaults + * @param $uuid item unique id + * @return array monit alert content + * @throws \ReflectionException when not bound to model */ - public function getAction($nodeType = null, $uuid = null, $syntax = null) + public function getAlertAction($uuid = 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') { - $node = $this->mdlMonit->getNodeByReference($nodeType); - } else { - if ($uuid != null) { - $node = $this->mdlMonit->getNodeByReference($nodeType . '.' . $uuid); - } else { - $node = $this->mdlMonit->$nodeType->Add(); - } - } - if ($node != null) { - $result['monit'] = array($nodeType => $node->getNodes()); - $result['result'] = 'ok'; - } - } - return $result; + return $this->getBase("alert", "alert", $uuid); } /** - * set monit properties - * @param $nodeType - * @param $uuid - * @return array status - * @throws \Exception + * Update alert with given properties + * @param string $uuid internal id + * @return array save result + validation output + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model */ - public function setAction($nodeType = null, $uuid = null) + public function setAlertAction($uuid) { - $result = array("result" => "failed", "validations" => array()); - if ($this->request->isPost() && $this->request->hasPost("monit") && $nodeType != null) { - $this->validateNodeType($nodeType); - if ($nodeType == 'general') { - $node = $this->mdlMonit->getNodeByReference($nodeType); - } else { - if ($uuid != null) { - $node = $this->mdlMonit->getNodeByReference($nodeType . '.' . $uuid); - } else { - $node = $this->mdlMonit->$nodeType->Add(); - } - } - if ($node != null) { - $monitInfo = $this->request->getPost("monit"); - - // 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'])) { - $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 = $this->mdlMonit->performValidation(); - foreach ($valMsgs as $field => $msg) { - $fieldnm = str_replace($node->__reference, "monit." . $nodeType, $msg->getField()); - $result["validations"][$fieldnm] = $msg->getMessage(); - } - if (empty($result["validations"])) { - unset($result["validations"]); - $result['result'] = 'ok'; - $this->mdlMonit->serializeToConfig(); - Config::getInstance()->save(); - if ($this->mdlMonit->configDirty()) { - $result['status'] = 'ok'; - } - } - } - } - return $result; + return $this->setBase("alert", "alert", $uuid); } /** - * delete monit settings - * @param $nodeType - * @param $uuid - * @return array status - * @throws \Exception + * Add alert with given properties + * @return array save result + validation output + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model */ - public function delAction($nodeType = null, $uuid = null) + public function addAlertAction() { - $result = array("result" => "failed"); - if ($nodeType != null) { - $this->validateNodeType($nodeType); - if ($uuid != null) { - $node = $this->mdlMonit->getNodeByReference($nodeType . '.' . $uuid); - if ($node != null) { - if ($this->mdlMonit->$nodeType->del($uuid) == true) { - // delete relations - if ($nodeType == 'test') { - $nodeName = $this->mdlMonit->getNodeByReference($nodeType . '.' . $uuid . '.name'); - if ($nodeName != null) { - $nodeName = $nodeName->__toString(); - $this->deleteRelations('service', 'tests', $uuid, 'test', $nodeName, $this->mdlMonit); - } - } - $this->mdlMonit->serializeToConfig(); - Config::getInstance()->save(); - if ($this->mdlMonit->configDirty()) { - $result['status'] = 'ok'; - } - } - } - } - } - return $result; + return $this->addBase("alert", "alert"); } /** - * toggle monit items (enable/disable) - * @param $nodeType - * @param $uuid - * @return array result + * Delete alert by uuid + * @param string $uuid internal id + * @return array save status + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model */ - public function toggleAction($nodeType = null, $uuid = null) + public function delAlertAction($uuid) { - $result = array("result" => "failed"); - if ($this->request->isPost() && $nodeType != null) { - if ($uuid != null) { - $node = $this->mdlMonit->getNodeByReference($nodeType . '.' . $uuid); - if ($node != null) { - if ($node->enabled->__toString() == "1") { - $node->enabled = "0"; - } else { - $node->enabled = "1"; - } - $this->mdlMonit->serializeToConfig(); - Config::getInstance()->save(); - if ($this->mdlMonit->configDirty()) { - $result['status'] = 'ok'; - } - } else { - $result['result'] = "not found"; - } - } else { - $result['result'] = "uuid not given"; - } - } - return $result; + return $this->delBase("alert", $uuid); } /** - * search monit settings - * @param $nodeType - * @return array result - * @throws \Exception + * Search monit alerts + * @return array list of found alerts + * @throws \ReflectionException when not bound to model */ - public function searchAction($nodeType = null) + public function searchAlertAction() { - $this->sessionClose(); - if ($this->request->isPost() && $nodeType != null) { - $this->validateNodeType($nodeType); - $grid = new UIModelGrid($this->mdlMonit->$nodeType); - $fields = array(); - switch ($nodeType) { - case 'alert': - $fields = array("enabled", "recipient", "noton", "events", "description"); - break; - case 'service': - $fields = array("enabled", "name", "type"); - break; - case 'test': - $fields = array("name", "type", "condition", "action"); - break; - } - return $grid->fetchBindRequest($this->request, $fields); - } + return $this->searchBase( + "alert", + array("enabled", "recipient", "noton", "events", "description"), + "description" + ); + } + + /** + * Toggle alert defined by uuid (enable/disable) + * @param $uuid alert internal id + * @param $enabled desired state enabled(1)/disabled(1), leave empty for toggle + * @return array save result + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function toggleAlertAction($uuid, $enabled = null) + { + return $this->toggleBase("alert", $uuid, $enabled); + } + + /** + * Retrieve service settings or return defaults + * @param $uuid item unique id + * @return array monit service content + * @throws \ReflectionException when not bound to model + */ + public function getServiceAction($uuid = null) + { + return $this->getBase("service", "service", $uuid); + } + + /** + * Update service with given properties + * @param string $uuid internal id + * @return array save result + validation output + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function setServiceAction($uuid) + { + return $this->setBase("service", "service", $uuid); + } + + /** + * Add service with given properties + * @return array save result + validation output + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function addServiceAction() + { + return $this->addBase("service", "service"); + } + + /** + * Delete service by uuid + * @param string $uuid internal id + * @return array save status + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function delServiceAction($uuid) + { + return $this->delBase("service", $uuid); + } + + /** + * Search monit services + * @return array list of found services + * @throws \ReflectionException when not bound to model + */ + public function searchServiceAction() + { + return $this->searchBase("service", array("enabled", "name", "type"), "name"); + } + + /** + * Toggle service defined by uuid (enable/disable) + * @param $uuid service internal id + * @param $enabled desired state enabled(1)/disabled(1), leave empty for toggle + * @return array save result + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function toggleServiceAction($uuid, $enabled = null) + { + return $this->toggleBase("service", $uuid, $enabled); + } + + /** + * Retrieve test settings or return defaults + * @param $uuid item unique id + * @return array monit test content + * @throws \ReflectionException when not bound to model + */ + public function getTestAction($uuid = null) + { + return $this->getBase("test", "test", $uuid); + } + + /** + * Update test with given properties + * @param string $uuid internal id + * @return array save result + validation output + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function setTestAction($uuid) + { + return $this->setBase("test", "test", $uuid); + } + + /** + * Add test with given properties + * @return array save result + validation output + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function addTestAction() + { + return $this->addBase("test", "test"); + } + + /** + * Delete test by uuid + * @param string $uuid internal id + * @return array save status + * @throws \Phalcon\Validation\Exception when field validations fail + * @throws \ReflectionException when not bound to model + */ + public function delTestAction($uuid) + { + return $this->delBase("test", $uuid); + } + + /** + * Search monit services + * @return array list of found services + * @throws \ReflectionException when not bound to model + */ + public function searchTestAction() + { + return $this->searchBase("test", array("name", "condition", "action"), "name"); + } + + /** + * Retrieve general settings + * @return array monit general settings content + * @throws \ReflectionException when not bound to model + */ + public function getGeneralAction() + { + return ['monit' => $this->getModel()->general->getNodes(), 'result' => 'ok']; } /** @@ -427,7 +274,7 @@ class SettingsController extends ApiControllerBase $cfg = Config::getInstance(); $cfgObj = $cfg->object(); - $node = $this->mdlMonit->getNodeByReference('general'); + $node = $this->getModel()->getNodeByReference('general'); $generalSettings = array(); // inherit SMTP settings from System->Settings->Notifications @@ -448,72 +295,19 @@ class SettingsController extends ApiControllerBase // apply them $node->setNodes($generalSettings); - $valMsgs = $this->mdlMonit->performValidation(); + $valMsgs = $this->getModel()->performValidation(); foreach ($valMsgs as $field => $msg) { $fieldnm = str_replace($node->__reference, "monit.general.", $msg->getField()); $result["validations"][$fieldnm] = $msg->getMessage(); } if (empty($result["validations"])) { unset($result["validations"]); - $this->mdlMonit->serializeToConfig(); + $this->getModel()->serializeToConfig(); Config::getInstance()->save(); - if ($this->mdlMonit->configDirty()) { - $result['status'] = 'ok'; - $result['result'] = 'OK'; - } + $result['status'] = 'ok'; + $result['result'] = 'OK'; } } return $result; } - - /** - * validate nodeType - * @param $nodeType - * @throws \Exception - */ - private function validateNodeType($nodeType = null) - { - if (array_search($nodeType, $this->nodeTypes) === false) { - throw new \Exception('unknown nodeType: ' . $nodeType); - } - } - - /** - * delete relations - * @param string|null $nodeType - * @param string|null $nodeField - * @param string|null $relUuid - * @param string|null $relNodeType - * @param string|null $relNodeName - * @throws \Exception - */ - private function deleteRelations( - $nodeType = null, - $nodeField = null, - $relUuid = null, - $relNodeType = null, - $relNodeName = null - ) { - $nodes = $this->mdlMonit->$nodeType->getNodes(); - // get nodes with relations - foreach ($nodes as $nodeUuid => $node) { - // get relation uuids - foreach ($node[$nodeField] as $fieldUuid => $field) { - // remove uuid from field - if ($fieldUuid == $relUuid) { - $refField = $nodeType . '.' . $nodeUuid . '.' . $nodeField; - $relNode = $this->mdlMonit->getNodeByReference($refField); - $nodeRels = str_replace($relUuid, '', $relNode->__toString()); - $nodeRels = str_replace(',,', ',', $nodeRels); - $nodeRels = rtrim($nodeRels, ','); - $nodeRels = ltrim($nodeRels, ','); - $this->mdlMonit->setNodeByReference($refField, $nodeRels); - if ($relNode->isEmptyAndRequired()) { - $nodeName = $this->mdlMonit->getNodeByReference($nodeType . '.' . $nodeUuid . '.name')->__toString(); - throw new \Exception("Cannot delete $relNodeType '$relNodeName' from $nodeType '$nodeName'"); - } - } - } - } - } } diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml index 867465487..2b7a64ff1 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml +++ b/src/opnsense/mvc/app/controllers/OPNsense/Monit/forms/alerts.xml @@ -1,43 +1,43 @@