From b83282f267b46bbf234a748cf9d4879e3a63a3e8 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Sun, 24 Dec 2017 15:56:49 +0100 Subject: [PATCH] mvc: add a mutable service controller for easy reuse --- LICENSE | 1 + plist | 1 + .../Base/ApiMutableServiceControllerBase.php | 206 ++++++++++++++++++ 3 files changed, 208 insertions(+) create mode 100644 src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableServiceControllerBase.php diff --git a/LICENSE b/LICENSE index 515cff240..5afea1ab7 100644 --- a/LICENSE +++ b/LICENSE @@ -34,6 +34,7 @@ Copyright (c) 2015 Manuel Faux Copyright (c) 2003-2007 Manuel Kasper Copyright (c) 2012 Marcello Coutinho Copyright (c) 2010-2015 Michael Bostock +Copyright (c) 2017 Michael Muenz Copyright (c) 2005-2006 Paul Taylor Copyright (c) 2005-2006 Peter Allgeyer Copyright (c) 2004 Peter Curran diff --git a/plist b/plist index 37f9ac807..97d0f7429 100644 --- a/plist +++ b/plist @@ -329,6 +329,7 @@ /usr/local/opnsense/mvc/app/config/services_api.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Base/ApiControllerBase.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableModelControllerBase.php +/usr/local/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableServiceControllerBase.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Base/ControllerBase.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Base/ControllerRoot.php /usr/local/opnsense/mvc/app/controllers/OPNsense/Base/IndexController.php diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableServiceControllerBase.php b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableServiceControllerBase.php new file mode 100644 index 000000000..8144c92fa --- /dev/null +++ b/src/opnsense/mvc/app/controllers/OPNsense/Base/ApiMutableServiceControllerBase.php @@ -0,0 +1,206 @@ + + * Copyright (C) 2017 Michael Muenz + * Copyright (C) 2016 IT-assistans Sverige AB + * Copyright (C) 2016 Deciso B.V. + * 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\Base; + +/** + * Class ApiMutableServiceControllerBase, inherit this class to implement + * an API that exposes a service controller with start, stop, restart, + * reconfigure and status actions. + * @package OPNsense\Base + */ +abstract class ApiMutableServiceControllerBase extends ApiControllerBase +{ + /** + * @var string this implementations internal model name to use + */ + static protected $internalModelName = null; + + /** + * @var string model class name to use + */ + static protected $internalModelClass = null; + + /** + * @var string model template name to use + */ + static protected $internalModelTemplate = null; + + /** + * @var string model enabled xpath to use + */ + static protected $internalModelEnabled = null; + + /** + * @var null|BaseModel model object to work on + */ + private $modelHandle = null; + + /** + * validate on initialization + * @throws Exception + */ + public function initialize() + { + parent::initialize(); + if (empty(static::$internalModelClass)) { + throw new \Exception('cannot instantiate without internalModelClass defined.'); + } + if (empty(static::$internalModelName)) { + throw new \Exception('cannot instantiate without internalModelName defined.'); + } + if (empty(static::$internalModelTemplate)) { + throw new \Exception('cannot instantiate without internalModelTemplate defined.'); + } + if (empty(static::$internalModelEnabled)) { + throw new \Exception('cannot instantiate without internalModelEnabled defined.'); + } + } + + /** + * @return null|BaseModel + */ + protected function getModel() + { + if ($this->modelHandle == null) { + $this->modelHandle = (new \ReflectionClass(static::$internalModelClass))->newInstance(); + } + + return $this->modelHandle; + } + + /** + * start service + * @return array + */ + public function startAction() + { + if ($this->request->isPost()) { + // close session for long running action + $this->sessionClose(); + $backend = new Backend(); + $response = $backend->configdRun(escapeshellarg($internalModelName) . ' start'); + return array('response' => $response); + } else { + return array('response' => array()); + } + } + + /** + * stop service + * @return array + */ + public function stopAction() + { + if ($this->request->isPost()) { + // close session for long running action + $this->sessionClose(); + $backend = new Backend(); + $response = $backend->configdRun(escapeshellarg($internalModelName) . ' stop'); + return array('response' => $response); + } else { + return array('response' => array()); + } + } + + /** + * restart service + * @return array + */ + public function restartAction() + { + if ($this->request->isPost()) { + // close session for long running action + $this->sessionClose(); + $backend = new Backend(); + $response = $backend->configdRun(escapeshellarg($internalModelName) . ' restart'); + return array('response' => $response); + } else { + return array('response' => array()); + } + } + + /** + * reconfigure, generate config and reload + */ + public function reconfigureAction() + { + if ($this->request->isPost()) { + // close session for long running action + $this->sessionClose(); + + $model = $this->getModel(); + $backend = new Backend(); + + $this->stopAction(); + + // generate template + $backend->configdRun('template reload ' . escapeshellarg($internalModelTemplate)); + + // (re)start daemon + if ((string)$model->xpath($internalModelEnabled) == '1') { + $this->startAction(); + } + + return array('status' => 'ok'); + } else { + return array('status' => 'failed'); + } + } + + /** + * retrieve status of service + * @return array + * @throws \Exception + */ + public function statusAction() + { + $backend = new Backend(); + $model = $this->getModel(); + $response = $backend->configdRun(escapeshellarg($internalModelName) . ' status'); + + if (strpos($response, 'not running') > 0) { + if ((string)$model->xpath($internalModelEnabled) == 1) { + $status = 'stopped'; + } else { + $status = 'disabled'; + } + } elseif (strpos($response, 'is running') > 0) { + $status = 'running'; + } elseif ((string)$model->xpath($internalModelEnabled) == 0) { + $status = 'disabled'; + } else { + $status = 'unknown'; + } + + return array('status' => $status); + } +}