From 09da5ec8302e7ac5c082cbf93d679231b5cd8fa5 Mon Sep 17 00:00:00 2001 From: lare Date: Wed, 14 Jun 2023 08:52:17 +0200 Subject: [PATCH] [web] notify user if something failed in the backend --- web/backend/main.py | 6 ++- web/backend/peering_manager.py | 79 +++++++++++++++++++++------------- 2 files changed, 53 insertions(+), 32 deletions(-) diff --git a/web/backend/main.py b/web/backend/main.py index 9c79dcb..2c6b506 100644 --- a/web/backend/main.py +++ b/web/backend/main.py @@ -391,8 +391,9 @@ def peerings_new(): if not peering_valid: return render_template("peerings-new.html", session=session, config=config, peerings=peerings, msg=peering_or_msg), 400 - if not peerings.add_peering(session["user-data"]["asn"], request.args["node"], session["user-data"]["mnt"], peering_or_msg["peer-wgkey"], peering_or_msg["peer-endpoint"], peering_or_msg["peer-v6ll"], peering_or_msg["peer-v4"], peering_or_msg["peer-v6"], peering_or_msg["bgp-mp"], peering_or_msg["bgp-enh"]): - return render_template("peerings-new.html", session=session, config=config, peerings=peerings, msg="this ASN already has a peering with the requested node"), 400 + success, code = peerings.add_peering(session["user-data"]["asn"], request.args["node"], session["user-data"]["mnt"], peering_or_msg["peer-wgkey"], peering_or_msg["peer-endpoint"], peering_or_msg["peer-v6ll"], peering_or_msg["peer-v4"], peering_or_msg["peer-v6"], peering_or_msg["bgp-mp"], peering_or_msg["bgp-enh"]) + if not success: + return render_template("peerings-new.html", session=session, config=config, peerings=peerings, msg="this ASN already has a peering with the requested node or something failed in the backend, please retry later"), code return redirect(f"{config['base-dir']}peerings") @@ -411,6 +412,7 @@ def peerings_view(): elif request.method == "DELETE": return peerings_delete() else: + # shouldn't get here abort(405) diff --git a/web/backend/peering_manager.py b/web/backend/peering_manager.py index b950cd8..8e076f1 100644 --- a/web/backend/peering_manager.py +++ b/web/backend/peering_manager.py @@ -15,14 +15,21 @@ class NodeCommunicator: self.__api_addr = config["api-con"] def update(self, action: str, peering: dict): - if action == "add": - print(requests.post(f"{self.__api_addr}peerings", json=peering)) - elif action == "update": - print(requests.put(f"{self.__api_addr}peerings", json=peering)) - elif action == "delete": - print(requests.delete(f"{self.__api_addr}peerings", json=peering)) - else: - return 400 + try: + if action == "add": + req = requests.post(f"{self.__api_addr}peerings", json=peering, timeout=6) + elif action == "update": + req = requests.put(f"{self.__api_addr}peerings", json=peering, timeout=6) + elif action == "delete": + req = requests.delete(f"{self.__api_addr}peerings", json=peering, timeout=6) + else: + return 400 + + # should only get here if a request was "successful" (not necessarily http code 200) + return req.status_code + except requests.exceptions.ReadTimeout: + # if it took more than timeout for the client to respond + return 504 class PeeringManager: @@ -78,15 +85,13 @@ class PeeringManager: new_peering: if mode=="update" the new peering to update to """ if peering["node"] in self._nodes: - #thread = threading.Thread(target= - self._nodes[peering["node"]].update(#), kwargs={ - action=action, peering = peering if not new_peering else new_peering#, }) - ) - #thread.start() - #self._threads.append(thread) - + return_code = self._nodes[peering["node"]].update(action=action, peering = peering if not new_peering else new_peering) + if return_code in [200, 201]: + return True, return_code + else: + return False, return_code else: - return False + return False, 404 def _update_amounts(self): __new = {} @@ -158,10 +163,14 @@ class PeeringManager: peering = {"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, code = self._update_nodes("add", peering=peering) + if not success: + # if ssomething failed notify user and don't add it to the list + return False, code + # self.peerings["asn"][asn].append(peering) - self._update_nodes("add", peering=peering) self._save_peerings() - return True + return True, code 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 @@ -170,13 +179,15 @@ class PeeringManager: # ... and add it if it hasn't self.peerings[mnt].append(asn) except KeyError: - # ... and cerate it if it doesn't have any yet + # ... and create it if it doesn't have any yet self.peerings["mnter"][mnt] = [asn] try: + # there are no peerings for this asn -> can't edit nothing... if not asn in self.peerings["asn"]: - return False + return False, 404 except KeyError: - return False + # this should only happen if "asn" not in self.peerings + return False, 404 success = False for pNr in range(len(self.peerings["asn"][asn])): @@ -185,23 +196,31 @@ class PeeringManager: new_peering = 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 + peering_number = pNr if not success: return False + # notify the node + + success, code = self._update_nodes("update", old_peering, new_peering=new_peering) + if not success: + # revert updating peering + self.peerings["asn"][asn][peering_number] = old_peering + return False, code + else: - self._save_peerings() - self._update_nodes("update", old_peering, new_peering=new_peering) - return True + self._save_peerings() + return True, code def delete_peering(self, asn, node, mnt, wg_key=None): if not self.exists(asn, node, mnt=mnt, wg_key=wg_key): - return False + return False, 404 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() - self._update_nodes("delete", peering=p) - return True + success, code = self._update_nodes("delete", peering=p) + print(f"DELETE: {asn} on {node}: {success}, {code}") + return success, code # if nothing got found (should have been catched by self.exists) - return False + return False, 404