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
apk add php php-session jq
```
```shell
apk add php php-session jq git
cd /opt
git clone https://git.kirillius.ru/kirillius/protected-resources-list.git
cd /opt/protected-resources-list/
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);
})();
});
$("#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"];
public function enable();
public function disable();
public function init();
public function init(PluginContext $context);
}

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) {
try {
$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) {
continue;
}
@ -39,7 +40,7 @@ class RPC
return $meta;
}
private function loadPlugin($name, $classname): void
private function loadPlugin($name, $classname): IPluggable
{
$file = dirname(__DIR__) . "/plugins/" . $name . "/" . $classname . ".php";
if (!file_exists($file)) {
@ -52,7 +53,7 @@ class RPC
throw new RuntimeException("Class $classname have to implement IPluggable");
}
$this->plugins[$name] = $instance;
return $this->plugins[$name] = $instance;
}
public function getConfig(): array
@ -80,7 +81,6 @@ class RPC
{
$this->checkAuth();
return (new NetworkConfigReader())->getConfigs();
}

View File

@ -1,32 +1,89 @@
<?php
/*
*
* public function restart_quagga()
{
return shell_exec("./zebracfg.php");
}
*/
class QuaggaPlugin implements IPluggable
{
public function restart()
{
return shell_exec("./zebracfg.php");
}
public function enable()
{
// TODO: Implement enable() method.
}
private PluginContext $context;
const REM_PREFIX = "! routes from file ";
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",
"config": {
"quagga": {
"restart_cmd": "/etc/init.d/zebra restart",
"file": "/etc/quagga/zebra.conf"
}
"restart_cmd": "/etc/init.d/zebra restart",
"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
{
public function enable()
{
}
public function disable()
{
}
public function init()
{
}
public function check(): ?bool
{
@ -34,4 +19,9 @@ class Updates implements IPluggable
{
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);