RNDMISC-440: First Milestone

This commit is contained in:
Leon Schoch
2023-08-25 08:57:04 +00:00
parent f0c7d3c0d4
commit 0fdf86c992
13 changed files with 308 additions and 72 deletions

View File

@@ -5,12 +5,141 @@
%% -*- coding: utf-8 -*-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Staging Umgebung}
\chapter{API Komponente}
\section{Konzeption} %TODO RNDSUP-423
\section{Aufgaben}
Die \ac{API} ist die Schnittstelle des Service und außen stehenden Technologien wie der Anexia Engine.
Ihre Hauptaufgabe besteht darin, eine strukturierte Interaktionsmöglichkeit zu bieten, die es internen Benutzern über Systeme wie der Anexia Engine ermöglicht, \ac{BGP}-Routen mit zugehörigen \ac{BGP}-Communities in das Netzwerk zu injizieren.
Dies geschieht durch die Annahme von \ac{JSON}-Anfragen, die spezifische Informationen enthalten, nämlich IPv4- oder IPv6-Präfixe und die entsprechenden \ac{BGP}-Communities.
Die \ac{API} führt eine umfassende Validierung der eingehenden Daten durch, um sicherzustellen, dass die bereitgestellten Informationen korrekt und im erwarteten Format vorliegen.
Diese Validierung umfasst die Überprüfung der Richtigkeit der IP-Adressbereiche sowie die syntaktische Korrektheit der zugeordneten \ac{BGP}-Communities.
Durch diesen Schritt wird gewährleistet, dass nur gültige Informationen in das System eingebracht werden.
Die validierten Daten werden anschließend an Consul, über dessen eigene \ac{API} übermittelt.
Die Daten werden so abgelegt, dass der Injector einen erleichterten Zugriff hat.
\newpage
\section{Umsetzung}
Da die Konzeption und Implementierung der \ac{API} schon umfassend in der Projektarbeit T1000 erläutert wurde, wird auf eine Wiederholung dessen verzichtet.
In diesem Bericht wird lediglich die Implementierung des `Delete`-Endpunkts dargestellt, da dieser aus zeitlichen Gründen nicht mehr in den ersten beiden Praxisphase implementiert werden konnte, jedoch ein Grundbestandteil des entwickelten Service ist.
\vspace{1cm}
Die Implementierung eines `Delete`-Endpunkts in der API, mittels des Django Rest Frameworks, ermöglicht das Löschen von Routen aus dem System.
\begin{lstlisting}[language=python,
frame=single, % Ein Rahmen um den Code
framexleftmargin=15pt, % Rahmen link von den Zahlen
style=algoBericht,
label={lst:baserouteviewset},
captionpos=b, % Caption unter den Code setzen
caption={BaseRouteViewset Klasse}]
class BaseRouteViewSet(
CreateModelMixin,
ReadOnlyModelViewSet,
BaseRequestViewSet,
):
@action(detail=False, url_path=r"([A-Za-z-_/]*)status/(?P<task_info_id>[0-9a-z-]+)")
def status(self, request, task_info_id):
route_object = get_object_or_404(
self.serializer_class.Meta.model, task_info_id=task_info_id
)
propagate_status(route_object)
return super().status(request, task_info_id)
\end{lstlisting}
Der in Snippet 4.1 gezeigte Code stellt eine Mutterklasse dar, von welcher sowohl der `Create`, als auch `Delete`-Endpunkt erben.
Durch diese Klasse wird die Möglichkeit gegeben, von der Anexia Engine erwartete Endpunkte einfach zu implementieren, ohne dass sich ein Entwickler mit den Feinheiten dessen auseinandersetzen muss.
Da hier die \verb|CreateModelMixin| Klasse geerbt wird, stellt sich das \ac{DRF} automatisch ein 'POST'-Requests für diesen Endpunkt zu akzeptieren.
\newpage
\begin{lstlisting}[language=python,
frame=single, % Ein Rahmen um den Code
framexleftmargin=15pt, % Rahmen link von den Zahlen
style=algoBericht,
label={lst:deleterouteviewset},
captionpos=b, % Caption unter den Code setzen
caption={DeleteRouteViewset Klasse}]
class DeleteRouteViewSet(BaseRouteViewSet):
queryset = DeleteRoute.objects.all()
serializer_class = DeleteRouteSerializer
def perform_create(self, serializer):
super().perform_create(serializer)
delete_route(serializer.instance)
\end{lstlisting}
Die tatsächliche Implementierung fällt durch das Erben von der `BaseRouteViewSet` Mutterklasse sehr simpel aus.
Durch das Überschreiben der \verb|perform_create| Methode, welche vom \ac{DRF} zur Verfügung gestellt wird, kann diese als Hook benutzt werden um eigenen Code ausführen zu lassen.
Mit der Super Methode wird sichergestellt, dass die nicht überschriebene Ursprungsmethode von \verb|perform_create| ausgeführt wird.
Das \ac{DRF} erstellt dann einen Datenbankeintrag mit den vom Nutzer eingegeben Werten.
Vor dem Ende des Kontextes der Methode wird noch eine weitere Methode \verb|delete_route| aufgerufen.
\begin{lstlisting}[language=python,
frame=single, % Ein Rahmen um den Code
framexleftmargin=15pt, % Rahmen link von den Zahlen
style=algoBericht,
label={lst:deleteroute},
captionpos=b, % Caption unter den Code setzen
caption={delete\_route Methode}]
def delete_route(instance):
consul_instance = prepare_consul(os.getenv("CONSUL_HOST"), os.getenv("CONSUL_PORT"))
prefix = str(instance.prefix)
prefix_encoding = get_prefix_encoding(prefix)
consul_instance.kv.delete(
f'v1/route/global/{prefix_encoding}/{prefix.replace("/", "_")}'
)
update_active_injectors(instance)
\end{lstlisting}
Hier findet nun das eigentliche Übermitteln der Daten an Consul statt.
\chapter{Injector Komponente}
\section{Aufgaben}
Der Injector ist der zentrale Baustein des Route Injection Service, der die Möglichkeit bietet, mittels \ac{BGP} Communities, Routen in das Netzwerk zu injizieren.
Der Injector erfüllt dabei eine Reihe von wesentlichen Aufgaben:
\vspace{1cm}
Zuallererst ist der Injector für die Konvertierung der von der \ac{API} empfangenen Routen in eine für den Router (Bird) verständliche Konfigurationsdatei verantwortlich.
Diese Konvertierung ist von entscheidender Bedeutung, um die Weiterleitung der Routen an den Router in einem kompatiblen Format sicherzustellen.
Während die Validierung der Präfixe und Communities von der \ac{API} Komponente übernommen wird, hat der Injector eine eigene Validierung für Routen, welchen über den Emergency-Mode angegeben werden, da hier die \ac{API} Komponente überbrückt wird.
Bei auftretenden Konflikten oder Unstimmigkeiten kann der Injector angemessene Maßnahmen ergreifen, um die Integrität der anderen Komponenten und schlussendlich des Netzwerks, zu gewährleisten.
Ein wichtiger Aspekt ist auch die aktive Kommunikation des Injectors mit dem Router (Bird).
Diese Kommunikation erfolgt, um die generierten Konfigurationsänderungen effektiv zu übertragen und sicherzustellen, dass die injizierten Routen nahtlos in das Routing-Protokoll des Routers integriert werden.
Schließlich stellt der Injector durch präzises loggen sicher, dass im Falle eines Fehlers, oder im schlimmsten Fall, bei einem Absturz der Komponente, Ereignisse festgehalten werden.
Zusammenfassend fungiert der Injector als entscheidende Schnittstelle, die die Funktionen der \ac{API} und des Routers miteinander verbindet.
Mit seiner intelligenten Konvertierung und Verwaltung von Routen durch \ac{BGP} Communities gewährleistet er, dass die gewünschten Routing-Änderungen präzise und effizient im \ac{BGP}-Netzwerk implementiert werden.
\newpage
\section{Umsetzung}
\subsection{Generieren der Config Files für Bird} %TODO RNDMISC-410
Um die Routen an den Bird Routing Daemon übermitteln zu können, müssen diese erst in eine für Bird verständliche Konfigurationsdatei umgewandelt werden.
%Warum verwenden wir Jinja und wie funktionierts?
\subsubsection{Integrität der Konfigurationsdatei sicherstellen} %TODO RNDMISC-420
\subsection{Status der Routen von Bird abfragen} %TODO RNDMISC-361
\subsubsection{Evaluation der pybird Bibliothek}
\subsection{Bird und Bird6 aufteilen} %TODO RNDMISC-362
\subsection{Realisierung des Heartbeats}
\subsection{Emergency-Mode implementieren} %TODO RNDMISC-363
\section{Testen}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\endinput
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%