quagga plugin refactor

This commit is contained in:
kirillius 2024-12-26 13:35:04 +03:00
parent 8d53dc5f8f
commit bd4c7b25c4
10 changed files with 152 additions and 143 deletions

View File

@ -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
``` ```

View File

@ -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);
}
})();
}
});
} }

View File

@ -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();
} }

35
classes/PluginContext.php Normal file
View File

@ -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;
}
}

View File

@ -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();
} }

View File

@ -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"];
}
}
} }

View File

@ -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"
}
} }
} }

View File

@ -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);
}
})();
}
});
})();

View File

@ -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)
{
}
} }

View File

@ -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);