From 3fdca054d09bbabac124bb7ce0fc3bf533fcdaa3 Mon Sep 17 00:00:00 2001 From: David Harrigan Date: Mon, 4 Sep 2017 20:59:49 +0100 Subject: [PATCH] bugfix/247 Improve Zerotier Start/Stop Behaviour https://github.com/opnsense/plugins/issues/247 This commit improves upon the way that Zerotier starts and stops and how networks are added/removed and activated/deactivated. There is now a "Global" tab on the Zerotier page that enables or disables the service which is honoured between reboots. Additionally, the service needs to be active in order for networks to be added and removed. If the service is not active, then the tab "Networks" will be disabled and the user will not be able to add/remove or activate/deactivate Zerotier networks. This should fix the observed problems raised in the issue. The "Global" tab will be extended later to include further information and actions, especially when Zerotier API usage is developed. -=david=- --- net/zerotier/Makefile | 2 +- .../src/etc/inc/plugins.inc.d/zerotier.inc | 11 +-- .../Zerotier/Api/ZerotierController.php | 69 +++++++++++-------- .../OPNsense/Zerotier/IndexController.php | 3 +- .../OPNsense/Zerotier/forms/global.xml | 8 +++ .../app/models/OPNsense/Zerotier/Zerotier.xml | 5 ++ .../app/views/OPNsense/Zerotier/index.volt | 68 +++++++++++------- .../templates/OPNsense/zerotier/zerotier | 8 +-- 8 files changed, 105 insertions(+), 69 deletions(-) create mode 100644 net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/forms/global.xml diff --git a/net/zerotier/Makefile b/net/zerotier/Makefile index 8cdc78b31..5c55b3919 100644 --- a/net/zerotier/Makefile +++ b/net/zerotier/Makefile @@ -1,5 +1,5 @@ PLUGIN_NAME= zerotier -PLUGIN_VERSION= 1.0 +PLUGIN_VERSION= 1.1.0 PLUGIN_COMMENT= Virtual Networks That Just Work PLUGIN_DEPENDS= zerotier PLUGIN_MAINTAINER= dharrigan@gmail.com diff --git a/net/zerotier/src/etc/inc/plugins.inc.d/zerotier.inc b/net/zerotier/src/etc/inc/plugins.inc.d/zerotier.inc index 00ba35193..e0804a84c 100644 --- a/net/zerotier/src/etc/inc/plugins.inc.d/zerotier.inc +++ b/net/zerotier/src/etc/inc/plugins.inc.d/zerotier.inc @@ -29,15 +29,8 @@ function zerotier_enabled() { - $mdl = new \OPNsense\Zerotier\Zerotier(); - - foreach ($mdl->networks->network->__items as $network) { - if ($network->enabled == '1') { - return true; - } - } - - return false; + $zerotier = new \OPNsense\Zerotier\Zerotier(); + return (string)$zerotier->enabled == '1'; } function zerotier_services() diff --git a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/Api/ZerotierController.php b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/Api/ZerotierController.php index 1297eb888..7764adc18 100644 --- a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/Api/ZerotierController.php +++ b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/Api/ZerotierController.php @@ -45,12 +45,26 @@ class ZerotierController extends ApiMutableModelControllerBase { $result = array(); if ($this->request->isGet()) { - $mdlZerotier = new Zerotier(); + $mdlZerotier = $this->getModel(); $result['zerotier'] = $mdlZerotier->getNodes(); } return $result; } + public function setAction() + { + $result = array("result" => "failed"); + if($this->request->isPost()) { + $mdlZerotier = $this->getModel(); + $mdlZerotier->setNodes($this->request->getPost("zerotier")); + $mdlZerotier->serializeToConfig(); + Config::getInstance()->save(); + $enabled = $this->isEnabled($mdlZerotier); + $result["result"] = $this->toggleZerotierService($enabled); + } + return $result; + } + public function searchNetworkAction() { $this->sessionClose(); @@ -129,8 +143,12 @@ class ZerotierController extends ApiMutableModelControllerBase if ($this->request->isPost()) { $mdlZerotier = $this->getModel(); if ($uuid != null) { + if (!$this->isEnabled($mdlZerotier)) { + $result["result"] = "service_not_enabled"; + return $result; + } $node = $mdlZerotier->getNodeByReference('networks.network.' . $uuid); - if ($node->enabled->__toString() == "1") { + if ($this->isEnabled($node)) { # Ensure we remove the interface before deleting the network $this->toggleZerotierNetwork($node->networkId, 0); } @@ -139,7 +157,7 @@ class ZerotierController extends ApiMutableModelControllerBase Config::getInstance()->save(); $result["result"] = "deleted"; } else { - $result["result"] = "not found"; + $result["result"] = "not_found"; } } } @@ -152,10 +170,14 @@ class ZerotierController extends ApiMutableModelControllerBase if ($this->request->isPost()) { $mdlZerotier = $this->getModel(); if ($uuid != null) { + if (!$this->isEnabled($mdlZerotier)) { + $result["result"] = "service_not_enabled"; + return $result; + } $node = $mdlZerotier->getNodeByReference('networks.network.' . $uuid); if ($node != null) { $networkId = $node->networkId; - if ($node->enabled->__toString() == "1") { + if ($this->isEnabled($node)) { $node->enabled = "0"; $result['result'] = $this->toggleZerotierNetwork($networkId, 0); } else { @@ -170,34 +192,13 @@ class ZerotierController extends ApiMutableModelControllerBase return $result; } - public function reconfigureZerotierAction() - { - if ($this->request->isPost()) { - $this->sessionClose(); - $backend = new Backend(); - $backend->configdRun("template reload OPNsense/zerotier"); - $mdlZerotier = $this->getModel(); - $action = 'stop'; - foreach ($mdlZerotier->networks->network->__items as $network) { - if ($network->enabled == '1') { - $action = 'restart'; - break; - } - } - $result = trim($backend->configdRun("zerotier $action")); - return array("status" => $result); - } else { - return array("status" => "failed"); - } - } - public function statusAction() { $mdlZerotier = $this->getModel(); $enabled = false; foreach ($mdlZerotier->networks->network->__items as $network) { - if ($network->enabled == '1') { + if ($this->isEnabled($network)) { $enabled = true; break; } @@ -220,7 +221,7 @@ class ZerotierController extends ApiMutableModelControllerBase $status = "unknown"; } - return array("status" => $status); + return array("result" => $status); } private function toggleZerotierNetwork($networkId, $enabled) @@ -229,4 +230,18 @@ class ZerotierController extends ApiMutableModelControllerBase $action = $enabled ? 'join' : 'leave'; return trim($backend->configdRun("zerotier $action $networkId")); } + + private function toggleZerotierService($enabled) + { + $backend = new Backend(); + $backend->configdRun("template reload OPNsense/zerotier"); + $action = $enabled ? "start" : "stop"; + return trim($backend->configdRun("zerotier $action")); + } + + private function isEnabled($node) + { + return $node->enabled->__toString() == "1"; + } + } diff --git a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/IndexController.php b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/IndexController.php index cfa96678b..1e4eac172 100644 --- a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/IndexController.php +++ b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/IndexController.php @@ -35,6 +35,7 @@ class IndexController extends \OPNsense\Base\IndexController { $this->view->title = "VPN: Zerotier"; $this->view->pick('OPNsense/Zerotier/index'); - $this->view->formDialogNetwork = $this->getForm("dialogNetwork"); + $this->view->globalForm = $this->getForm("global"); + $this->view->dialogNetworkForm = $this->getForm("dialogNetwork"); } } diff --git a/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/forms/global.xml b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/forms/global.xml new file mode 100644 index 000000000..339dd423d --- /dev/null +++ b/net/zerotier/src/opnsense/mvc/app/controllers/OPNsense/Zerotier/forms/global.xml @@ -0,0 +1,8 @@ +
+ + zerotier.enabled + + checkbox + This will activate the Zerotier service + +
diff --git a/net/zerotier/src/opnsense/mvc/app/models/OPNsense/Zerotier/Zerotier.xml b/net/zerotier/src/opnsense/mvc/app/models/OPNsense/Zerotier/Zerotier.xml index 1b8207f1c..3b801f502 100644 --- a/net/zerotier/src/opnsense/mvc/app/models/OPNsense/Zerotier/Zerotier.xml +++ b/net/zerotier/src/opnsense/mvc/app/models/OPNsense/Zerotier/Zerotier.xml @@ -3,7 +3,12 @@ Zerotier - Virtual Networks That Just Work. + 1.1.0 + + 0 + Y + diff --git a/net/zerotier/src/opnsense/mvc/app/views/OPNsense/Zerotier/index.volt b/net/zerotier/src/opnsense/mvc/app/views/OPNsense/Zerotier/index.volt index 5991cf633..d5c4c1ddc 100644 --- a/net/zerotier/src/opnsense/mvc/app/views/OPNsense/Zerotier/index.volt +++ b/net/zerotier/src/opnsense/mvc/app/views/OPNsense/Zerotier/index.volt @@ -31,6 +31,13 @@ POSSIBILITY OF SUCH DAMAGE. $(document).ready(function() { + var zerotierSettings = {'global': '/api/zerotier/zerotier/get'}; + + mapDataToFormUI(zerotierSettings).done(function(data) { + formatTokenizersUI(); + $('select').selectpicker('refresh'); + }); + $("#grid-networks").UIBootgrid( { search: '/api/zerotier/zerotier/searchNetwork', @@ -42,37 +49,55 @@ POSSIBILITY OF SUCH DAMAGE. } ); - ajaxCall(url="/api/zerotier/zerotier/status", sendData={}, callback=function(data,status) { - updateServiceStatusUI(data['status']); + ajaxCall(url="/api/zerotier/zerotier/status", sendData={}, callback=function(data, status) { + updateServiceStatusUI(data['result']); + toggleNetworksTab(data['result']); }); - $("#reconfigureZerotier").click(function() { - $("#reconfigureZerotierProgress").addClass("fa fa-spinner fa-pulse"); - ajaxCall(url="/api/zerotier/zerotier/reconfigureZerotier", sendData={}, callback=function(data, status) { - ajaxCall(url="/api/zerotier/zerotier/status", sendData={}, callback=function(data,status) { - updateServiceStatusUI(data['status']); + $("#save").click(function() { + $("#saveProgress").addClass("fa fa-spinner fa-pulse"); + saveFormToEndpoint(url="/api/zerotier/zerotier/set", formid="global", callback_ok=function(data, status) { + ajaxCall(url="/api/zerotier/zerotier/status", sendData={}, callback=function(data, status) { + updateServiceStatusUI(data['result']); + toggleNetworksTab(data['result']); }); - $("#reconfigureZerotierProgress").removeClass("fa fa-spinner fa-pulse"); - if (status != "success" || data['status'] != 'OK') { - BootstrapDialog.show({ - type: BootstrapDialog.TYPE_WARNING, - title: "{{ lang._('Error reconfiguring Zerotier') }}", - message: data['status'], - draggable: true - }); - } + $("#saveProgress").removeClass("fa fa-spinner fa-pulse"); }); }); + + function toggleNetworksTab(status) { + switch(status) { + case "disabled": + case "service_not_enabled": + $('#ztNetworks').addClass("disabled"); + $('#ztNetworksLink').removeAttr("data-toggle"); + break; + default: + $('#ztNetworks').removeClass("disabled"); + $('#ztNetworksLink').attr("data-toggle", "tab"); + } + }; + });
-
+
+
+ {{ partial("layout_partials/base_form", ['fields': globalForm, 'id': 'global']) }} +
+
+ +
+
+
+
@@ -95,11 +120,6 @@ POSSIBILITY OF SUCH DAMAGE.
-
-
- -

-
-{{ partial("layout_partials/base_dialog",['fields':formDialogNetwork,'id':'dialogNetwork','label':lang._('Edit Zerotier Network')]) }} +{{ partial("layout_partials/base_dialog", ['fields': dialogNetworkForm, 'id': 'dialogNetwork', 'label': lang._('Edit Zerotier Network')]) }} diff --git a/net/zerotier/src/opnsense/service/templates/OPNsense/zerotier/zerotier b/net/zerotier/src/opnsense/service/templates/OPNsense/zerotier/zerotier index 20d2e5740..ba2aee487 100644 --- a/net/zerotier/src/opnsense/service/templates/OPNsense/zerotier/zerotier +++ b/net/zerotier/src/opnsense/service/templates/OPNsense/zerotier/zerotier @@ -1,10 +1,4 @@ -{% set networks = [] %} -{% for network in helpers.toList('OPNsense.zerotier.networks.network') %} -{% if network.enabled == '1' %} -{% do networks.append(network) %} -{% endif %} -{% endfor %} -{% if networks|length > 0 %} +{% if helpers.exists('OPNsense.zerotier.enabled') and OPNsense.zerotier.enabled == '1' %} zerotier_enable="YES" {% else %} zerotier_enable="NO"