title: "Sieć" subtitle: "Dokumentacja projektowa PZSP2" date: "2025-01-10" titlepage: true titlepage-color: "FFFFFF" titlepage-text-color: "000000" titlepage-rule-color: "000000" titlepage-rule-height: 2
\newpage
Wersja 2.0
Zespół nr 2 w składzie
- Maksym Bieńkowski
- Mikołaj Garbowski
- Michał Łuszczek
- Krzysztof Sokół
Mentor zespołu: mgr. inż. Klara Borowa
Właściciel tematu: dr. inż. Stanisław Kozdrowski
Celem jest stworzenie aplikacji wspomagającej optymalizację bieżącego ruchu w realistycznej sieci teleinformatycznej. Podstawowym zadaniem jest odzwierciedlenie aktualnej zajętości pasma w sieci optycznej na podstawie plików z baz danych: w postaci arkusza kalkulacyjnego, jak i w postaci graficznej na modelu topologicznym sieci (mapa zajętości). W przeciwieństwie do technologii fixed grid, która zakłada równomierny podział pasma między kanały, stosowany model flex grid umożliwia zmienny przydział jednostek nazywanych slice'ami. Pozwala to na minimalizację marnowanego pasma, co prowadzi do zmniejszenia kosztów dzierżawy włókien przesyłowych. Problem optymalnej rozbudowy sieci należy do kategorii NP-trudnych. Naszym celem jest stworzenie aplikacji ułatwiającej zarządzanie taką siecią.
Głównymi celami są
- czytelna reprezentacja sieci w postaci grafu
- możliwość zestawienia nowych kanałów i automatyczny dobór optymalnych tras zapewniających równomierne obciążenie sieci
- generowanie raportów zajętości slice'ów w postaci plików csv
- zaproponowanie modelu w postaci matematycznej, zawierającego funkcję celu (kosztu) oraz zbioru ograniczeń, optymalizującego pasmo oraz ruting nowo-zestawianych kanałów (ścieżek) optycznych w sieci
Słowik pojęć
- pasmo - zakres częstotliwości światła, na którym przesyłane są dane
- slice’y - kawałki pasma o różnej rozpiętości częstotliwościowej
- krawędź - para włókien optycznych dzierżawionych przez firmę telekomunikacyjną
- kanał - ścieżka między dwoma wierzchołkami zajmująca tę samą grupę slice'ów na każdej krawędzi
- wierzchołek - punkt rozdzielczy sieci telekomunikacyjnej
Projekt realizowany jako aplikacja sieciowa.
Tryb Działania
- Użytkownik ma do dyspozycji interfejs, na którym wyświetlana jest sieć w postaci grafu.
- Dla polepszenia czytelności graf nałożony będzie na mapę, przez co łatwo będzie identyfikować połączenia.
- Interfejs użytkownika udostępnia narzędzia do modyfikacji modelu sieci i parametrów modeli optymalizacyjnych.
- System dostarcza modeli optymalizacyjnych do wyznaczania nowych kanałów w sieci.
Dane
Danymi w projekcie są:
- dostarczony przez użytkownika plik zawierający koordynaty punktów rozdzielczych, istniejące połączenia i kanały
- wewnętrzna reprezentacja grafowa sieci
- wygenerowany raport w formacie csv z informacjami o zajętości slice'ów - informacje o połączeniu, slice i czy jest obecnie używany
System nie będzie trwale przechowywać danych.
\newpage
\begin{align*} & N: \text{zbiór węzłów (wierzchołków).} \ & E \subseteq N \times N: \text{zbiór skierowanych krawędzi.} \ & K = {0,1,\dots,767}: \text{zbiór indeksów slice'ów.} \end{align*}
\begin{align*} & w_{ij} & & \text{koszt (waga) użycia krawędzi }(i,j)\in E.\ & & & \text{Wyliczanie wartości wagi rozwiązywane jest poza modelem całkowitoliczbowym} \ & & & \text{i jest częścią wspólną logiki stosowanych optymalizatorów.} \ & s \in N & & \text{wierzchołek źródłowy (source).} \ & t \in N & & \text{wierzchołek docelowy (target).} \ & \text{O}{(i,j),k} \in {0,1} & & \text{parametr binarny wskazujący, czy slice }k \text{ jest zajęty (}1\text{)} \ & & & \text{czy wolny (}0\text{) na krawędzi }(i,j). \ & S \in \mathbb{Z}{\ge 0} & & \text{liczba \emph{ciągłych} slice'ów wymagana na każdej wybranej krawędzi.} \end{align*}
\begin{align*} & x_{ij} \in {0,1} & & \text{równe }1\text{, jeśli krawędź }(i,j)\text{ jest użyta w ścieżce; }0\text{ w p.p.} \ & y_{k} \in {0,1} & & \text{równe }1\text{, jeśli slice }k \text{ jest wybrany jako \emph{początek} } \ & & & \text{ciągłego przedziału; }0\text{ w p.p.} \ & z_{(i,j),k} \in {0,1} & & \text{zmienna pomocnicza do powiązania }x_{ij} \text{ i } y_k. \end{align*}
Jej celem jest zminimalizowanie łącznego kosztu (wagi) wszystkich wybranych krawędzi. Obliczanie wagi jest wspólne dla obu modeli optymalizacyjnych, dlatego nie jest ujęta w samym modelu całkowitoliczbowym. Waga krawędzi to suma ważona jej długości (na podstawie współrzędnych geograficznych) oraz obciążenia, gdzie wagi w tej sumie są parametrami użytkownika.
\newpage
Zapewnia to, że ze źródła wypływa dokładnie 1 jednostka przepływu, do ujścia wpływa 1 jednostka, a pozostałe węzły mają
bilans zerowy (co definiuje ścieżkę od
$$ \forall,(i,j) \in E:\quad \sum_{\substack{k \in K \ k + S - 1 ,\le, \max(K)}} \Biggl( y_k \cdot \prod_{r = k}^{k + S - 1} \bigl[1 - \text{O}{(i,j),r}\bigr] \Biggr) ;;\ge;; x{ij}. $$
Dla każdej krawędzi
Jeśli
Jeżeli slice
$$
\sum_{\substack{k \in K \ k + S - 1 ,\le, \max(K)}}
y_k
;=; 1.
$$
Dokładnie jeden slice
\newpage
- Praca, poza określonymi w harmonogramie konsultacjami, organizowana jest w formie zwinnej.
- Przewidziane są cotygodniowe spotkania zdalne w ramach zespołu, w trakcie których członkowie ustalają priorytety i dzielą się zadaniami.
- Przydział zadań widoczny jest na Github w postaci issues.
- Dodatkowo dostępna jest ciągła komunikacja na platformie discord.
Role w zespole według podziału Belbina
- Mikołaj Grabowski - Shaper, Implementer, Team worker
- Maksym Bieńkowski - Implementer, Resource Investigator, Team Worker
- Michał Łuszczek - Coordinator, Implementer, Team Worker
- Krzysztof Sokół - Implementer, Evaluator
\newpage
Wymagania biznesowe
Aktorzy: osoba zarządzająca rozkładem połączeń w sieci
- Próba minimalizacji kosztów wynikających z dzierżawy włókien przesyłowych
- Ułatwienie rozszerzania sieci o nowe połączenia
- Rozwiązanie problemu wyboru optymalnej trasy nowego połączenia
- Ułatwienie administracji siecią
- Zapewnienie jak największej niezawodności sieci poprzez równomierne rozłożenie obciążeń pozwalające na poprowadzenie alternatywnego połączenia w przypadku zerwania fizycznych węzłów
- Rozwiązanie problemu identyfikacji najbardziej obciążonych odcinków sieci
Wymagania użytkowe
- Użytkownik powinien mieć możliwość zdefiniowania sieci poprzez przesłanie pliku zawierającego jej reprezentację
- Użytkownik powinien mieć możliwość wizualnego podglądu zajętości slice’ów poszczególnych krawędzi w sieci
- Użytkownik powinien mieć możliwość zdefiniowania nowego kanału w sieci o określonej przepustowości łączącego zadane dwa wierzchołki
- Użytkownik powinien otrzymać optymalne ułożenie nowego kanału w sieci
- Użytkownik powinien mieć możliwość pobrać plik reprezentujący zajętość pasma na każdym ze zdefiniowanych kanałów w sieci
- Dane użytkownika nie powinny być dostępne dla innych użytkowników systemu
- Użytkownik powinien mieć możliwość zmiany parametrów algorytmu optymalizacyjnego.
Wymagania systemowe
- System powinien udostępnić użytkownikowi graficzną reprezentację sieci w formie grafu
- System powinien wyświetlać zajętość slice'ów danej krawędzi po naciśnięciu na nią myszką
- System powinien wyświetlać krawędzie w różnych kolorach reprezentujących zajętość pasma
- System powinien ustalać optymalne ułożenie nowo zdefiniowanego kanału
- System powinien udostępniać optymalizację ułożenia dodawanego kanału przy pomocy algorytmu Dijkstry
- System powinien udostępniać optymalizację ułożenia dodawanego kanału przy pomocy modelu całkowitoliczbowego
- System powinien umożliwić wyeksportowanie reprezentacji sieci w pliku CSV w następującym formacie:
- Wierszowi tabeli odpowiada pojedynczy kanał
- Kolumnie tabeli odpowiada pojedynczy slice
- Zawartością komórki tabeli jest binarna informacja o zajętości kanału w danej ścieżce
- Reprezentacja sieci w sesji danego użytkownika powinna być widoczna tylko dla niego
- System powinien umożliwić zapisanie stanu sieci
- System powinien umożliwić odtworzenie sieci z wcześniej zapisanego stanu
Wymagania funkcjonalne
- Użytkownik powinien mieć możliwość przesłania pliku w formacie
.csv
zawierającego reprezentację sieci. - Aplikacja powinna udostępnić użytkownikowi graficzną reprezentację sieci w postaci grafu.
- Użytkownik powinien mieć możliwość zdefiniowania nowego kanału w sieci łączącej zadane dwa wierzchołki, określając jego przepustowość.
- Użytkownik powinien mieć możliwość wyświetlania grafu zrzutowanego na mapę geograficzną obszaru na podstawie współrzędnych poszczególnych węzłów.
- Aplikacja powinna dynamicznie zmieniać kolor krawędzi grafu w zależności od poziomu zajętości slice'ów tej krawędzi.
- Użytkownik powinien mieć możliwość podglądu szczegółowych danych dotyczących zajętości slice'ów określonej krawędzi poprzez najechanie na nią kursorem.
- Ułożenie nowych kanałów określane będzie przy pomocy algorytmu optymalizacyjnego.
- Aplikacja umożliwia optymalizację ułożenia nowego kanału za pomocą algorytmu Dijkstry.
- Aplikacja umożliwia optymalizację ułożenia nowego kanału przy użyciu modelu całkowitoliczbowego.
- Użytkownik powinien mieć możliwość zmiany parametrów algorytmu optymalizacyjnego.
Wymagania niefunkcjonalne
- Aplikacja powinna dostarczać wynik optymalizacji ułożenia kanału w czasie nie dłuższym niż 5 minut dla sieci złożonej z nie więcej niż 300 kanałów.
Biznesowe przypadki użycia
Aktorzy: użytkownik.
Scenariusz główny:
- System wyświetla graficzną prezentację sieci teletransmisyjnej.
- System wyświetla zbiorcze statystyki sieci.
- Użytkownik wybiera element sieci.
- System wyświetla szczegółowe informacje o elemencie.
Aktorzy: użytkownik.
Scenariusz główny:
- Użytkownik wybiera opcję generowania zestawienia dla załadowanej sieci.
- System generuje zestawienie.
- Użytkownik pobiera plik z zestawieniem.
Aktorzy: użytkownik.
Scenariusz główny:
- Użytkownik wprowadza parametry dla pożądanego kanału.
- System prezentuje nowy kanał na wizualizacji sieci.
- System wyświetla parametry nowego kanału.
Scenariusz alternatywny - system nie może wyznaczyć żądanego kanału:
- Użytkownik wprowadza parametry dla pożądanego kanału.
- System informuje użytkownika o niepowodzeniu wyznaczania nowego kanału.
- System umożliwia ponowne wprowadzenie parametrów - powrót do kroku 1.
Systemowe przypadki użycia
Aktorzy: użytkownik.
Scenariusz główny:
- Użytkownik otwiera widok wprowadzania danych.
- Użytkownik wybiera plik z opisem sieci (RB1).
- Użytkownik potwierdza, że chce nadpisać aktualnie załadowaną w systemie sieć.
- System informuje użytkownika o poprawnym załadowaniu pliku.
- System wyświetla widok prezentacji załadowanej sieci.
Scenariusz alternatywny - nieprawidłowy plik:
- Jak w scenariuszu głównym.
- System informuje użytkownika o nieprawidłowym formacie pliku.
- System wyświetla informację o akceptowanych formatach (RB1).
- System umożliwia ponowny wybór pliku - powrót do kroku 1.
Wspiera procedurę PB1 - Przeglądanie prezentacji sieci.
Korzysta z FU1.
Aktorzy: użytkownik.
Scenariusz główny:
- Użytkownik wprowadza opis sieci za pomocą funkcji FU1.
- Użytkownik otwiera widok prezentacji sieci.
- System wyświetla graficzną prezentację topologii sieci i zajętości pasma w krawędziach.
- System wyświetla zbiorcze statystyki sieci (RB4).
- Użytkownik wybiera element sieci (węzeł, krawędź, kanał).
- System wyświetla parametry elementu (RB2, RB3, RB5).
Wspiera procedurę PB2 - Wygenerowanie zestawienia zajętości pasma przez kanały.
Korzysta z FU1.
Aktorzy: użytkownik.
Scenariusz główny:
- Użytkownik wprowadza do systemu opis sieci za pomocą funkcji FU1.
- Użytkownik wybiera widok generowania zestawienia.
- System generuje plik w ustalonym formacie (RB6).
- Użytkownik pobiera plik.
Wspiera procedurę PB3 - Wyznaczenie nowego kanału.
Korzysta z funkcji FU1.
Aktorzy: użytkownik.
Scenariusz główny:
- Użytkownik wprowadza opis sieci do systemu za pomocą funkcji FU1.
- Użytkownik wybiera widok wyznaczania kanału.
- Użytkownik wybiera model optymalizacyjny (RB7).
- Użytkownik wprowadza parametry dla modelu (RB7).
- Użytkownik potwierdza wybór.
- System sygnalizuje przetwarzanie.
- System prezentuje znaleziony kanał na wizualizacji.
- System wyświetla parametry kanału (RB5).
Scenariusz alternatywny - system nie może wyznaczyć żądanego kanału:
- Jak w scenariuszu głównym.
- Jak w scenariuszu głównym.
- Jak w scenariuszu głównym.
- Jak w scenariuszu głównym.
- System informuje użytkownika o niepowodzeniu i jego przyczynie.
- System umożliwia zmianę parametrów i podobną próbę - powrót do kroku 4.
- Pliki w formacie .csv
- Pierwszy wiersz zawiera nazwy kolumn
- ID węzła
- Szerokość geograficzna (stopnie)
- Długość geograficzna (stopnie)
- ID krawędzi
- ID węzła początkowego
- ID węzła końcowego
- Szerokość całego dostępnego pasma (stałe 4.8 THz)
- Wykorzystane pasmo (procenty)
- ID krawędzi
- ID kanału
- Częstotliwość środkowa (THz)
- Szerokość (GHz)
- Długość fali (redundantna, nieużywana)
- Redundantne ID kanału (nieużywane)
- ID (napis)
- Szerokość geograficzna (liczba rzeczywista)
- Długość geograficzna (liczba rzeczywista)
- ID sąsiadów (lista napisów)
- ID (napis)
- ID węzła 1 (napis)
- ID węzła 2 (napis)
- Szerokość całego dostępnego pasma (napis)
- Wykorzystane pasmo w procentach (liczba całkowita)
- Liczba węzłów
- Liczba krawędzi
- Liczba kanałów
- Całkowite obciążenie sieci (procenty)
- Najbardziej obciążony kanał
- ID (napis)
- ID kolejnych węzłów na ścieżce (lista napisów)
- ID kolejnych krawędzi na ścieżce (lista napisów)
- Częstotliwość środkowa w THz (liczba rzeczywista)
- Szerokość w GHz (liczba rzeczywista)
- Wiersz 1 - częstotliwości środkowe kanałów 112.5 GHz
- Wiersz 2 - częstotliwości środkowe kanałów 50 GHz
- Wiersz 3 - częstotliwości środkowe kanałów 75 GHz
- Wiersz 4 - częstotliwość początkowa slice'a szerokości 6.25 GHz
- Kolumna 1 - ID kanału
- Komórki - wartość 1, jeśli slice jest zajęty przez kanał, pusta w przeciwnym wypadku
- Dostępne modele:
- algorytm Dijkstry
- model całkowitoliczbowy
- Parametry modelu (jednakowe dla obu)
- ID węzła początkowego
- ID węzła końcowego
- przepustowość kanału w Gb/s
- wagi funkcji celu (kosztu) dla poszczególnych kryteriów - długość i obciążenie krawędzi
\newpage
Opis architektury projektu w modelu 4+1
Przypadki użycia opisane w punkcie \ref{use-cases} dokumentacji.
- Rysunek \ref{fig:logical-view} przedstawia diagram klas
- Użytkownik (analityk) korzysta z interfejsów do
- wprowadzania opisu sieci do systemu
- przeglądania prezentacji sieci
- generowania raportu zajętości pasma przez kanały
- wyznaczanie nowego kanału z użyciem modelu optymalizacyjnego
- System dostarcza 2 modeli optymalizacyjnych
- oparty o algorytm Dijkstry
- oparty o model programowania całkowitoliczbowego
- Pojęcia użyte w modelu sieci są objaśnione w punkcie \ref{project-goal} dokumentacji
- Diagram \ref{fig:process-view} przedstawia typowe użycie systemu
- Użytkownik zaczyna od wprowadzenia opisu sieci
- Dla załadowanej sieci użytkownik może
- obejrzeć jej wizualizację i przeglądać parametry jej elementów
- wygenerować raport na podstawie aktualnie załadowanej sieci
- zestawić nowy kanał w sieci wykorzystując model optymalizacyjny
- Rysunek \ref{fig:development-view} przedstawia diagram komponentów
- Aplikacja webowa dostarcza widoków użytkownika do
- importu opisu sieci z plików .csv
- przeglądania graficznej prezentacji sieci (wizualizacja sieci i podgląd statystyk wybranych elementów)
- generowania raportów w formacie .csv
- korzystania z modeli optymalizacyjnych
- Modele optymalizacyjne są zaimplementowane po stronie serwera
- API Controller przyjmuje żądania, zleca przeprowadzenie optymalizacji i odsyła wynik
W implementacji podsystemu WebApp
planujemy wykorzystać framework React (Typescript) i bibliotekę
do wizualizacji grafów (do ustalenia).
W implementacji podsystemu OptimisationBackend
planujemy wykorzystać framework FastAPI (Python),
bibliotekę Pyomo oraz solwer dla modeli programowania całkowitoliczbowego (do ustalenia).
Do zweryfikowania pozostaje kwestia, czy istnieje solwer na licencji Open Source, który obsłuży nasz model całkowitoliczbowy i zbiór danych. Alternatywnie możemy wykorzystać oprogramowanie AMPL, w środowisku chmurowym dostępnym dla PW, na który licencję może udostępnić nam właściciel tematu.
- Rysunek \ref{fig:physical-view} przedstawia diagram wdrożenia
- Aplikacja będzie wdrożona na jednym serwerze
- przyjmujemy roboczo, że będzie to Raspberry Pi
- Aplikacja jest uruchamiana w środowisku Docker
- Kontener
backend
- artefakty obejmują kod źródłowy aplikacji wykorzystującej framework FastAPI oraz implementację modeli optymalizacyjnych.
- realizuje funkcje podsystemu
Optimisation Backend
- Kontener
web-server
- serwer HTTP Nginx
- serwuje aplikację webową realizującą funkcje podsystemu
WebApp
- służy jako reverse proxy dla klientów komunikujących się z podsystemem
Optimisation Backend
- artefakty to kod zbudowanej aplikacji webowej oraz pliki konfiguracyjne serwera Nginx
- Kontenery będą połączone w jednym docker network
- Schemat komunikacji klient-serwer
- klient wysyła żądanie użycia modelu optymalizacyjnego z danymi wejściowymi (opis sieci, opis żądanego kanału)
- serwer odpowiada, że przyjął żądanie
- serwer uruchamia model optymalizacyjny (czas przetwarzania rzędu kilku minut)
- serwer odsyła klientowi wynik optymalizacji (parametry nowego kanału)
Ze względu na długi czas przetwarzania po stronie serwera, chcemy zastosować protokół WebSockets, który umożliwi dwustronną komunikację, w której serwer odeśle wynik, kiedy będzie gotowy. W ten sposób unikniemy cyklicznego odpytywania serwera przez klienta (polling).
Powyższy plan wymagałby zmiany, jeśli skorzystamy z licencji na program AMPL w środowisku OpenStack Zakładu Sztucznej Inteligencji Instytutu Informatyki (planujemy jednak, o ile to możliwe, wykorzystać rozwiązania Open Source).
\newpage
W naszym projekcie nie przewidujemy użycia bazy danych.
Model sieci teleinformatycznej (wraz ze wszystkimi zmianami) będzie przechowywany po stronie aplikacji przeglądarkowej
do momentu zamknięcia lub odświeżania strony. Po tym okresie konieczne będzie ponowne wgranie opisu.
Po stronie serwera nie są przechowywane stale żadne dane. Działa on jak funkcja, która otrzymuje model sieci
i parametry optymalizatora, oblicza optymalną trasę kanału, zwraca ją aplikacji przeglądarkowej,
a następnie usuwa te dane, wracając do stanu początkowego. Ewentualne zachowanie wyników optymalizacji w celu dalszej pracy
możliwe jest dzięki funkcjonalności eksportowania oraz importowania sieci w formacie json
.
Formaty plików wejściowych są opisane w punkcie \ref{requirements-analysis}.
\newpage
https://github.com/mGarbowski/pzsp2-projekt
- Języki programowania
- Python
- Typescript
- Biblioteki
- FastAPI
- Pyomo
- cbc
- React
- Reagraph
- Frameworki testowe
- pytest
- Jest
- Środowisko uruchomieniowe - Docker
- System kontroli wersji - Git
- System uruchamiania aplikacji, testów, narzędzi pomocniczych, zarządzania zależnościami
- npm (frontend)
- pdm (backend)
- Środowisko ciągłej integracji - GitHub Actions
- Narzędzia do komunikacji i zarządzania projektem
- Discord
- GitHub (Issues, Pull Requests)
- Diagram \ref{fig:backend-models} przedstawia klasy z modułu
models
- Klasy modelują strukturę sieci teleinformatycznej oraz format zapytań i odpowiedzi API optymalizatora
- W implementacji wykorzystujemy bibliotekę Pydantic do walidacji oraz serializacji JSON
- Diagram \ref{fig:backend-optimization} przedstawia klasy z modułu
optimisation
Optimizer
to abstrakcyjna klasa bazowa dla konkretnych modeli optymalizacyjnychDijkstraOptimizer
iIntegerProgrammingOptimizer
to konkretne implementacje modeli optymalizacyjnych- Dla lepszej czytelności kodu źródłowego stosujemy aliasy typów, co jest widoczne w sygnaturach metod
- Diagram \ref{fig:frontend-components} przedstawia klasy komponentów React z podziałem na katalogi, w których się znajdują
- Komponenty są zorganizowane w katalogach odpowiadających ich funkcjonalności
- Na diagramie nie zostały przedstawione komponenty pomocnicze, takie jak stylowane przyciski czy pola tekstowe
- Diagram \ref{fig:frontend-network} przedstawia klasy z modułu
network
- Moduł ten zawiera interfejsy modelujące sieć teleinformatyczną
- Model w aplikacji frontendowej jest analogiczny do modelu przedstawionego na diagramie \ref{fig:backend-models}
- Liczba plików z kodem źródłowym: 61
- Liczba linii kodu źródłowego: 3880
- Liczba testów jednostkowych: 52
\newpage
Użytkownik aplikacji - analityk sieci teleinformatycznej w dużej firmie telekomunikacyjnej
- Jako analityk sieci teleinformatycznej chcę wizualizować istniejący graf połączeń i ich zajętości w sieci, aby łatwo zrozumieć strukturę połączeń i zidentyfikować potencjalne problemy
- Jako analityk sieci teleinformatycznej chcę, aby optymalne ścieżki nowych kanałów były automatycznie wyznaczane, aby uniknąć ręcznej analizy i zapewnić efektywne wykorzystanie pasma
- Jako analityk sieci teleinformatycznej chcę łatwo wygenerować raporty o zajętości kanałów w istniejącej sieci, aby monitorować obciążenie sieci i zapobiegać ewentualnym przeciążeniom
- Jako analityk sieci teleinformatycznej, chcę mieć łatwy i intuicyjny dostęp do danych o obciążeniu dowolnego elementu w sieci, aby zidentyfikować słabe punkty i wąskie gardła systemu.
- Jako analityk sieci teleinformatycznej, chcę optymalnie wykorzystywać przepustowość sieci, aby zminimalizować koszty ponoszone przez moją firmę i zapewnić, że sieć będzie gotowa na dalsze rozszerzenia.
Makiety trzech proponowanych widoków w programie Figma dostępne są do pod (tym URL). Podglądy widoków widoczne są na rysunkach \ref{fig:figma-importer}, \ref{fig:figma-presentation} i \ref{fig:figma-optimizer}.
\newpage
- W projekcie stosujemy testy jednostkowe do weryfikacji poprawności implementacji pojedynczych modułów w izolacji
- Backend
- testy jednostkowe dla backendu są zaimplementowane w plikach
test_*.py
w katalogubackend/tests
- do testów wykorzystujemy bibliotekę
pytest
- uruchomienie wszystkich testów:
pdm test
w katalogubackend
- testy jednostkowe dla backendu są zaimplementowane w plikach
- Frontend
- testy jednostkowe dla frontendu są zaimplementowane w plikach
*.test.ts
, obok plików*.ts
które podlegają testowaniu - do testów wykorzystujemy bibliotekę
Jest
- uruchomienie wszystkich testów:
npm test
w katalogufrontend
- testy jednostkowe dla frontendu są zaimplementowane w plikach
- W projekcie stosujemy testy manualne do weryfikacji poprawności interakcji użytkownika z aplikacją
- Pliki z opisem sieci
- przygotowanie plików .csv z opisem sieci teleinformatycznej (wezly.csv, zajetosc.csv, spectrum_kanaly.csv)
- pliki zostały dostarczone przez właściciela projektu, nie mogą znajdować się w publicznym repozytorium
- aplikacja umożliwia też pominięcie krok importu plików, wtedy użytkownik może wchodzić interakcję z demonstracyjną siecią
- Uruchomienie aplikacji
- lokalne uruchomienie aplikacji:
docker compose -f docker-compose.local.yml up --build
w katalogu głównym projektu - otwarcie przeglądarki i wejście na stronę
http://localhost:2137
- lub interakcja z wdrożoną aplikacją na serwerze http://pzsp2.mgarbowski.pl
- lokalne uruchomienie aplikacji:
- Użytkownik otwiera stronę importera danych (strona startowa)
- Użytkownik wybiera plik
wezly.csv
z opisem węzłów sieci - Użytkownik wybiera plik
zajetosc.csv
z opisem krawędzi sieci - Użytkownik wybiera plik
spectrum_kanaly.csv
z opisem kanałów sieci - Po wybraniu wszystkich plików pojawia się komunikat o pomyślnym zaimportowaniu sieci
- Po prawej stronie wyświetla się wizualizacja sieci
- Użytkownik otwiera stronę importera danych (strona startowa)
- Użytkownik wybiera plik
wezly.csv
z opisem węzłów sieci - Użytkownik wybiera plik
zajetosc.csv
z opisem krawędzi sieci - Użytkownik wybiera plik
spectrum_kanaly.csv
z opisem kanałów sieci - Wczytuje się poprawny opis sieci.
- Użytkownik naciska przycisk "Pobierz" w sekcji "Pobierz lub załaduj stan sieci"
- Pobiera się plik w formacie json.
- Użytkownik odświeża stronę.
- Użytkownik naciska przycisk "Załaduj" w sekcji "Pobierz lub załaduj stan sieci"
- Użytkownik wybiera wcześniej pobrany plik w formacie json.
- Wczytuje się ten sam opis sieci.
- Użytkownik otwiera stronę prezentacji sieci
- Użytkownik importuje opis sieci.
- Użytkownik przechodzi do zakładki "Statystyki"
- Użytkownik naciska przycisk "Pobierz raport"
- Przeglądarka pobiera plik .csv z raportem
- Użytkownik otwiera stronę prezentacji sieci
- Użytkownik importuje opis sieci.
- Użytkownik przechodzi do zakładki "Statystyki"
- Na karcie "Sieć" widoczne są globalne statystyki sieci
- Na karcie "Kanały" widoczna jest lista identyfikatorów kanałów
- Użytkownik klika na dowolny węzeł na prezentacji sieci
- Wybrany węzeł wyświetla się w kolorze niebieskim na prezentacji sieci
- Po lewej stronie widoczna jest karta "Wybrany węzeł" ze statystykami węzła
- Użytkownik klika na identyfikator dowolnego sąsiada na karcie "Wybrany węzeł"
- Wybrany sąsiad wyświetla się w kolorze niebieskim na prezentacji sieci
- Na karcie "Wybrany węzeł" wyświetlają się statystyki wybranego sąsiada
- Użytkownik klika na dowolną krawędź na prezentacji sieci
- Wybrana krawędź wyświetla się w kolorze niebieskim na prezentacji sieci
- Po lewej stronie wyświetla się karta "Wybrana krawędź" ze statystykami krawędzi
- Użytkownik klika na identyfikator węzła z listy "Łączy węzły" na karcie krawędzi
- Wybrany węzeł wyświetla się w kolorze niebieskim na prezentacji sieci
- Użytkownik klika na dowolny identyfikator na karcie "Kanały"
- Węzły i krawędzie wybranego kanału wyświetlają się w kolorze fioletowym na prezentacji sieci (lub zostały zaznaczone wcześniej i są zielone)
- Po lewej stronie wyświetla się karta "Wybrany kanał" ze statystykami kanału
- Użytkownik klika na identyfikator węzła z listy "Węzły" na karcie wybranego kanału
- Wybrany węzeł wyświetla się w kolorze niebieskim na prezentacji sieci
- Karta "Wybrany węzeł" wyświetla statystyki wybranego węzła
- Użytkownik klika na identyfikator krawędzi na liście "Krawędzie" na karcie wybranego kanału
- Wybrana krawędź wyświetla się w kolorze niebieskim na prezentacji sieci
- Karta "Wybrana krawędź" wyświetla statystyki wybranej krawędzi
- Użytkownik otwiera stronę prezentacji sieci
- Użytkownik importuje opis sieci.
- Użytkownik przechodzi do zakładki "Dodaj kanał"
- Użytkownik odczytuje z prezentacji identyfikator węzła i wpisuje go w pole "Węzeł startowy"
- Użytkownik odczytuje z prezentacji identyfikator innego węzła i wpisuje go w pole "Węzeł końcowy"
- Użytkownik wybiera jedną z opcji w polu "Przepustowość"
- Użytkownik wybiera "Model całkowitoliczbowy" w polu "Optymalizator"
- Użytkownik wpisuje dodatnie liczby w pola "Waga długości krawędzi" i "Waga obciążenia krawędzi"
- Użytkownik naciska przycisk "Dodaj kanał"
- Pojawia się indykator ładowania do czasu otrzymania wyniku
- Po pewnym czasie, na prezentacji sieci pojawia się wyróżniona kolorem fioletowym ścieżka między zadanymi węzłami
- Pod formularzem pojawia się komunikat z czasem obliczeń
- Użytkownik przechodzi do zakładki "Statystyki"
- Na karcie "Wybrany kanał" widoczne są statystyki i atrybuty nowego kanału
- Użytkownik otwiera stronę prezentacji sieci
- Użytkownik importuje opis sieci.
- Użytkownik przechodzi do zakładki "Dodaj kanał"
- Użytkownik odczytuje z prezentacji identyfikator węzła i wpisuje go w pole "Węzeł startowy"
- Użytkownik odczytuje z prezentacji identyfikator innego węzła i wpisuje go w pole "Węzeł końcowy"
- Użytkownik wybiera jedną z opcji w polu "Przepustowość"
- Użytkownik wybiera "Algorytm Dijkstry" w polu "Optymalizator"
- Użytkownik wpisuje dodatnie liczby w pola "Waga długości krawędzi" i "Waga obciążenia krawędzi"
- Użytkownik naciska przycisk "Dodaj kanał"
- Pojawia się indykator ładowania do czasu otrzymania wyniku
- Po pewnym czasie, na prezentacji sieci pojawia się wyróżniona kolorem fioletowym ścieżka między zadanymi węzłami
- Pod formularzem pojawia się komunikat z czasem obliczeń
- Użytkownik przechodzi do zakładki "Statystyki"
- Na karcie "Wybrany kanał" widoczne są statystyki i atrybuty nowego kanału
\newpage
- Jako miarę jakości testów jednostkowych przyjmujemy pokrycie linii kodu testami
- Do mierzenia pokrycia wykorzystujemy narzędzia dostarczone przez biblioteki testowe
- Komendy do zmierzenia pokrycia testami:
pdm cov
w katalogubackend
npm run coverage
w katalogufrontend
- Powyższe komendy wypisują w konsoli statystyki pokrycia całościowe oraz z podziałem na pliki
- Poziom pokrycia kodu biznesowego wynosi w obu projektach ponad 95%
Name Stmts Miss Branch BrPart Cover Missing
------------------------------------------------------------------------------------------------
src/pzsp_backend/__init__.py 0 0 0 0 100%
src/pzsp_backend/app.py 54 7 6 2 85% 52, 59->61, 74-75, 89-95
src/pzsp_backend/models.py 52 0 6 0 100%
src/pzsp_backend/optimization/__init__.py 0 0 0 0 100%
src/pzsp_backend/optimization/base.py 40 0 0 0 100%
src/pzsp_backend/optimization/constants.py 11 0 0 0 100%
src/pzsp_backend/optimization/dijkstra.py 72 0 22 1 99% 46->63
src/pzsp_backend/optimization/integer/__init__.py 0 0 0 0 100%
src/pzsp_backend/optimization/integer/abstract.py 50 0 6 0 100%
src/pzsp_backend/optimization/integer/optimizer.py 78 4 26 2 94% 93-94, 98-101
------------------------------------------------------------------------------------------------
TOTAL 357 11 66 5 96%
----------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------------------|---------|----------|---------|---------|-------------------
All files | 98.13 | 91.3 | 95.91 | 97.75 |
DataImporter | 98.08 | 90.24 | 97.56 | 97.67 |
buildNetwork.ts | 97.95 | 87.5 | 100 | 97.14 | 46
createChannels.ts | 97.05 | 78.57 | 91.66 | 96.49 | 158,174
parseCsv.ts | 100 | 100 | 100 | 100 |
NetworkModel | 100 | 100 | 100 | 100 |
calcNodeDistance.ts | 100 | 100 | 100 | 100 |
ReportGeneration | 97.67 | 100 | 83.33 | 97.29 |
generateReport.ts | 97.67 | 100 | 83.33 | 97.29 | 6
----------------------|---------|----------|---------|---------|-------------------
\newpage
- W projekcie stosujemy konteneryzację, wykorzystujemy środowisko Docker
- Schemat wdrożenia aplikacji jest przedstawiony na rysunku \ref{fig:physical-view}
- Aplikacja składa się z dwóch kontenerów
web-server
backend
- Kontenery są uruchamiane w jednej sieci
app-network
(Docker network) - Przygotowane są oddzielne pliki konfiguracyjne dla środowisk lokalnego i produkcyjnego
docker-compose.local.yml
docker-compose.prod.yml
web-server
- Serwer HTTP i reverse proxy
- Wykorzystuje obraz
nginx
oraznode:18
(przy wieloetapowym budowaniu) - Serwuje aplikację frontendową
- Przekierowuje zapytania do aplikacji backendowej (reverse proxy)
- Oddzielne Dockerfile i plik konfiguracyjny Nginx dla uruchomienia lokalnego i produkcyjnego
backend
- Aplikacja backendowa, API optymalizatora
- Wykorzystuje obraz
python:3.12-slim
oparty na systemie Debian - Instaluje solwer
cbc
oraz uruchamia aplikację FastAPI
- Zależności są zapisane w plikach
package.json
ipdm.lock
- Narzędzie
npm
umożliwia sprawdzenie zależności pod kątem luk bezpieczeństwa - GitHub Dependabot monitoruje zależności pod kątem znanych podatności
- Aplikacje nie przechowuje żadnych danych w sposób trwały
- Aplikacja nie przechowuje danych użytkowników, nie wymaga logowania
- Dane przesyłane do serwera nie mają charakteru poufnego
- Logowanie do serwera wymaga uwierzytelnienia kluczem (SSH)
\newpage
Aplikację można uruchomić lokalnie, korzystając ze środowiska Docker. Aplikacja jest również wdrożona w chmurze i dostępna pod adresem http://pzsp2.mgrabowski.pl.
- Zainstaluj Docker i Docker Compose
- Sklonuj repozytorium:
git clone [email protected]:mGarbowski/pzsp2-projekt.git
- Przejdź do katalogu projektu:
cd pzsp2-projekt
- Uruchom aplikację:
docker compose -f docker-compose.local.yml up --build
- Interfejs użytkownika będzie dostępny w przeglądarce pod adresem http://localhost:2137
- Importer danych
- wczytanie opisu sieci z zestawu plików .csv
- załadowanie demonstracyjnej sieci
- eksport stanu sieci do pliku .json
- import stanu sieci z pliku .json
- Wizualizacja grafu sieci teleinformatycznej
- Prezentacja statystyk i atrybutów sieci i jej elementów
- Generowanie raportu zajętości pasma przez kanały w formacie .csv
- Wyznaczanie nowego kanału z użyciem modelu optymalizacyjnego
- Otwórz stronę startową aplikacji (widoczna na zrzucie ekranu \ref{fig-importer-screenshot})
- Podstawowym krokiem jest załadowanie plików .csv z opisem sieci
- przygotuj pliki "wezly.csv", "zajetosc.csv" i "spectrum_kanaly.csv"
- na panelu "Zaimportuj dane sieci" wybierz przygotowane pliki w odpowiednich polach
- po załadowaniu wszystkich plików pojawi się komunikat o sukcesie
- Możesz również pominąć krok importu plików i korzystać z demonstracyjnej sieci
- aby ją załadować, naciśnij przycisk "Wczytaj demo" na panelu "Zaimportuj dane demonstracyjne"
- Stan załadowanej sieci, np. po wyznaczeniu nowych kanałów z użyciem modeli optymalizacyjnych, można zapisać do pliku JSON
- naciśnij przycisk "Pobierz" na panelu "Pobierz lub załaduj stan sieci"
- ten sam plik można następnie załadować, np. po zakończeniu sesji, naciskając przycisk "Załaduj"
- Po załadowaniu sieci w dowolny z wymienionych sposobów, po prawej stronie pojawi się wizualizacja grafu sieci
- Możesz powrócić do tej strony, naciskając "Import" na pasku nawigacyjnym
- Pamiętaj, że system nie przechowuje danych po zamknięciu przeglądarki
{#fig-presentation-screenshot}
- Po załadowaniu sieci w zakładce "Import" przejdź do zakładki "Statystyki" (widoczna na zrzucie ekranu \ref{fig-presentation-screenshot})
- Wizualizację grafu sieci po prawej stronie możesz przesuwać przytrzymując lewy przycisk myszy
- Wizualizację można przybliżać i oddalać za pomocą kółka myszy
- Po najechaniu na węzeł lub krawędź kliknij lewym przyciskiem myszy
- wybrany element zostanie wyróżniony kolorem na wizualizacji
- po lewej stronie pojawi się karta z jego atrybutami i statystykami
- Użyj kółka myszy, aby przewinąć karty statystyk, jeśli nie wszystkie mieszczą się na ekranie
- Na kartach po lewej stronie pojawiają się identyfikatory kanałów, węzłów i krawędzi
- kliknij identyfikator, aby zobaczyć atrybuty wybranego elementu oraz wyróżnić go na wizualizacji
- Po załadowaniu sieci w zakładce "Import" przejdź do zakładki "Statystyki"
- Aby pobrać raport, naciśnij przycisk "Pobierz raport" na dole strony
- Zostanie pobrany plik w formacie .csv z raportem zajętości pasma przez kanały
- można go otworzyć i wygodnie przeglądać w arkuszu kalkulacyjnym z pakietu biurowego
- Po załadowaniu sieci w zakładce "Import" przejdź do zakładki "Dodaj kanał" (widoczna na zrzucie ekranu \ref{fig-optimizer-screenshot})
- W polach "Węzeł startowy" i "Węzeł końcowy" wpisz identyfikatory węzłów, między którymi ma być wyznaczony kanał
- możesz je odczytać z wizualizacji sieci
- jeśli sieć jest zbyt duża i identyfikatory nie są widoczne, przybliż wizualizację kółkiem myszy
- Wybierz jedną z opcji w polu "Przepustowość"
- określa ona, jaką przepustowość ma mieć nowy kanał
- Wybierz jeden z modeli optymalizacyjnych w polu "Optymalizator"
- Model całkowitoliczbowy
- znajdzie optymalny przebieg kanału, o ile można go wytyczyć przy zadanych parametrach i stanie sieci
- wyznaczanie kanału może zająć kilka minut
- Algorytm Dijkstry
- znajduje optymalną ścieżkę znacznie szybciej
- nie gwarantuje sukcesu we wszystkich przypadkach, które obsłuży model całkowitoliczbowy
- Wprowadź wagi długości i obciążenia krawędzi
- określają one, jak ważne będą względem siebie te parametry przy wyznaczaniu kanału
- Po wypełnieniu wszystkich opcji naciśnij przycisk "Dodaj kanał" i poczekaj na wynik
- Po pewnym czasie zobaczysz komunikat o wyniku i czasie obliczeń
- Znaleziony kanał zostanie wyróżniony na wizualizacji sieci kolorem fioletowym
- Możesz obejrzeć szczegółowe parametry nowego kanału w zakładce "Statystyki"
- Nowy kanał zostanie również ujęty w raporcie zajętości pasma, który możesz pobrać w zakładce "Statystyki"
\newpage
Aplikacja jest w pełni skonteneryzowana.
Obsługuje dwa tryby uruchomienia:
- lokalny, w celu testowania i wytwarzania
- produkcyjny, w którym wszystkie kontenery uruchamiane są na jednej maszynie, dostępna przez HTTP
Do uruchomienia lokalnego potrzebne jest jedynie narzędzie Docker. Wdrożenie produkcyjne przystosowane jest do usługi Microsoft Azure.
Pliki używane do uruchomienia:
- Lokalnie:
- frontend/Dockerfile.dev
- backend/Dockerfile
- docker-compose.local.yml
- nginx.local.conf
- .env.development
- Produkcyjnie:
- frontend/Dockerfile.prod
- backend/Dockerfile
- docker-compose.prod.yml
- nginx.prod.conf
- .env.production
Do stworzenia infrastruktury chmurowej wykorzystywane jest narzędzie Terraform. Przygotowany skrypt używa usługi Microsoft Azure. Aplikacja nie jest uzależniona od tego wyboru. Możliwe jest stworzenie własnej architektury fizycznej lub chmurowej we własnym zakresie.
- Wymagane jest posiadanie konta i subskrypcji Microsoft Azure, na której dostępne są co najmniej:
- Jeden adres publiczny ip
- Jedna maszyna wirtualna
- 4 rdzenie procesorów wirtualnych
- Należy mieć zainstalowane narzędzie AZ (Azure CLI), zalogować się na swoje konto Azure i wybrać subskrypcję, z której korzystać ma aplikacja
- Należy zainstalować narzędzie Terraform
- W pliku terraform.tfvars ustawić zmienną "public_ssh_key_file" na ścieżkę do pliku zawierającego klucz publiczny, który będzie potrzebny do pierwszego zalogowania się na maszynę wirtualną (domyślnie: "~/.ssh/id_rsa.pub")
- (opcjonalnie) w pliku main.tf zmienić nazwy i lokalizacje zasobów alokowanych na platformie Azure wedle potrzeb
- W katalogu cloud/terraform wykonać polecenia:
terraform init
terraform apply
Do wdrożenia aplikacja na istniejącej infrastrukturze używane jest narzędzie Ansible.
-
Upewnić się, że maszyna wirtualna z adresem publicznym jest uruchomiona
-
W pliku inventory.ini zmienić adres na adres publiczny maszyny wirtualnej
-
W pliku frontend/ngnix.prod.conf i frontend/.env.production zmienić ".*pzsp2.mgarbowski.pl" na adres używany przez maszynę wirtualną
-
W pliku full-deployment.yaml, w zadaniu "Create users and add SSH keys", dopasować listę użytkowników, których chcemy dodać na maszynie
-
Pliki z kluczami publicznymi użytkowników umieścić w katalogu "/cloud/ansible/public_keys/".
- Nazwa pliku musi odpowiadać nazwie użytkownika zdefiniowanej w poprzednim kroku.
-
Po pierwszym uruchomieniu maszyny administrator operujący kluczem ssh zdefiniowanym przy tworzeniu architektury musi wykonać na swojej maszynie
$user@computer: ~/projekt/cloud/ansible$ ansible-playbook -i inventory.ini \
./full-deployment.yaml --user azureuser
W przypadku wykorzystania innego rozwiązania niż Azure należy zastąpić "azureuser" nazwą użytkownika z dostępem do uprawnień root
- Po każdym kolejnym uruchomieniu zapisani użytkownicy mogą wdrożyć aplikację na nowo poleceniem
$user@computer: ~/projekt/cloud/ansible$ ansible-playbook -i inventory.ini \
./full-deployment.yaml --user {nazwa uzytkownika}
Aplikacja powinna być teraz dostępna pod adresem http://{adres publiczny maszyny}
Jeśli nie pożądane jest, aby wdrażana była najnowsza dostępna wersja aplikacji (https://github.com/mGarbowski/pzsp2-projekt.git), należy zastąpić adres repozytorium w pliku full-deployment, w zadaniu "Clone the project repository" na własne publiczne repozytorium zawierające pożądaną wersję.
\newpage
W projekcie zrealizowane zostały wszystkie wymagania właściciela tematu, które ulegały modyfikacjom i uszczegółowieniom w miarę postępu prac. Aplikacja realizuje wszystkie funkcje zdefiniowane w specyfikacji funkcjonalnej, a także spełnia wymagania jakościowe.
- Zespół projektowy, przy wytwarzaniu oprogramowania, stosował GitHub Flow
- wprowadzanie zmian w kodzie odbywało się za pomocą Pull Requests
- każda zmiana była recenzowana przez jednego lub więcej członków zespołu
- dyskusja i krytyczna analiza pozwalała na uniknięcie błędów i zapewnienie jakości kodu
- Do logiki biznesowej aplikacji powstały testy jednostkowe
- pokrycie kodu biznesowego testami jest na poziomie powyżej 95%
- testy są uruchamiane automatycznie w potoku CI
- Aplikacja została poddana testom manualnym
- przygotowano scenariusze testów
- przetestowano wszystkie funkcje aplikacji
- zidentyfikowano i usunięto błędy
- Zespół wykorzystuje narzędzia do automatycznego formatowania kodu
- krok potoku CI zapewnia, że kod jest zgodny z ustalonymi standardami
- Aplikacja powstawała zgodnie z najlepszymi praktykami programowania
- Aplikacja wykorzystuje współczesne technologie klasy Open Source
- Aplikacja jest skonteneryzowana, co znacznie ułatwia rozwój i wdrożenie
- Rozwój aplikacji o dodatkowe funkcje
- struktura aplikacja pozwala na łatwe rozszerzenie jej o inne modele optymalizacyjne
- API optymalizatora może być wykorzystane w innych aplikacjach
- możliwe jest stworzenie alternatywnej aplikacji klienckiej, która korzystałaby z API optymalizatora
- API pozwala na zintegrowanie optymalizatora z innymi systemami
- Taccari, Leonardo. "Integer programming formulations for the elementary shortest path problem." European Journal of Operational Research (2016). http://dx.doi.org/10.1016/j.ejor.2016.01.003