"small changes"
- remove http only in login.html - extract PeeringManager into separate file - add "progress meter" for "used" to "available" peerings
This commit is contained in:
parent
d6509ef6fe
commit
1fda3c11a4
8 changed files with 307 additions and 166 deletions
19
.vscode/launch.json
vendored
19
.vscode/launch.json
vendored
|
@ -1,5 +1,16 @@
|
||||||
{
|
{
|
||||||
"configurations": [
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Python: Flask-backend",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "flask",
|
||||||
|
"cwd": "${workspaceFolder}/web/",
|
||||||
|
"env": { "FLASK_APP": "backend/main.py", "FLASK_DEBUG": "1", "FLASK_RUN_HOST": "0.0.0.0", "FLASK_RUN_PORT": "8042" },
|
||||||
|
"args": ["run", "--no-debugger"],
|
||||||
|
"jinja": true,
|
||||||
|
"justMyCode": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Python: Current File",
|
"name": "Python: Current File",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
|
@ -8,6 +19,14 @@
|
||||||
"cwd": "${workspaceFolder}/web/",
|
"cwd": "${workspaceFolder}/web/",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"justMyCode": true
|
"justMyCode": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Python: backend",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "backend/main.py",
|
||||||
|
"cwd": "${workspaceFolder}/web/",
|
||||||
|
"justMyCode": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"ASN": "424242000", //Your ASN (used to generate default peer ListenPorts)
|
"ASN": "424242000", //Your ASN (used to generate default peer ListenPorts)
|
||||||
"listen": "0.0.0.0",
|
"listen": "0.0.0.0",
|
||||||
"port": 8042,
|
"port": 8042,
|
||||||
"domain": "example.org", // domain to use for kioubit verification service
|
"domain": "example.org", // domain to use for kioubit verification service (with protocol)
|
||||||
"base-dir": "/", //optional:directury for which it is reachable (if behind some sort of reverse proxy) default "/"
|
"base-dir": "/", //optional:directury for which it is reachable (if behind some sort of reverse proxy) default "/"
|
||||||
"peerings": "/path/to/peering-config.json", // optional; default "$PWD/peerings", directory to save existing peerings to
|
"peerings": "/path/to/peering-config.json", // optional; default "$PWD/peerings", directory to save existing peerings to
|
||||||
"production": true, //optional, default true;
|
"production": true, //optional, default true;
|
|
@ -10,6 +10,7 @@ import random
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from ipaddress import ip_address, ip_network, IPv4Network, IPv6Network
|
from ipaddress import ip_address, ip_network, IPv4Network, IPv6Network
|
||||||
import kioubit_verify
|
import kioubit_verify
|
||||||
|
from peering_manager import PeeringManager
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ class Config (dict):
|
||||||
if os.path.exists("./config.json"):
|
if os.path.exists("./config.json"):
|
||||||
self.configfile = "./config.json"
|
self.configfile = "./config.json"
|
||||||
elif os.path.exists("/etc/dn42-autopeer/config.json"):
|
elif os.path.exists("/etc/dn42-autopeer/config.json"):
|
||||||
self.configfile = "/etc/dn42-autopeer/config,json"
|
self.configfile = "/etc/dn42-autopeer/config.json"
|
||||||
else:
|
else:
|
||||||
raise FileNotFoundError(
|
raise FileNotFoundError(
|
||||||
"no config file found in ./config.json or /etc/dn42-autopeer/config.json")
|
"no config file found in ./config.json or /etc/dn42-autopeer/config.json")
|
||||||
|
@ -58,152 +59,19 @@ class Config (dict):
|
||||||
|
|
||||||
if not "peerings-data" in self._config:
|
if not "peerings-data" in self._config:
|
||||||
self._config["peering-data"] = "./peerings"
|
self._config["peering-data"] = "./peerings"
|
||||||
|
|
||||||
|
if not "nodes" in self._config:
|
||||||
|
self,_config = {}
|
||||||
|
for node in self._config["nodes"]:
|
||||||
|
if not "capacity" in self._config["nodes"][node]:
|
||||||
|
self._config["nodes"][node]["capacity"] = -1
|
||||||
|
|
||||||
logging.info(self._config)
|
logging.info(self._config)
|
||||||
|
|
||||||
|
|
||||||
class PeeringManager:
|
|
||||||
|
|
||||||
def __init__(self, peerings_file):
|
|
||||||
self._peering_file = peerings_file
|
|
||||||
|
|
||||||
self._load_peerings()
|
|
||||||
|
|
||||||
def _load_peerings(self):
|
|
||||||
if not os.path.exists(self._peering_file):
|
|
||||||
with open(self._peering_file, "x") as p:
|
|
||||||
json.dump({"mnter": {}, "asn": {}}, p)
|
|
||||||
try:
|
|
||||||
with open(self._peering_file, "r") as p:
|
|
||||||
self.peerings = json.load(p)
|
|
||||||
except json.decoder.JSONDecodeError:
|
|
||||||
with open(self._peering_file, "w") as p:
|
|
||||||
json.dump({"mnter": {}, "asn": {}}, p)
|
|
||||||
with open(self._peering_file, "r") as p:
|
|
||||||
self.peerings = json.load(p)
|
|
||||||
|
|
||||||
# self.peerings = {}
|
|
||||||
# missing_peerings = False
|
|
||||||
# for peering in self._peerings:
|
|
||||||
# if os.path.exists(f"{self._peering_dir}/{peering}.json"):
|
|
||||||
# with open(f"{self._peering_dir}/{peering}.json") as peer_cfg:
|
|
||||||
# self.peerings[peering] = json.load(peer_cfg)
|
|
||||||
# else:
|
|
||||||
# logging.warning(f"peering with id {peering} doesn't exist. removing reference in `{self._peering_dir}/peerings.json`")
|
|
||||||
# self._peerings.remove(peering)
|
|
||||||
# missing_peerings = True
|
|
||||||
# if missing_peerings:
|
|
||||||
# with open(f"{self._peering_dir}/peerings.json","w") as p:
|
|
||||||
# json.dump(self._peerings, p, indent=4)
|
|
||||||
def _save_peerings(self):
|
|
||||||
with open(self._peering_file, "w") as p:
|
|
||||||
json.dump(self.peerings, p, indent=4)
|
|
||||||
|
|
||||||
def _update_nodes(mode, peering, new_peering=None):
|
|
||||||
"""mode: "add","update","delete
|
|
||||||
peering: peering to send to node (included in peering)
|
|
||||||
new_peering: if mode=="update" the new peering to update to
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def exists(self, asn, node, mnt=None, wg_key=None, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True):
|
|
||||||
"""checks if a peerings with specific data already exists"""
|
|
||||||
# check if mnt is specified, already exists in the database and if that mnt has the specified ASn -> if not: return False
|
|
||||||
if mnt and not (mnt in self.peerings["mnter"] and asn in self.peerings["mnter"][mnt]):
|
|
||||||
return False
|
|
||||||
selected_peerings = self.peerings["asn"][asn]
|
|
||||||
# check if the ASn even has peerings
|
|
||||||
if len(selected_peerings) == 0:
|
|
||||||
return False
|
|
||||||
for p in selected_peerings:
|
|
||||||
if p["node"] == node:
|
|
||||||
if (not wg_key or p["wg_key"] == wg_key) and (not endpoint or p["endpoint"] == endpoint) \
|
|
||||||
and (not ipv6ll or p["ipv6ll"] == ipv6ll) and (not ipv4 or p["ipv4"] == ipv4) and (not ipv6 or p["ipv6"] == ipv6)\
|
|
||||||
and (not bgp_mp or p["bgp_mp"] == bgp_mp) and (not bgp_enh or p["bgp_enh"] == bgp_enh):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_peerings_by_mnt(self, mnt):
|
|
||||||
# print(self.peerings)
|
|
||||||
try:
|
|
||||||
out = []
|
|
||||||
for asn in self.peerings["mnter"][mnt]:
|
|
||||||
try:
|
|
||||||
for peering in self.peerings["asn"][asn]:
|
|
||||||
out.append(peering)
|
|
||||||
except KeyError as e:
|
|
||||||
pass
|
|
||||||
return out
|
|
||||||
except KeyError:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
def add_peering(self, asn, node, mnt, wg_key, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True):
|
|
||||||
# check if this MNT already has a/this asn
|
|
||||||
try:
|
|
||||||
if not asn in self.peerings["mnter"][mnt]:
|
|
||||||
# ... and add it if it hasn't
|
|
||||||
self.peerings[mnt].append(asn)
|
|
||||||
except KeyError:
|
|
||||||
# ... and cerate it if it doesn't have any yet
|
|
||||||
self.peerings["mnter"][mnt] = [asn]
|
|
||||||
try:
|
|
||||||
if not asn in self.peerings["asn"]:
|
|
||||||
self.peerings["asn"][asn] = []
|
|
||||||
except KeyError:
|
|
||||||
self.peerings["asn"][asn] = []
|
|
||||||
|
|
||||||
# deny more than one peering per ASN to one node
|
|
||||||
for peering in self.peerings["asn"][asn]:
|
|
||||||
if peering["node"] == node:
|
|
||||||
return False
|
|
||||||
|
|
||||||
self.peerings["asn"][asn].append({"MNT": mnt, "ASN": asn, "node": node, "wg_key": wg_key, "endpoint": endpoint,
|
|
||||||
"ipv6ll": ipv6ll, "ipv4": ipv4, "ipv6": ipv6, "bgp_mp": bgp_mp, "bgp_enh": bgp_enh})
|
|
||||||
|
|
||||||
self._save_peerings()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def update_peering(self, asn, node, mnt, wg_key, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True):
|
|
||||||
# check if this MNT already has a/this asn
|
|
||||||
try:
|
|
||||||
if not asn in self.peerings["mnter"][mnt]:
|
|
||||||
# ... and add it if it hasn't
|
|
||||||
self.peerings[mnt].append(asn)
|
|
||||||
except KeyError:
|
|
||||||
# ... and cerate it if it doesn't have any yet
|
|
||||||
self.peerings["mnter"][mnt] = [asn]
|
|
||||||
try:
|
|
||||||
if not asn in self.peerings["asn"]:
|
|
||||||
return False
|
|
||||||
except KeyError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
success = False
|
|
||||||
for pNr in range(len(self.peerings["asn"][asn])):
|
|
||||||
if self.peerings["asn"][asn][pNr]["node"] == node:
|
|
||||||
self.peerings["asn"][asn][pNr] = {"MNT": mnt, "ASN": asn, "node": node, "wg_key": wg_key,
|
|
||||||
"endpoint": endpoint, "ipv6ll": ipv6ll, "ipv4": ipv4, "ipv6": ipv6, "bgp_mp": bgp_mp, "bgp_enh": bgp_enh}
|
|
||||||
success = True
|
|
||||||
if not success:
|
|
||||||
return False
|
|
||||||
self._save_peerings()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def delete_peering(self, asn, node, mnt, wg_key=None):
|
|
||||||
if not self.exists(asn, node, mnt=mnt, wg_key=wg_key):
|
|
||||||
return False
|
|
||||||
for p in self.peerings["asn"][asn]:
|
|
||||||
if p["node"] == node:
|
|
||||||
if wg_key and p["wg_key"] != wg_key:
|
|
||||||
continue
|
|
||||||
self.peerings["asn"][asn].remove(p)
|
|
||||||
self._save_peerings()
|
|
||||||
return True
|
|
||||||
# if nothing got found (should have been catched by self.exists)
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
config = Config()
|
config = Config()
|
||||||
peerings = PeeringManager(config["peerings"])
|
peerings = PeeringManager(config)
|
||||||
kverifyer = kioubit_verify.AuthVerifyer(config["domain"])
|
kverifyer = kioubit_verify.AuthVerifyer(config["domain"])
|
||||||
|
|
||||||
|
|
||||||
|
@ -241,9 +109,9 @@ def check_peering_data(form):
|
||||||
else:
|
else:
|
||||||
new_peering["peer-v6"] = None
|
new_peering["peer-v6"] = None
|
||||||
new_peering["bgp-mp"] = form["bgp-multi-protocol"] if "bgp-multi-protocol" in form else "off"
|
new_peering["bgp-mp"] = form["bgp-multi-protocol"] if "bgp-multi-protocol" in form else "off"
|
||||||
new_peering["bgp-mp"] = True if new_peering["bgp-mp"] else False
|
new_peering["bgp-mp"] = True if new_peering["bgp-mp"] == "on" else False
|
||||||
new_peering["bgp-enh"] = form["bgp-extended-next-hop"] if "bgp-extended-next-hop" in form else "off"
|
new_peering["bgp-enh"] = form["bgp-extended-next-hop"] if "bgp-extended-next-hop" in form else "off"
|
||||||
new_peering["bgp-enh"] = True if new_peering["bgp-enh"] else False
|
new_peering["bgp-enh"] = True if new_peering["bgp-enh"] == "on" else False
|
||||||
#new_peering[""] = form["peer-wgkey"]
|
#new_peering[""] = form["peer-wgkey"]
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
print(f"error: {e.args}")
|
print(f"error: {e.args}")
|
||||||
|
@ -322,13 +190,13 @@ def check_peering_data(form):
|
||||||
|
|
||||||
# check bgp options
|
# check bgp options
|
||||||
try:
|
try:
|
||||||
if new_peering["bgp-mp"] == "off" and new_peering["bgp-enh"] == "on":
|
if new_peering["bgp-mp"] == False and new_peering["bgp-enh"] == True:
|
||||||
return False, "extended next hop requires multiprotocol bgp"
|
return False, "extended next hop requires multiprotocol bgp"
|
||||||
if new_peering["bgp-mp"] == "off":
|
if new_peering["bgp-mp"] == False:
|
||||||
if not (new_peering["peer-v4"] and (new_peering["peer-v6"] or new_peering["peer-v6ll"])):
|
if not (new_peering["peer-v4"] and (new_peering["peer-v6"] or new_peering["peer-v6ll"])):
|
||||||
return False, "ipv4 and ipv6 addresses required when not having MP-BGP"
|
return False, "ipv4 and ipv6 addresses required when not having MP-BGP"
|
||||||
except ValueError:
|
except ValueError:
|
||||||
...
|
pass
|
||||||
return True, new_peering
|
return True, new_peering
|
||||||
|
|
||||||
|
|
||||||
|
@ -537,13 +405,13 @@ def index():
|
||||||
# print(config._config["nodes"])
|
# print(config._config["nodes"])
|
||||||
# for node in config["nodes"].values():
|
# for node in config["nodes"].values():
|
||||||
# print (node)
|
# print (node)
|
||||||
return render_template("index.html", session=session, config=config._config)
|
return render_template("index.html", session=session, config=config, peerings = peerings)
|
||||||
|
|
||||||
|
|
||||||
|
app.static_folder = config["flask-template-dir"]+"/static/"
|
||||||
|
app.template_folder = config["flask-template-dir"]
|
||||||
|
app.secret_key = config["flask-secret-key"]
|
||||||
def main():
|
def main():
|
||||||
app.static_folder = config["flask-template-dir"]+"/static/"
|
|
||||||
app.template_folder = config["flask-template-dir"]
|
|
||||||
app.secret_key = config["flask-secret-key"]
|
|
||||||
if "production" in config and config["production"] == False:
|
if "production" in config and config["production"] == False:
|
||||||
logging.getLogger(__name__).setLevel(0)
|
logging.getLogger(__name__).setLevel(0)
|
||||||
app.run(host=config["listen"], port=config["port"],
|
app.run(host=config["listen"], port=config["port"],
|
||||||
|
|
176
web/backend/peering_manager.py
Normal file
176
web/backend/peering_manager.py
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import base64
|
||||||
|
import logging
|
||||||
|
import random
|
||||||
|
|
||||||
|
class NodeCommunicator:
|
||||||
|
|
||||||
|
def __init__(self, name:str, config):
|
||||||
|
self.name = name
|
||||||
|
self.__config = config
|
||||||
|
self.__api_addr = config["api-con"]
|
||||||
|
|
||||||
|
class PeeringManager:
|
||||||
|
|
||||||
|
def __init__(self, config):
|
||||||
|
self.__config = config
|
||||||
|
self.__peering_file = config["peerings"]
|
||||||
|
|
||||||
|
self.__load_peerings()
|
||||||
|
|
||||||
|
self._nodes = {}
|
||||||
|
for node in self.__config["nodes"]:
|
||||||
|
self._nodes[node] = NodeCommunicator(name=node, config=self.__config["nodes"][node])
|
||||||
|
|
||||||
|
self._amounts = None
|
||||||
|
|
||||||
|
def __load_peerings(self):
|
||||||
|
if not os.path.exists(self.__peering_file):
|
||||||
|
with open(self.__peering_file, "x") as p:
|
||||||
|
json.dump({"mnter": {}, "asn": {}}, p)
|
||||||
|
try:
|
||||||
|
with open(self.__peering_file, "r") as p:
|
||||||
|
self.peerings = json.load(p)
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
with open(self.__peering_file, "w") as p:
|
||||||
|
json.dump({"mnter": {}, "asn": {}}, p)
|
||||||
|
with open(self.__peering_file, "r") as p:
|
||||||
|
self.peerings = json.load(p)
|
||||||
|
|
||||||
|
# self.peerings = {}
|
||||||
|
# missing_peerings = False
|
||||||
|
# for peering in self._peerings:
|
||||||
|
# if os.path.exists(f"{self._peering_dir}/{peering}.json"):
|
||||||
|
# with open(f"{self._peering_dir}/{peering}.json") as peer_cfg:
|
||||||
|
# self.peerings[peering] = json.load(peer_cfg)
|
||||||
|
# else:
|
||||||
|
# logging.warning(f"peering with id {peering} doesn't exist. removing reference in `{self._peering_dir}/peerings.json`")
|
||||||
|
# self._peerings.remove(peering)
|
||||||
|
# missing_peerings = True
|
||||||
|
# if missing_peerings:
|
||||||
|
# with open(f"{self._peering_dir}/peerings.json","w") as p:
|
||||||
|
# json.dump(self._peerings, p, indent=4)
|
||||||
|
def _save_peerings(self):
|
||||||
|
with open(self.__peering_file, "w") as p:
|
||||||
|
json.dump(self.peerings, p, indent=4)
|
||||||
|
self._amounts = None
|
||||||
|
|
||||||
|
def _update_nodes(self, mode, peering, new_peering=None):
|
||||||
|
"""mode: "add","update","delete
|
||||||
|
peering: peering to send to node (included in peering)
|
||||||
|
new_peering: if mode=="update" the new peering to update to
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
def _update_amounts(self):
|
||||||
|
__new = {}
|
||||||
|
for asn in self.peerings["asn"]:
|
||||||
|
for peering in self.peerings["asn"][asn]:
|
||||||
|
if not peering["node"] in __new:
|
||||||
|
__new[peering["node"]] = 0
|
||||||
|
__new[peering["node"]] += 1
|
||||||
|
self._amounts = __new
|
||||||
|
|
||||||
|
|
||||||
|
def amount_by_node(self, node_name: str):
|
||||||
|
if self._amounts ==None:
|
||||||
|
self._update_amounts()
|
||||||
|
try:
|
||||||
|
return self._amounts[node_name]
|
||||||
|
except KeyError:
|
||||||
|
return 0
|
||||||
|
def exists(self, asn, node, mnt=None, wg_key=None, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True):
|
||||||
|
"""checks if a peerings with specific data already exists"""
|
||||||
|
# check if mnt is specified, already exists in the database and if that mnt has the specified ASn -> if not: return False
|
||||||
|
if mnt and not (mnt in self.peerings["mnter"] and asn in self.peerings["mnter"][mnt]):
|
||||||
|
return False
|
||||||
|
selected_peerings = self.peerings["asn"][asn]
|
||||||
|
# check if the ASn even has peerings
|
||||||
|
if len(selected_peerings) == 0:
|
||||||
|
return False
|
||||||
|
for p in selected_peerings:
|
||||||
|
if p["node"] == node:
|
||||||
|
if (not wg_key or p["wg_key"] == wg_key) and (not endpoint or p["endpoint"] == endpoint) \
|
||||||
|
and (not ipv6ll or p["ipv6ll"] == ipv6ll) and (not ipv4 or p["ipv4"] == ipv4) and (not ipv6 or p["ipv6"] == ipv6)\
|
||||||
|
and (not bgp_mp or p["bgp_mp"] == bgp_mp) and (not bgp_enh or p["bgp_enh"] == bgp_enh):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_peerings_by_mnt(self, mnt):
|
||||||
|
# print(self.peerings)
|
||||||
|
try:
|
||||||
|
out = []
|
||||||
|
for asn in self.peerings["mnter"][mnt]:
|
||||||
|
try:
|
||||||
|
for peering in self.peerings["asn"][asn]:
|
||||||
|
out.append(peering)
|
||||||
|
except KeyError as e:
|
||||||
|
pass
|
||||||
|
return out
|
||||||
|
except KeyError:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def add_peering(self, asn, node, mnt, wg_key, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True):
|
||||||
|
# check if this MNT already has a/this asn
|
||||||
|
try:
|
||||||
|
if not asn in self.peerings["mnter"][mnt]:
|
||||||
|
# ... and add it if it hasn't
|
||||||
|
self.peerings[mnt].append(asn)
|
||||||
|
except KeyError:
|
||||||
|
# ... and cerate it if it doesn't have any yet
|
||||||
|
self.peerings["mnter"][mnt] = [asn]
|
||||||
|
try:
|
||||||
|
if not asn in self.peerings["asn"]:
|
||||||
|
self.peerings["asn"][asn] = []
|
||||||
|
except KeyError:
|
||||||
|
self.peerings["asn"][asn] = []
|
||||||
|
|
||||||
|
# deny more than one peering per ASN to one node
|
||||||
|
for peering in self.peerings["asn"][asn]:
|
||||||
|
if peering["node"] == node:
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.peerings["asn"][asn].append({"MNT": mnt, "ASN": asn, "node": node, "wg_key": wg_key, "endpoint": endpoint,
|
||||||
|
"ipv6ll": ipv6ll, "ipv4": ipv4, "ipv6": ipv6, "bgp_mp": bgp_mp, "bgp_enh": bgp_enh})
|
||||||
|
|
||||||
|
self._save_peerings()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def update_peering(self, asn, node, mnt, wg_key, endpoint=None, ipv6ll=None, ipv4=None, ipv6=None, bgp_mp=True, bgp_enh=True):
|
||||||
|
# check if this MNT already has a/this asn
|
||||||
|
try:
|
||||||
|
if not asn in self.peerings["mnter"][mnt]:
|
||||||
|
# ... and add it if it hasn't
|
||||||
|
self.peerings[mnt].append(asn)
|
||||||
|
except KeyError:
|
||||||
|
# ... and cerate it if it doesn't have any yet
|
||||||
|
self.peerings["mnter"][mnt] = [asn]
|
||||||
|
try:
|
||||||
|
if not asn in self.peerings["asn"]:
|
||||||
|
return False
|
||||||
|
except KeyError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
success = False
|
||||||
|
for pNr in range(len(self.peerings["asn"][asn])):
|
||||||
|
if self.peerings["asn"][asn][pNr]["node"] == node:
|
||||||
|
self.peerings["asn"][asn][pNr] = {"MNT": mnt, "ASN": asn, "node": node, "wg_key": wg_key,
|
||||||
|
"endpoint": endpoint, "ipv6ll": ipv6ll, "ipv4": ipv4, "ipv6": ipv6, "bgp_mp": bgp_mp, "bgp_enh": bgp_enh}
|
||||||
|
success = True
|
||||||
|
if not success:
|
||||||
|
return False
|
||||||
|
self._save_peerings()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def delete_peering(self, asn, node, mnt, wg_key=None):
|
||||||
|
if not self.exists(asn, node, mnt=mnt, wg_key=wg_key):
|
||||||
|
return False
|
||||||
|
for p in self.peerings["asn"][asn]:
|
||||||
|
if p["node"] == node:
|
||||||
|
if wg_key and p["wg_key"] != wg_key:
|
||||||
|
continue
|
||||||
|
self.peerings["asn"][asn].remove(p)
|
||||||
|
self._save_peerings()
|
||||||
|
return True
|
||||||
|
# if nothing got found (should have been catched by self.exists)
|
||||||
|
return False
|
|
@ -16,7 +16,17 @@
|
||||||
<td>{{node}}</td>
|
<td>{{node}}</td>
|
||||||
<td>{{config["nodes"][node]["country"]}}</td>
|
<td>{{config["nodes"][node]["country"]}}</td>
|
||||||
<td>{{config["nodes"][node]["city"]}}</td>
|
<td>{{config["nodes"][node]["city"]}}</td>
|
||||||
<td></td>
|
<td>
|
||||||
|
{% set peerings_percentage =
|
||||||
|
(peerings.amount_by_node(node)/config['nodes'][node]['capacity']*100) %}
|
||||||
|
<div class="progress progress-bar" title="{{peerings.amount_by_node(node)}}/{{config['nodes'][node]['capacity']}}">
|
||||||
|
<div
|
||||||
|
class="progress progress-value"
|
||||||
|
style="width:'{{peerings_percentage}}px'; background-color: {% if (peerings_percentage<80) %}green{% elif (peerings_percentage < 90) %}orange{%else%}red{%endif%};"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<td><a href="peerings/new?node={{node}}">peer</a></td>
|
<td><a href="peerings/new?node={{node}}">peer</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
type="hidden"
|
type="hidden"
|
||||||
id="return"
|
id="return"
|
||||||
name="return"
|
name="return"
|
||||||
value='{{"http://"+config["domain"]+"/api/auth/kverify"}}'
|
value='{{config["domain"]+"/api/auth/kverify"}}'
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|
|
@ -214,13 +214,13 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><label for="peer-v4">your ipv4</label></td>
|
<td><label for="peer-v4">your ipv4</label></td>
|
||||||
<td><input type="checkbox" name="peer-v4-enabled" id="peer-v4-enabled"onchange="return update_from_v4()" {% if selected_peering["ipv4"] %} checked {% endif %}></td>
|
<td><input type="checkbox" name="peer-v4-enabled" id="peer-v4-enabled" onchange="return update_from_v4()" {% if selected_peering["ipv4"] %} checked {% endif %}></td>
|
||||||
<td><input type="text" name="peer-v4" id="peer-v4"onchange="return update_from_v4()" {% if selected_peering["ipv4"] %}value="{{selected_peering['ipv4']}}" {% endif %}></td>
|
<td><input type="text" name="peer-v4" id="peer-v4" onchange="return update_from_v4()" {% if selected_peering["ipv4"] %}value="{{selected_peering['ipv4']}}" {% endif %}></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><label for="peer-v6">your ipv6</label></td>
|
<td><label for="peer-v6">your ipv6</label></td>
|
||||||
<td><input type="checkbox" name="peer-v6-enabled" id="peer-v6-enabled"onchange="return update_from_v6()"{% if selected_peering["ipv6"] %} checked {% endif %}></td>
|
<td><input type="checkbox" name="peer-v6-enabled" id="peer-v6-enabled" onchange="return update_from_v6()"{% if selected_peering["ipv6"] %} checked {% endif %}></td>
|
||||||
<td><input type="text" name="peer-v6" id="peer-v6"onchange="return update_from_v6()" {% if selected_peering["ipv6"] %}value="{{selected_peering['ipv6']}}" {% endif %}></td>
|
<td><input type="text" name="peer-v6" id="peer-v6" onchange="return update_from_v6()" {% if selected_peering["ipv6"] %}value="{{selected_peering['ipv6']}}" {% endif %}></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><h4>BGP</h4></td>
|
<td><h4>BGP</h4></td>
|
||||||
|
@ -228,13 +228,13 @@
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>MultiProtocol</td>
|
<td><label for="bgp-multi-protocol">MultiProtocol</label></td>
|
||||||
<td><input type="checkbox" name="bgp-multi-protocol" id="bgp-multi-protocol" onchange="return update_from_mpbgp()" {% if selected_peering["bgp-mp"] %} checked {% endif %}></td>
|
<td><input type="checkbox" name="bgp-multi-protocol" id="bgp-multi-protocol" onchange="return update_from_mpbgp()" {% if selected_peering["bgp_mp"] == True %} checked {% endif %}></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>extended next hop</td>
|
<td><label for="bgp-extended-next-hop">extended next hop</label></td>
|
||||||
<td><input type="checkbox" name="bgp-extended-next-hop" id="bgp-extended-next-hop" onchange="return update_from_enh()" {% if selected_peering["bgp-enh"] %} checked {% endif %}></td>
|
<td><input type="checkbox" name="bgp-extended-next-hop" id="bgp-extended-next-hop" onchange="return update_from_enh()" {% if selected_peering["bgp_enh"] == True%} checked {% endif %}></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -62,6 +62,72 @@ footer.flex {
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* # index.html */
|
||||||
|
|
||||||
|
/* based on https://codepen.io/t_afif/pen/RwQZLYb */
|
||||||
|
.progress-bar {
|
||||||
|
--w: 100px; /* the width*/
|
||||||
|
|
||||||
|
--background: lightgrey; /* the background color */
|
||||||
|
width: var(--w);
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
.progress {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 10em;
|
||||||
|
background: var(--background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-value[value]{
|
||||||
|
--color: /* the progress color */
|
||||||
|
/* linear-gradient(#fff8,#fff0), */
|
||||||
|
/* repeating-linear-gradient(135deg,#0003 0 10px,#0000 0 20px), */
|
||||||
|
/* if < 30% "red" */
|
||||||
|
linear-gradient(green 0 0) 0 /calc(var(--w)*.8 - 100%) 1px,
|
||||||
|
/* if < 60% "orange" */
|
||||||
|
linear-gradient(orange 0 0) 0 /calc(var(--w)*.9 - 100%) 1px,
|
||||||
|
/* else "green" */
|
||||||
|
red;
|
||||||
|
background-color: var(--color);
|
||||||
|
align-self: left;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress[value]::-webkit-progress-bar {
|
||||||
|
border-radius: 10em;
|
||||||
|
background: var(--background);
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress[value]::-webkit-progress-value {
|
||||||
|
border-radius: 10em;
|
||||||
|
background: var(--color);
|
||||||
|
}
|
||||||
|
.progress[value]::-moz-progress-bar {
|
||||||
|
border-radius: 10em;
|
||||||
|
background-color: var(--color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .progress:before { */
|
||||||
|
/* position:absolute; */
|
||||||
|
/* height:30px; */
|
||||||
|
/* background:green; */
|
||||||
|
/* content:'50%'; hrere you should add the text */
|
||||||
|
/* top:0; */
|
||||||
|
/* left:0; */
|
||||||
|
/* width:50%; */
|
||||||
|
/* display:flex; */
|
||||||
|
/* color:white; */
|
||||||
|
/* align-items:center; */
|
||||||
|
/* justify-content:flex-end; */
|
||||||
|
/* padding-right:10px; */
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
|
||||||
|
/* for peerings-{edit,new}.html */
|
||||||
.example-config {
|
.example-config {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 1%;
|
padding: 1%;
|
||||||
|
@ -78,6 +144,7 @@ form>div>* {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for peerings.html */
|
||||||
.peering {
|
.peering {
|
||||||
border-color: var(--other-background);
|
border-color: var(--other-background);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
|
@ -99,6 +166,11 @@ form>div>* {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.peering>* {
|
||||||
|
width: auto;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
/* button def */
|
||||||
button,
|
button,
|
||||||
input[type=button] {
|
input[type=button] {
|
||||||
background-color: #00000020;
|
background-color: #00000020;
|
||||||
|
@ -113,10 +185,6 @@ input[type=button].button-selected {
|
||||||
color: var(--text-color-dark);
|
color: var(--text-color-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
.peering>* {
|
|
||||||
width: auto;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-blue {
|
.button-blue {
|
||||||
border-color: lightblue;
|
border-color: lightblue;
|
||||||
|
|
Loading…
Add table
Reference in a new issue