quagga plugin refactor
This commit is contained in:
parent
8d53dc5f8f
commit
bd4c7b25c4
12
README.md
12
README.md
|
|
@ -9,9 +9,13 @@
|
||||||
|
|
||||||
### Установка
|
### Установка
|
||||||
```shell
|
```shell
|
||||||
apk add php php-session jq
|
apk add php php-session jq git
|
||||||
```
|
cd /opt
|
||||||
|
git clone https://git.kirillius.ru/kirillius/protected-resources-list.git
|
||||||
```shell
|
cd /opt/protected-resources-list/
|
||||||
chmod -R +x ./bin
|
chmod -R +x ./bin
|
||||||
|
ln -s /opt/protected-resources-list/bin/webui /etc/init.d/webui
|
||||||
|
cp config.json.example config.json
|
||||||
|
rc-update add webui
|
||||||
|
/etc/init.d/webui start
|
||||||
```
|
```
|
||||||
|
|
@ -67,22 +67,6 @@ App.render = async function () {
|
||||||
self.prop("disabled", false);
|
self.prop("disabled", false);
|
||||||
})();
|
})();
|
||||||
});
|
});
|
||||||
$("#restart-quagga").click(function () {
|
|
||||||
if (confirm("Are you sure?")) {
|
|
||||||
const self = $(this);
|
|
||||||
self.prop("disabled", true);
|
|
||||||
(async function () {
|
|
||||||
try {
|
|
||||||
alert(await JSONRPC.__invoke("restart_quagga"));
|
|
||||||
} finally {
|
|
||||||
setTimeout(() => {
|
|
||||||
self.prop("disabled", false);
|
|
||||||
}, 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,5 @@ interface IPluggable
|
||||||
{
|
{
|
||||||
const PROTECTED_NAMES = ["enable", "disable", "render", "init"];
|
const PROTECTED_NAMES = ["enable", "disable", "render", "init"];
|
||||||
|
|
||||||
public function enable();
|
public function init(PluginContext $context);
|
||||||
|
|
||||||
public function disable();
|
|
||||||
|
|
||||||
|
|
||||||
public function init();
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class PluginContext
|
||||||
|
{
|
||||||
|
private RPC $RPC;
|
||||||
|
private Config $config;
|
||||||
|
private array $metadata;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param RPC $RPC
|
||||||
|
* @param Config $config
|
||||||
|
* @param array $metadata
|
||||||
|
*/
|
||||||
|
public function __construct(RPC $RPC, Config $config, array $metadata)
|
||||||
|
{
|
||||||
|
$this->RPC = $RPC;
|
||||||
|
$this->config = $config;
|
||||||
|
$this->metadata = $metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRPC(): RPC
|
||||||
|
{
|
||||||
|
return $this->RPC;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfig(): Config
|
||||||
|
{
|
||||||
|
return $this->config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMetadata(): array
|
||||||
|
{
|
||||||
|
return $this->metadata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,8 @@ class RPC
|
||||||
foreach ($this->config["plugins"] as $plugin) {
|
foreach ($this->config["plugins"] as $plugin) {
|
||||||
try {
|
try {
|
||||||
$meta = $this->getPluginMetadata($plugin);
|
$meta = $this->getPluginMetadata($plugin);
|
||||||
$this->loadPlugin($plugin, $meta["class"]);
|
$inst = $this->loadPlugin($plugin, $meta["class"]);
|
||||||
|
$inst->init(new PluginContext($this, $this->config, $meta));
|
||||||
} catch (Error $e) {
|
} catch (Error $e) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -39,7 +40,7 @@ class RPC
|
||||||
return $meta;
|
return $meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadPlugin($name, $classname): void
|
private function loadPlugin($name, $classname): IPluggable
|
||||||
{
|
{
|
||||||
$file = dirname(__DIR__) . "/plugins/" . $name . "/" . $classname . ".php";
|
$file = dirname(__DIR__) . "/plugins/" . $name . "/" . $classname . ".php";
|
||||||
if (!file_exists($file)) {
|
if (!file_exists($file)) {
|
||||||
|
|
@ -52,7 +53,7 @@ class RPC
|
||||||
throw new RuntimeException("Class $classname have to implement IPluggable");
|
throw new RuntimeException("Class $classname have to implement IPluggable");
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->plugins[$name] = $instance;
|
return $this->plugins[$name] = $instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConfig(): array
|
public function getConfig(): array
|
||||||
|
|
@ -80,7 +81,6 @@ class RPC
|
||||||
{
|
{
|
||||||
$this->checkAuth();
|
$this->checkAuth();
|
||||||
return (new NetworkConfigReader())->getConfigs();
|
return (new NetworkConfigReader())->getConfigs();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,89 @@
|
||||||
<?php
|
<?php
|
||||||
/*
|
|
||||||
*
|
|
||||||
* public function restart_quagga()
|
|
||||||
{
|
|
||||||
return shell_exec("./zebracfg.php");
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
class QuaggaPlugin implements IPluggable
|
class QuaggaPlugin implements IPluggable
|
||||||
{
|
{
|
||||||
public function restart()
|
private PluginContext $context;
|
||||||
{
|
const REM_PREFIX = "! routes from file ";
|
||||||
return shell_exec("./zebracfg.php");
|
|
||||||
}
|
|
||||||
public function enable()
|
|
||||||
{
|
|
||||||
// TODO: Implement enable() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
public function disable()
|
public function restart(): string
|
||||||
{
|
{
|
||||||
// TODO: Implement disable() method.
|
$configfile = $this->context->getConfig()["quagga"]["file"];
|
||||||
}
|
|
||||||
|
if (!file_exists($configfile)) {
|
||||||
|
throw new RuntimeException("Quagga config file not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
$networks = (new NetworkConfigReader())->getConfigs();
|
||||||
|
$routeParser = new RoutingTableReader();
|
||||||
|
$routes = $routeParser->getRoutes();
|
||||||
|
$defGatewayInterface = "";
|
||||||
|
$defGateway = "";
|
||||||
|
|
||||||
|
foreach ($routes as $route) {
|
||||||
|
if ($route["dst"] === "0.0.0.0/0") {
|
||||||
|
$defGatewayInterface = $route["dev"];
|
||||||
|
$defGateway = $route["gateway"];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$defGatewayInterface) {
|
||||||
|
throw new RuntimeException("Failed to detect default gateway interface");
|
||||||
|
}
|
||||||
|
|
||||||
|
$contents = file_get_contents($configfile);
|
||||||
|
$lines = explode("\n", $contents);
|
||||||
|
|
||||||
|
//remove existing routes
|
||||||
|
foreach ($lines as $key => $line) {
|
||||||
|
if (str_starts_with($line, self::REM_PREFIX) or str_starts_with($line, "ip route ") and str_contains($line . " ", $defGateway . " ")) {
|
||||||
|
unset($lines[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//add new routes
|
||||||
|
foreach ($this->context->getConfig()["networks"] as $key) {
|
||||||
|
$lines[] = self::REM_PREFIX . $key;
|
||||||
|
if (isset($networks[$key])) {
|
||||||
|
foreach ($networks[$key]["networks"] as $route) {
|
||||||
|
$lines[] = "ip route " . $route . " " . $defGateway;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($lines as $key => $line) {
|
||||||
|
if (trim($line) === "") {
|
||||||
|
unset($lines[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$backupFile = $configfile . ".sav";
|
||||||
|
|
||||||
|
unlink($backupFile);
|
||||||
|
rename($configfile, $backupFile);
|
||||||
|
file_put_contents($configfile, implode("\n", $lines));
|
||||||
|
|
||||||
|
//restart zebra
|
||||||
|
return shell_exec($this->context->getConfig()["quagga"]["restart_cmd"]);
|
||||||
|
|
||||||
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
// TODO: Implement init() method.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function init(PluginContext $context): void
|
||||||
|
{
|
||||||
|
$this->context = $context;
|
||||||
|
$this->checkConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkConfig(): void
|
||||||
|
{
|
||||||
|
$config = $this->context->getConfig();
|
||||||
|
if (!isset($config["quagga"])) {
|
||||||
|
$config["quagga"] = $this->context->getMetadata()["config"];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
{
|
{
|
||||||
"class": "QuaggaPlugin",
|
"class": "QuaggaPlugin",
|
||||||
"config": {
|
"config": {
|
||||||
"quagga": {
|
"restart_cmd": "/etc/init.d/zebra restart",
|
||||||
"restart_cmd": "/etc/init.d/zebra restart",
|
"file": "/etc/quagga/zebra.conf"
|
||||||
"file": "/etc/quagga/zebra.conf"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1 +1,19 @@
|
||||||
//<button id="restart-quagga">Restart quagga</button>
|
(async function () {
|
||||||
|
$("#buttons").append(`<button id="restart-quagga">Restart quagga</button>`);
|
||||||
|
$("#restart-quagga").click(function () {
|
||||||
|
if (confirm("Are you sure?")) {
|
||||||
|
const self = $(this);
|
||||||
|
self.prop("disabled", true);
|
||||||
|
(async function () {
|
||||||
|
try {
|
||||||
|
alert(await JSONRPC.__invoke("restart_quagga"));
|
||||||
|
} finally {
|
||||||
|
setTimeout(() => {
|
||||||
|
self.prop("disabled", false);
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
@ -3,21 +3,6 @@
|
||||||
class Updates implements IPluggable
|
class Updates implements IPluggable
|
||||||
{
|
{
|
||||||
|
|
||||||
public function enable()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function disable()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function check(): ?bool
|
public function check(): ?bool
|
||||||
{
|
{
|
||||||
|
|
@ -34,4 +19,9 @@ class Updates implements IPluggable
|
||||||
{
|
{
|
||||||
return @shell_exec("git --no-pager pull --verbose 2>&1");
|
return @shell_exec("git --no-pager pull --verbose 2>&1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function init(PluginContext $context)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
72
zebracfg.php
72
zebracfg.php
|
|
@ -1,72 +0,0 @@
|
||||||
#!/usr/bin/php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use classes\Config;
|
|
||||||
use classes\NetworkConfigReader;
|
|
||||||
use classes\RoutingTableReader;
|
|
||||||
|
|
||||||
require_once __DIR__ . "/loader.php";
|
|
||||||
const CFGFILE = "/etc/quagga/zebra.conf";
|
|
||||||
const REM_PREFIX = "! routes from file ";
|
|
||||||
try {
|
|
||||||
$networks = (new NetworkConfigReader())->getConfigs();
|
|
||||||
$config = new Config();
|
|
||||||
$config->read();
|
|
||||||
|
|
||||||
$routeParser = new RoutingTableReader();
|
|
||||||
$routes = $routeParser->getRoutes();
|
|
||||||
$defGatewayInterface = "";
|
|
||||||
$defGateway = "";
|
|
||||||
|
|
||||||
foreach ($routes as $route) {
|
|
||||||
if ($route["dst"] === "0.0.0.0/0") {
|
|
||||||
$defGatewayInterface = $route["dev"];
|
|
||||||
$defGateway = $route["gateway"];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$defGatewayInterface) {
|
|
||||||
throw new RuntimeException("Failed to detect default gateway interface");
|
|
||||||
}
|
|
||||||
|
|
||||||
$contents = file_get_contents(CFGFILE);
|
|
||||||
$lines = explode("\n", $contents);
|
|
||||||
|
|
||||||
//remove existing routes
|
|
||||||
foreach ($lines as $key => $line) {
|
|
||||||
if (str_starts_with($line, REM_PREFIX) or str_starts_with($line, "ip route ") and str_contains($line . " ", $defGateway . " ")) {
|
|
||||||
unset($lines[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//add new routes
|
|
||||||
foreach ($config["networks"] as $key) {
|
|
||||||
$lines[] = REM_PREFIX . $key;
|
|
||||||
if (isset($networks[$key])) {
|
|
||||||
foreach ($networks[$key]["networks"] as $route) {
|
|
||||||
$lines[] = "ip route " . $route . " " . $defGateway;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($lines as $key => $line) {
|
|
||||||
if (trim($line) === "") {
|
|
||||||
unset($lines[$key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$backupFile = CFGFILE . ".sav";
|
|
||||||
|
|
||||||
unlink($backupFile);
|
|
||||||
rename(CFGFILE, $backupFile);
|
|
||||||
file_put_contents(CFGFILE, implode("\n", $lines));
|
|
||||||
|
|
||||||
//restart zebra
|
|
||||||
echo shell_exec($config["zebra_restart_cmd"]);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
echo "\nError:" . $e->getMessage() . "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(0);
|
|
||||||
Loading…
Reference in New Issue