WIP
574
main.tex
@ -822,45 +822,253 @@ oprogramowania na maszynie zarządzanej, wystarczy jedynie uruchomiony serwer SS
|
||||
|
||||
|
||||
% TODO
|
||||
\chapter{Wymagania i narzędzia (WORK IN PROGRESS)}
|
||||
\chapter{Wymagania i narzędzia}
|
||||
\label{ch:wymagania-i-narzedzia}
|
||||
|
||||
\paragraph{}
|
||||
Do implementacji pierwszej części projektu wyszczególnionej powyżej wykorzystano język Python, do zaimplementowania prostego serwera oraz klienta, synchronizujących
|
||||
obrazy maszyn wirtualnych, QEMU wraz z KVM do uruchamiania samych maszyn oraz system operacyjny nadzorcy Ubuntu Linux w wersji 22.04 LTS.
|
||||
\paragraph{Wymagania funkcjonalne}
|
||||
Rozwiązanie powinno spełniać następujące wymagania funkcjonalne:
|
||||
|
||||
\paragraph{}
|
||||
Część projektu odpowiedzialna za obsługę systemów zarządców maszyn wirtualnych została także oparta o system operacyjny Ubuntu Linux w wersji 22.04 LTS,
|
||||
serwer TFTP oraz PXE do serwowania medium instalacyjnego systemu bazowego nadzorców, cloud-init oraz Ansible do automatyzacji instalacji i konfiguracji hostów.
|
||||
|
||||
\paragraph{QEMU}
|
||||
QEMU to zintegrowany system do emulacji procesorów poprzez tłumaczenie binarne, potrafi także korzystać z technologii KVM do uruchamiania
|
||||
aplikacji/maszyn wirtualnych z minimalnym narzutem wydajnościowym. \cite{bib:qemu-main}
|
||||
\begin{itemize}
|
||||
\item wymagania funkcjonalne i niefunkcjonalne
|
||||
\item przypadki użycia (diagramy UML) -- dla prac, w których mają zastosowanie
|
||||
\item opis narzędzi, metod eksperymentalnych, metod modelowania itp.
|
||||
\item metodyka pracy nad projektowaniem i implementacją -- dla prac, w których ma to zastosowanie
|
||||
\item pełna automatyzacja procesu instalowania i konfiguracji systemu operacyjnego na urządzeniach
|
||||
\item użycie maszyn wirtualnych
|
||||
\item pozorna ,,bezstanowość'': po zakończeniu pracy w maszynie wirtualnej i jej wyłączeniu, kolejne jej uruchomienie przywróci pierwotny obraz dysku maszyny, bez zmian wprowadzonych przez poprzedniego użytkownika
|
||||
\item proste tworzenie obrazów maszyn wirtualnych o zmodyfikowanej konfiguracji
|
||||
\item łatwość użycia: użytkownicy końcowi powinni być w stanie w łatwy sposób obsługiwać maszyny klienckie
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{Wymagania niefunkcjonalne}
|
||||
Rozwiązanie powinno spełniać następujące wymagania niefunkcjonalne:
|
||||
|
||||
\begin{itemize}
|
||||
\item modularność: możliwość łatwego dodania nowych funkcjonalności
|
||||
\item użycie rozwiązań, które są Wolnym Oprogramowaniem
|
||||
\item możliwość wbudowania rozwiązania w już istniejącą architekturę sieciową
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Aby osiągnąć pełną automatyzację procesu instalacji i konfiguracji systemu operacyjnego na urządzeniach wykorzystano
|
||||
serwer PXE, stworzony z serwera TFTP (tftp-hpa), serwera DHCP (dhcp-isc-server) oraz serwera HTTP (apache2), a także narzędzie
|
||||
cloud-init do automatycznego przeprowadzenia procesu instalacji systemu operacyjnego nadzorcy oraz narzędzie Ansible, do pełnej
|
||||
konfiguracji systemu operacyjnego zarządcy.
|
||||
|
||||
\paragraph{}
|
||||
Całość rozwiązania instalacyjno-konfiguracyjnego zaimplementowano pod kontrolą systemu operacyjnego Ubuntu Linux w
|
||||
wersji 22.04 LTS na urządzeniu Dell Wyse 5060. Jest to tak zwany ,,cienki klient'', czyli zminiaturyzowana wersja komputera
|
||||
osobistego o ograniczonej mocy obliczeniowej, której celem było uruchamianie klienta zdalnego pulpitu i umożliwienie w ten sposób
|
||||
pracy na dużo wydajniejszej maszynie. Maszyny te są obecnie często wykorzystywane przez pasjonatów jako energooszczędne
|
||||
alternatywy dla komputerów jednopłytkowych (takich jak Raspberry Pi) i służą jako prywatne serwery domowe. Wykorzystany
|
||||
terminal posiada czterordzeniowy procesor AMD GX-424CC, 8 GB pamięci RAM, dysk SATA SSD 256GB oraz gigabitową kartę sieciową
|
||||
opartą o chip Realtek RTL8111/8168/8411.
|
||||
|
||||
\paragraph{}
|
||||
Do obsługi wirtualizacji wykorzystano narzędzie QEMU. Jest to zintegrowany system do emulacji procesorów poprzez tłumaczenie binarne, potrafi także korzystać z technologii KVM do uruchamiania
|
||||
aplikacji/maszyn wirtualnych z minimalnym narzutem wydajnościowym.\cite{bib:qemu-main} W proponowanym
|
||||
rozwiązaniu użyto trybu, gdzie QEMU korzysta z KVM, aby zapewnić jak najlepszą wydajność.
|
||||
|
||||
|
||||
% \begin{itemize}
|
||||
% \item wymagania funkcjonalne i niefunkcjonalne
|
||||
% \item przypadki użycia (diagramy UML) -- dla prac, w których mają zastosowanie
|
||||
% \item opis narzędzi, metod eksperymentalnych, metod modelowania itp.
|
||||
% \item metodyka pracy nad projektowaniem i implementacją -- dla prac, w których ma to zastosowanie
|
||||
% \end{itemize}
|
||||
|
||||
|
||||
% TODO
|
||||
\chapter{[Właściwy dla kierunku -- np. Specyfikacja zewnętrzna]}
|
||||
\label{ch:04}
|
||||
\chapter{Specyfikacja zewnętrzna}
|
||||
\label{ch:specyfikacja-zewnetrzna}
|
||||
|
||||
\paragraph{Wymagania sprzętowe - strona kliencka}
|
||||
Maszyny klienckie, na których uruchomiona ma być aplikacja kliencka i maszyny wirtualne, powinny spełniać następujące wymagania:
|
||||
|
||||
Jeśli „Specyfikacja zewnętrzna”:
|
||||
\begin{itemize}
|
||||
\item wymagania sprzętowe i programowe
|
||||
\item sposób instalacji
|
||||
\item sposób aktywacji
|
||||
\item kategorie użytkowników
|
||||
\item sposób obsługi
|
||||
\item administracja systemem
|
||||
\item kwestie bezpieczeństwa
|
||||
\item przykład działania
|
||||
\item scenariusze korzystania z systemu (ilustrowane zrzutami z ekranu lub generowanymi dokumentami)
|
||||
\item procesor 64-bit, wspierający Intel VT-d, lub AMD-V
|
||||
\item program uruchomieniowy UEFI
|
||||
\item co najmniej 4GB pamięci RAM, preferowane 8GB
|
||||
\item dysk o pojemności co najmniej 250GB
|
||||
\item płyta główna wspierająca Wake On LAN oraz uruchamianie poprzez PXE
|
||||
\item karta graficzna o wydajności zbliżonej do Intel HD Graphics 620, na przykład APU z serii AMD Ryzen, Nvidia GT 1030, lub nawet Nvidia GT 730
|
||||
\item karta sieciowa wspierająca Wake On LAN i prędkości 1 gigabit
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{Wymagania sprzętowe - strona sieciowa}
|
||||
Sieć, w której ma operować projekt, powinna spełniać poniższe warunki:
|
||||
|
||||
\begin{itemize}
|
||||
\item warstwa łącza zbudowana w oparciu o sieć Ethernet w klasie co najmniej 5E (osiągającą prędkości 1 gigabita)
|
||||
\item urządzenia sieciowe pozwalające na transmisję ,,magic packet''
|
||||
\item preferencyjnie dedykowana podsieć, wyłącznie dla zarządzanych maszyn klienckich
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{Wymagania sprzętowe - strona serwera}
|
||||
Serwer, na którym uruchomione będą aplikacje serwerów, powinien spełniać następujące wymagania:
|
||||
|
||||
\begin{itemize}
|
||||
\item co najmniej gigabitowa karta sieciowa
|
||||
\item procesor czterordzeniowy
|
||||
\item 8GB pamięci RAM, 8GB pamięci SWAP
|
||||
\item dysk o pojemności co najmniej 250GB
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{Sposób instalacji}
|
||||
Procedura instalacji serwera zarządcy obrazów i maszyn jest następująca:
|
||||
|
||||
\begin{itemize}
|
||||
\item system operacyjny, na którym uruchamiany jest serwer powinien posiadać zainstalowane następujące pakiety:
|
||||
\begin{itemize}
|
||||
\item serwer HTTP Apache2 (apache2 dla Ubuntu)
|
||||
\item implementację ISC serwera DHCP (dhcp-isc-server dla Ubuntu)
|
||||
\item serwer TFTP (tftp-hpa dla Ubuntu)
|
||||
\item interpreter Python w wersji co najmniej 3.9
|
||||
\end{itemize}
|
||||
\item po instalacji wymaganych pakietów należy utworzyć wymagane katalogi:
|
||||
\begin{itemize}
|
||||
\item \texttt{/ks} - katalog zawierający pliki konfiguracyjne dla narzędzia cloud-init
|
||||
\item \texttt{/images} - katalog zawierający obraz systemu operacyjnego zarządcy dla maszyn klienckich (Ubuntu Server 22.04 LTS)
|
||||
\item \texttt{/srv/tftp} - katalog zawierający pliki do uruchomienia instalatora poprzez PXE
|
||||
\end{itemize}
|
||||
\item skopiować pliki konfiguracyjne z repozytorium poniżej do odpowiednich katalogów
|
||||
|
||||
\texttt{https://git.nixenos.ovh/engineering-degree/configuration-files.git}
|
||||
\item przygotować listę adresów MAC zarządzanych urządzeń
|
||||
\item skonfigurować serwer DHCP tak, aby przypisywał stałe adresy IP urządzeniom klienckim, spisać te adresy
|
||||
\item do katalogu należy pobrać kod źródłowy aplikacji serwera:
|
||||
|
||||
\texttt{git clone https://git.nixenos.ovh/engineering-degree/orchestrator-app.git}
|
||||
\item następnie należy przejść do katalogu zawirającego aplikację \texttt{cd orchestrator-app}
|
||||
\item utworzyć środowisko wirtualne Python i uruchomić je:
|
||||
\begin{itemize}
|
||||
\item \texttt{python3 -m venv .env}
|
||||
\item \texttt{source .env/bin/activate}
|
||||
\end{itemize}
|
||||
\item skonfigurować opcje serwera w pliku konfiguracyjnym \texttt{config.yml}
|
||||
\item zresetować serwer dhcp, tftp oraz http
|
||||
\item uruchomić serwer obrazów komendą \texttt{python fleetcontrol run}
|
||||
\item pobrać zestaw skryptów Ansible
|
||||
|
||||
\texttt{git clone https://git.nixenos.ovh/engineering-degree/ansible-scripts.git}
|
||||
\item uzupełnić plik inventory/nodes.yml adresami IP przypisanymi do urządzeń klienckich w konfiguracji serwera DHCP
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Proces instalacji i konfiguracji klientów jest następujący:
|
||||
|
||||
\begin{itemize}
|
||||
\item uruchomić wspracie dla PXE oraz Wake On LAN w oprogramowaniu BIOS
|
||||
\item ustawić PXE jako pierwsze urządzenie uruchomieniowe, jako drugie ustawić lokalny dysk twardy
|
||||
\item wysłać do każdego urządzenia ,,magic packet'':
|
||||
|
||||
\texttt{wakeonlan -i adres-broadcast-sieci adres-mac-urządzenia}
|
||||
\item uruchomić instalator klikając enter w oknie wyboru przedstawionym na rys. \ref{fig:boot-screen-pxe}
|
||||
\item po restarcie wszystkich urządzeń, podmienić adres IP serwera w pliku config.yml i uruchomić skrypty ansible z katalogu \texttt{ansible-scripts} na serwerze:
|
||||
|
||||
\texttt{ansible-playbook provision-new-node.yml -i inventory/nodes.yml -K}
|
||||
\end{itemize}
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{./pictures/boot-screen-pxe.png}
|
||||
\caption{Ekran wyboru systemu do zainstalowania}
|
||||
\label{fig:boot-screen-pxe}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{Obsługa - strona serwera}
|
||||
Po wykonaniu wstępnej konfiguracji, należy zbudować obraz maszyny wirtualnej i zarejestrować go w systemie ich obsługi.
|
||||
Aby zbudować obraz maszyny wirtualnej, wystarczy stworzyć obraz dysku w formacie qcow2 (np. \texttt{qemu-img create -f qcow2 ubuntu.qcow2 20G}),
|
||||
a następnie uruchomić maszynę wirtualną z tym obrazem dysku i medium instalacyjnym, zainstalować oraz skonfigurować system operacyjny,
|
||||
a następnie skopiować utworzony obraz dysku na serwer.
|
||||
|
||||
Będąc zalogowanym do powłoki na serwerze, należy umieścić obraz dysku w miejscu, gdzie użytkownik uruchamiający serwer ma dostęp do odczytu i zapisu plików.
|
||||
Następnie, należy zarejestrować obraz w bazie danych serwera komendą \texttt{python fleetcontrol add\_image}, przykład użycia
|
||||
przedstawiono na rys. \ref{fig:register-image-command}. Po dodaniu obrazu można zweryfikować, że obraz został prawidłowo zarejestrowany
|
||||
poprzez komendę \texttt{python fleetcontrol print\_images}. Dla skonfigurowanego serwera dała ona rezultat przedstawiony na rys. \ref{fig:print-images-command}.
|
||||
|
||||
Po pierwszym uruchomieniu wszystkie maszyny klienckie powinny same się zarejestrować na serwerze, co można sprawdzić komendą
|
||||
\texttt{python fleetcontrol print\_clients}. Przykładowy rezultat takiej komendy predstawiono na rys. \ref{fig:print-clients-command}.
|
||||
|
||||
Po pomyślnej weryfikacji, można przypisać obrazy do klientów. Odbywa sie to poprzez komendę
|
||||
\texttt{python fleetcontrol assign\_image} zaprezentowaną na rys. \ref{fig:assign-image-command}.
|
||||
|
||||
Konfiguracja serwera odbywa się poprzez edycję pliku \texttt{config.yml}, lub poprzez ustawienie następujących zmiennych środowiskowych
|
||||
przed uruchomieniem serwera:
|
||||
|
||||
\begin{itemize}
|
||||
\item \texttt{VALHALLA\_SERVER\_NAME} - nazwa serwera
|
||||
\item \texttt{VALHALLA\_SERVER\_PORT} - port na którym ma nasłuchiwać serwer
|
||||
\item \texttt{VALHALLA\_SERVER\_HOST} - adres IP hosta, na którym działa serwer (adres karty sieciowej wpiętej do sieci, w której są maszyny klienckie)
|
||||
\item \texttt{VALHALLA\_SERVER\_PASSWORD} - hasło dostępu do serwera dla klientów
|
||||
\item \texttt{VALHALLA\_SERVER\_ACCESS\_USERNAME} - nazwa użytkownika dostępowego dla klientów
|
||||
\item \texttt{VALHALLA\_JWT\_SECRET} - sekretna fraza wykorzystywana do obliczenia tokenu JWT
|
||||
\item \texttt{VALHALLA\_DATABASE\_FILE} - inny plik bazy danych SQLite3
|
||||
\item \texttt{VALHALLA\_LOGLEVEL} - poziom logowania dla aplikacji serwera
|
||||
\end{itemize}
|
||||
|
||||
Każde z tych ustawień można ustawić także poprzez plik config.yml, jednak to zmienne środowiskowe mają pierwszeństwo i są
|
||||
brane pod uwagę preferencyjnie. Po zmianie ustawień serwera należy pamiętać o aktualizacji ustawień klienta. Odbywa się to
|
||||
poprzez edycję pliku \texttt{config.yml} w katalogu \texttt{ansible\_scripts}.
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{./pictures/add_image_command.png}
|
||||
\caption{Przykład rejestrowania obrazu maszyny wirtualnej}
|
||||
\label{fig:register-image-command}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{./pictures/print_images_command.png}
|
||||
\caption{Przykładowy wynik komendy wyświetlającej wszystkie zarejestrowane obrazy}
|
||||
\label{fig:print-images-command}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{./pictures/print_clients_command.png}
|
||||
\caption{Przykładowy wynik komendy wyświetlającej wszystkich zarejestrowanych klientów}
|
||||
\label{fig:print-clients-command}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{./pictures/assign_image_command.png}
|
||||
\caption{Przykładowe wywołanie komendy przypisującej obraz do klienta}
|
||||
\label{fig:assign-image-command}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{Obsługa - strona klienta}
|
||||
Maszyna kliencka po uruchomieniu przedstawia ekran wyboru obrazu maszyny wirtualnej do uruchomienia, zaprezentowany na rys. \ref{fig:client-runner-screen}.
|
||||
Użytkownik wybiera interesujący go obraz korzystając ze strzałek, następnie klawiszem tabulatora wybiera opcję OK i naciska klawisz Enter.
|
||||
Wtedy cały ekran przejmowany jest przez maszynę wirtualną, która uruchamia się. Po skończonej pracy w maszynie wirtualnej i jej wyłączeniu,
|
||||
znów pojawia się ekran wyboru obrazu maszyny.
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{./pictures/screenshot-client-app-running.png}
|
||||
\caption{Ekran wyboru maszyny wirtualnej do uruchomienia}
|
||||
\label{fig:client-runner-screen}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{Bezpieczeństwo - zarządzanie obrazami}
|
||||
Każde zapytanie do serwera zarządcy obrazów musi być zautoryzowane. Odbywa sie to poprzez token JWT, który klient wysyła
|
||||
z każdym zapytaniem do serwera. Proces instalacji systemu bazowego i konfiguracji nie jest jednak chroniony,
|
||||
jeżeli w sieci znajdują się maszyny, które uruchomią się poprzez PXE, mogą zainstalować podstawową konfigurację systemu.
|
||||
Nie posiada ona jednak aplikacji klienckiej, ani żadnej konfiguracji, jedynie klucz publiczny SSH, wymagany do wykonania
|
||||
skryptów Ansible. Jednak o ile złośliwy aktor nie podszyje się pod adres IP dowolnej maszyny do skonfigurowania, nie zostana na takiej maszynie
|
||||
wykonane skrypty konfigurujące aplikację kliencką oraz nie zostaną przekazane pliki konfiguracyjne.
|
||||
|
||||
% Jeśli „Specyfikacja zewnętrzna”:
|
||||
% \begin{itemize}
|
||||
% \item wymagania sprzętowe i programowe
|
||||
% \item sposób instalacji
|
||||
% \item sposób aktywacji
|
||||
% \item kategorie użytkowników
|
||||
% \item sposób obsługi
|
||||
% \item administracja systemem
|
||||
% \item kwestie bezpieczeństwa
|
||||
% \item przykład działania
|
||||
% \item scenariusze korzystania z systemu (ilustrowane zrzutami z ekranu lub generowanymi dokumentami)
|
||||
% \end{itemize}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%
|
||||
%% RYSUNEK Z PLIKU
|
||||
%
|
||||
@ -910,85 +1118,230 @@ Jeśli „Specyfikacja zewnętrzna”:
|
||||
|
||||
|
||||
|
||||
\begin{figure}
|
||||
\centering
|
||||
\begin{tikzpicture}
|
||||
\begin{axis}[
|
||||
y tick label style={
|
||||
/pgf/number format/.cd,
|
||||
fixed, % po zakomentowaniu os rzednych jest indeksowana wykladniczo
|
||||
fixed zerofill, % 1.0 zamiast 1
|
||||
precision=1,
|
||||
/tikz/.cd
|
||||
},
|
||||
x tick label style={
|
||||
/pgf/number format/.cd,
|
||||
fixed,
|
||||
fixed zerofill,
|
||||
precision=2,
|
||||
/tikz/.cd
|
||||
}
|
||||
]
|
||||
\addplot [domain=0.0:0.1] {rnd};
|
||||
\end{axis}
|
||||
\end{tikzpicture}
|
||||
\caption{Podpis rysunku po rysunkiem.}
|
||||
\label{fig:2}
|
||||
\end{figure}
|
||||
% \begin{figure}
|
||||
% \centering
|
||||
% \begin{tikzpicture}
|
||||
% \begin{axis}[
|
||||
% y tick label style={
|
||||
% /pgf/number format/.cd,
|
||||
% fixed, % po zakomentowaniu os rzednych jest indeksowana wykladniczo
|
||||
% fixed zerofill, % 1.0 zamiast 1
|
||||
% precision=1,
|
||||
% /tikz/.cd
|
||||
% },
|
||||
% x tick label style={
|
||||
% /pgf/number format/.cd,
|
||||
% fixed,
|
||||
% fixed zerofill,
|
||||
% precision=2,
|
||||
% /tikz/.cd
|
||||
% }
|
||||
% ]
|
||||
% \addplot [domain=0.0:0.1] {rnd};
|
||||
% \end{axis}
|
||||
% \end{tikzpicture}
|
||||
% \caption{Podpis rysunku po rysunkiem.}
|
||||
% \label{fig:2}
|
||||
% \end{figure}
|
||||
|
||||
|
||||
|
||||
% TODO
|
||||
\chapter{[Właściwy dla kierunku -- np. Specyfikacja wewnętrzna]}
|
||||
\label{ch:05}
|
||||
\chapter{Specyfikacja wewnętrzna}
|
||||
\label{ch:specyfikacja-wewnetrzna}
|
||||
|
||||
\paragraph{Idea rozwiązania}
|
||||
Zamysł proponowanego rozwiązania jest dość prosty i opiera się na kilku elementach:
|
||||
|
||||
Jeśli „Specyfikacja wewnętrzna”:
|
||||
\begin{itemize}
|
||||
\item przedstawienie idei
|
||||
\item architektura systemu
|
||||
\item opis struktur danych (i organizacji baz danych)
|
||||
\item komponenty, moduły, biblioteki, przegląd ważniejszych klas (jeśli występują)
|
||||
\item przegląd ważniejszych algorytmów (jeśli występują)
|
||||
\item szczegóły implementacji wybranych fragmentów, zastosowane wzorce projektowe
|
||||
\item diagramy UML
|
||||
\item serwer przechowuje metadane o obrazach (nazwa, wersja, hash pliku, lokalizacja pliku), same pliki obrazów oraz dane o klientach (nazwa hosta, adres IP, adres MAC, wersja aplikacji klienckiej)
|
||||
\item dane o obrazach jak i same obrazy są ręcznie dodawane przez administratora
|
||||
\item klienci sami rejestrują się oraz aktualizują dane o sobie na serwerze
|
||||
\item klienci pobierają dane o przypisanych do siebie maszynach wirtualnych, pobierają także przypisane obrazy
|
||||
\item komunikacja odbywa się poprzez protokół HTTP
|
||||
\item do komunikacji z serwerem wymagana jest autoryzacja poprzez token JWT(JSON Web Token), uzyskiwany poprzez wysłanie loginu oraz hasła w formacie JSON do odpowiedniego punktu końcowego na serwerze
|
||||
\item po synchronizacji stanu pomiędzy klientem a serwerem, na kliencie uruchamia się okno wyboru obrazu do uruchomienia
|
||||
\item aplikacja klienta zbiera także podstawowe dane o maszynie: (zainstalowaną pojemność pamięci RAM, liczbę wątków procesora, adres IP oraz MAC karty sieciowej, która ma połączenie z siecią)
|
||||
\item po wybraniu obrazu, na podstawie danych o maszynie zebranych przez aplikację klienta generowany jest skrypt, uruchamiający program QEMU z zebranymi danymi jako argumentami wywołania
|
||||
\item oryginalny obraz maszyny wirtualnej jest kopiowany, a następnie uruchamiany jest skrypt włączający maszynę wirtualną
|
||||
\item po zakończonej pracy i wyłączeniu maszyny wirtualnej, skrypt podmienia modyfikowany obraz dysku maszyny wirtualnej na oryginalny, skopiowany w kroku wcześniej
|
||||
\item środowisko klienta składa się z bardzo okrojonego środowiska graficznego \texttt{i3}\footnote{\url{https://i3wm.org/}}, które nie pozwala na wyjście z aplikacji klienckiej oraz emulatora terminala rxvt
|
||||
\item po uruchomieniu maszyny wirtualnej środowisko graficzne promuje jej okno do wypełnienia całego ekranu, jednocześnie przechwytując klawiaturę i myszkę, aby przekierować je do obsługi maszyny wirtualnej
|
||||
\end{itemize}
|
||||
|
||||
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
|
||||
% Pakiet minted wymaga odkomentowania w pliku config/settings.tex %
|
||||
% importu pakietu minted: \usepackage{minted} %
|
||||
% i specjalnego kompilowania: %
|
||||
% pdflatex -shell-escape praca %
|
||||
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
|
||||
\paragraph{Architektura sieciowa rozwiązania}
|
||||
Proponowana architektura sieciowa dla rozwiązania została zaprezentowana na rys. \ref{fig:prop-network}.
|
||||
Zakłada ona, że serwer DHCP będzie na tej samej maszynie co serwer TFTP oraz zarządcy obrazów, jednak
|
||||
możliwe jest rozbicie każdego z tych narzędzi na osobną maszynę dedykowaną. Podobnie, jeżeli zagwarantowana
|
||||
zostanie poprawna konfiguracja, możliwe jest wykorzystanie dowolnego serwera DHCP, jednak przetestowana została
|
||||
wyłącznie architektura z serwerem DHCP w implementacji ISC.
|
||||
|
||||
|
||||
Krótka wstawka kodu w linii tekstu jest możliwa, np. \lstinline|int a;| (biblioteka \texttt{listings})% lub \mintinline{C++}|int a;| (biblioteka \texttt{minted})
|
||||
.
|
||||
Dłuższe fragmenty lepiej jest umieszczać jako rysunek, np. kod na rys \ref{fig:pseudokod:listings}% i rys. \ref{fig:pseudokod:minted}
|
||||
, a naprawdę długie fragmenty – w załączniku.
|
||||
|
||||
|
||||
\begin{figure}
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\begin{lstlisting}
|
||||
class test : public basic
|
||||
{
|
||||
public:
|
||||
test (int a);
|
||||
friend std::ostream operator<<(std::ostream & s,
|
||||
const test & t);
|
||||
protected:
|
||||
int _a;
|
||||
|
||||
};
|
||||
\end{lstlisting}
|
||||
\caption{Pseudokod w \texttt{listings}.}
|
||||
\label{fig:pseudokod:listings}
|
||||
\includegraphics[width=\textwidth]{./pictures/architektura-pracy-inzynierskiej-sieciowa.png}
|
||||
\caption{Proponowana architektura sieciowa dla rozwiązania}
|
||||
\label{fig:prop-network}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{Strona serwera}
|
||||
Logika serwera zarządcy obrazów opiera się na koncepcie obrazu oraz klienta. Istnieje tylko jeden użytkownik, wspólny dla wszystkich
|
||||
klientów. Każdy klient może mieć przypisane do siebie wiele obrazów. Diagram klas wykorzystywanych przez aplikację przedstawiono
|
||||
na rys. \ref{fig:class-diagram-server}.
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{./pictures/diagram_klaspng.png}
|
||||
\caption{Diagram klas wykorzystywanych przez serwer}
|
||||
\label{fig:class-diagram-server}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{}
|
||||
Dane o obrazach i klientach przechowywane są w bazie danych SQLite3. Aplikacja korzysta z biblioteki ORM (Object-Relational Mapping)
|
||||
SQLAlchemy dla języka Python. Narzędzie to stworzyło 4 tabele o następujących kolumnach:
|
||||
|
||||
\begin{itemize}
|
||||
\item clients:
|
||||
\begin{itemize}
|
||||
\item mac\_address: VARCHAR NOT NULL PRIMARY KEY
|
||||
\item ip\_address: VARCHAR(16) NOT NULL
|
||||
\item hostname: VARCHAR(100) NOT NULL
|
||||
\item client\_version: VARCHAR(100) NOT NULL
|
||||
\end{itemize}
|
||||
\item vm\_images:
|
||||
\begin{itemize}
|
||||
\item image\_id: INTEGER NOT NULL PRIMARY KEY
|
||||
\item image\_name: VARCHAR(100) NOT NULL
|
||||
\item image\_file: VARCHAR(500) NOT NULL
|
||||
\item image\_version: VARCHAR(100) NOT NULL
|
||||
\item image\_hash: VARCHAR(500) NOT NULL
|
||||
\item image\_name\_version\_combo: VARCHAR (600) NOT NULL
|
||||
\end{itemize}
|
||||
\item users:
|
||||
\begin{itemize}
|
||||
\item user\_id: INTEGER NOT NULL PRIMARY KEY
|
||||
\item username: VARCHAR NOT NULL
|
||||
\item password\_hash: VARCHAR NOT NULL
|
||||
\end{itemize}
|
||||
\item client\_image:
|
||||
\begin{itemize}
|
||||
\item client\_mac: FOREIGN KEY VARCHAR
|
||||
\item mage\_id: FOREIGN KEY INTEGER
|
||||
\end{itemize}
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Do stworzenia serwera wykorzystano następujące biblioteki:
|
||||
|
||||
\begin{itemize}
|
||||
\item bcrypt - do tworzenia bezpiecznych ,,hashy'' (wyników funkcji skrótu) haseł
|
||||
\item Flask - do stworzenia serwera HTTP
|
||||
\item pyaml - do odczytu i analizy plików o rozszerzeniu YAML
|
||||
\item PyJWT - do obsługi i tworzenia tokenów JWT
|
||||
\item prettytable - do formatowania danych w przejrzysty sposób
|
||||
\item SQLAlchemy - jako ORM do obsługi bazy danych
|
||||
\item argparse - do parsowania argumentów wywołania programu
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Program został podzielony na kilka głównych modułów:
|
||||
|
||||
\begin{itemize}
|
||||
\item obsługa bazy danych
|
||||
\item serwer HTTP, obsługa żądań i odpowiedzi
|
||||
\item obsługa pliku konfiguracyjnego i zmiennych środowiskowych
|
||||
\item moduł modeli danych dla bazy danych
|
||||
\item moduł obsługi autoryzacji poprzez tokeny JWT
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Obsługa bazy danych została zaimplementowana w klasie \texttt{Database}. Jej zadaniem jest zestawienie połączenia z bazą danych
|
||||
oraz manipulacja wszystkimi modelami wykorzystywanymi w programie. Dodawanie, usuwanie, modyfikacja i pobieranie danych
|
||||
z bazy danych odbywa się poprzez zaimplementowane metody. Są one wysokopoziomowymi abstrakcjami podstawowych zapytań
|
||||
SQL:
|
||||
|
||||
\begin{itemize}
|
||||
\item metody o formacie \texttt{get\_[nazwa\_modelu]\_by\_[nazwa\_atrybutu]} odpowiadają zapytaniom \texttt{SELECT}
|
||||
\item metody o formacie \texttt{add\_[nazwa\_modelu]} odpowiadają zapytaniom \texttt{INSERT}
|
||||
\item metody o formacie \texttt{modify\_[nazwa\_modelu]} odpowiadają zapytaniom \texttt{UPDATE}
|
||||
\item metody o formacie \texttt{delete\_[nazwa\_modelu]} odpowiadają zapytaniom \texttt{DELETE}
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Serwer HTPP został zbudowany w oparciu o bibliotekę Flask. Do obsługi zapytań HTTP stworzono klasę \texttt{Server}, która
|
||||
zawiera w sobie metody, które obsługują wszystkie punkty końcowe. Autoryzacja dostępu została zaimplementowana przez mechanizm
|
||||
dekoratorów, a dokładniej przez zaimplementowany dekorator \texttt{require\_auth}. Sprawdza on, czy w nagłówkach zapytania HTTP
|
||||
klient wysłał odpowiedni token JWT i jeżeli nie był poprawny, zwraca odpowiedni komunikat do klienta. Jeżeli jednak był poprawny,
|
||||
przekazuje do funkcji obsługującej zapytanie informacje o zautoryzowanym użytkowniku. Przykład użycia tego dekoratora przedstawiono
|
||||
na listingu \ref{fig:requireauth:listings}.
|
||||
|
||||
\begin{figure}[hb]
|
||||
\centering
|
||||
\begin{lstlisting}
|
||||
class Server:
|
||||
@require_auth
|
||||
def register_new_client_to_database(request_user, self):
|
||||
\end{lstlisting}
|
||||
\caption{Przykład użycia dekoratora \texttt{require\_auth}}
|
||||
\label{fig:requireauth:listings}
|
||||
\end{figure}
|
||||
|
||||
\paragraph{}
|
||||
Ostatnim ważnym komponentem aplikacji jest klasa \texttt{ServerConfig}. Odpowiada ona za odczyt i parsowanie plików konfiguracyjnych
|
||||
oraz odczytanie wartości ustawionych zmiennych środowiskowych i nadpisanie odpowiednich wartości w konfiguracji.
|
||||
Do obsługi plików konfiguracyjnych wybrano bibliotekę \texttt{PYAML}.
|
||||
|
||||
\paragraph{Strona klienta}
|
||||
Po stronie klienta jedyną strukturą danych jaka została wykorzystana, był model obrazu, wykorzystywany także po stronie serwera.
|
||||
Wykorzystano następujące biblioteki:
|
||||
|
||||
\begin{itemize}
|
||||
\item picotui - do stworzenia interfejsu użytkownika
|
||||
\item getmac - do pobrania informacji o karcie sieciowej
|
||||
\item pyaml - do odczytu i parsowania plików konfiguracyjnych
|
||||
\item requests - do wysyłania zapytań do serwera
|
||||
\item psutil - do pobierania informacji o dostępnej liczbie rdzeni i pamięci operacyjnej urządzenia
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
Aplikacja klienta została podzielona na klika podstawowych modułów:
|
||||
|
||||
\begin{itemize}
|
||||
\item moduł sprawdzający dane o maszynie, na której jest uruchomiony
|
||||
\item moduł obsługujący komunikację z serwerem
|
||||
\item moduł obsługujący uruchamianie maszyn wirtualnych oraz wyświetlanie interfejsu użytkownika
|
||||
\end{itemize}
|
||||
|
||||
\paragraph{}
|
||||
|
||||
|
||||
% Jeśli „Specyfikacja wewnętrzna”:
|
||||
% \begin{itemize}
|
||||
% \item przedstawienie idei
|
||||
% \item architektura systemu
|
||||
% \item opis struktur danych (i organizacji baz danych)
|
||||
% \item komponenty, moduły, biblioteki, przegląd ważniejszych klas (jeśli występują)
|
||||
% \item przegląd ważniejszych algorytmów (jeśli występują)
|
||||
% \item szczegóły implementacji wybranych fragmentów, zastosowane wzorce projektowe
|
||||
% \item diagramy UML
|
||||
% \end{itemize}
|
||||
%
|
||||
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
|
||||
% % Pakiet minted wymaga odkomentowania w pliku config/settings.tex %
|
||||
% % importu pakietu minted: \usepackage{minted} %
|
||||
% % i specjalnego kompilowania: %
|
||||
% % pdflatex -shell-escape praca %
|
||||
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % %
|
||||
%
|
||||
%
|
||||
% Krótka wstawka kodu w linii tekstu jest możliwa, np. \lstinline|int a;| (biblioteka \texttt{listings})% lub \mintinline{C++}|int a;| (biblioteka \texttt{minted})
|
||||
% .
|
||||
% Dłuższe fragmenty lepiej jest umieszczać jako rysunek, np. kod na rys \ref{fig:pseudokod:listings}% i rys. \ref{fig:pseudokod:minted}
|
||||
% , a naprawdę długie fragmenty – w załączniku.
|
||||
%
|
||||
%
|
||||
% \begin{figure}
|
||||
% \centering
|
||||
%\begin{minted}[linenos,frame=lines]{c++}
|
||||
% \begin{lstlisting}
|
||||
% class test : public basic
|
||||
% {
|
||||
% public:
|
||||
@ -999,10 +1352,28 @@ class test : public basic
|
||||
% int _a;
|
||||
%
|
||||
% };
|
||||
%\end{minted}
|
||||
%\caption{Pseudokod w \texttt{minted}.}
|
||||
%\label{fig:pseudokod:minted}
|
||||
% \end{lstlisting}
|
||||
% \caption{Pseudokod w \texttt{listings}.}
|
||||
% \label{fig:pseudokod:listings}
|
||||
% \end{figure}
|
||||
%
|
||||
% %\begin{figure}
|
||||
% %\centering
|
||||
% %\begin{minted}[linenos,frame=lines]{c++}
|
||||
% %class test : public basic
|
||||
% %{
|
||||
% % public:
|
||||
% % test (int a);
|
||||
% % friend std::ostream operator<<(std::ostream & s,
|
||||
% % const test & t);
|
||||
% % protected:
|
||||
% % int _a;
|
||||
% %
|
||||
% %};
|
||||
% %\end{minted}
|
||||
% %\caption{Pseudokod w \texttt{minted}.}
|
||||
% %\label{fig:pseudokod:minted}
|
||||
% %\end{figure}
|
||||
|
||||
|
||||
|
||||
@ -1010,6 +1381,21 @@ class test : public basic
|
||||
% TODO
|
||||
\chapter{Weryfikacja i walidacja}
|
||||
\label{ch:06}
|
||||
|
||||
\paragraph{Sposób testów}
|
||||
Testy całości rozwiązania zostały przeprowadzone korzystając z komputera Lenovo Thinkpad T480.
|
||||
Posiada procesor Intel Core i5-8250U (4 rdzenie, 8 wątków), 24GB pamięci RAM oraz dysk SSD o pojemności 256GB.
|
||||
Pracuje pod kontrolą UEFI, wspiera Intel VT-d oraz PXE.
|
||||
|
||||
W ramach pierwszej fazy testów urządzenie było wielokrotnie czyszczone oraz konfigurowane ponownie. W ich trakcie przeporwadzono
|
||||
pomiary czasu jaki jest wymagany do pełnej konfiguracji maszyny.
|
||||
|
||||
W ramach drugiej fazy testów ręcznie wymuszano proces synchronizacji zmian z serwerem. Do testów przygotowano obraz maszyny wirtualnej
|
||||
pracującej pod kontrolą systemu Ubuntu Linux w wersji 22.04 LTS wraz ze środowiskiem graficznym Gnome. Obraz dysku zajmował
|
||||
12GB. Podczas tych testów sprawdzano czas potrzebny na pobranie przykladowego obrazu, korzystając z gigabitowej karty sieciowej, dostępnej w maszynie.
|
||||
|
||||
W ramach trzeciej fazy testów, poddano ocenie wydajność i odczucia płynące z używania maszyny wirtualnej.
|
||||
|
||||
\begin{itemize}
|
||||
\item sposób testowania w ramach pracy (np. odniesienie do modelu V)
|
||||
\item organizacja eksperymentów
|
||||
|
BIN
pictures/.DS_Store
vendored
Normal file
BIN
pictures/add_image_command.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
pictures/architektura-pracy-inzynierskiej-sieciowa.png
Normal file
After Width: | Height: | Size: 21 KiB |
4
pictures/architektura-pracy-inzynierskiej-sieciowa.svg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
pictures/assign_image_command.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
pictures/boot-screen-pxe.png
Normal file
After Width: | Height: | Size: 76 KiB |
1
pictures/diagram_klas.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="Electron" modified="2023-01-05T16:28:57.770Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.7.4 Chrome/106.0.5249.199 Electron/21.3.3 Safari/537.36" version="20.7.4" etag="Wfms6icj7N-3HrRO-ynV" type="device"><diagram id="0O1eIQxPBPTji6g3RqVb" name="Strona-1">7Zpfc5s4EMA/jR97Y/DfPMZOcu1M0nbiuUnvXjwqkkFXoWWEHNv99F2BMGDAdS7BnvaYyWS8i4Sk3Z/E7kJvMA+3fyoSBQ9Amei5fbrtDW56rjueOvjfKHapYji4ShW+4jRVObliwb8zq+xb7ZpTFpcaagCheVRWeiAl83RJR5SCTbnZCkR51Ij4rKJYeERUtU+c6iDVTt1Jrn/PuB9kIztju76QZI3tSuKAUNgUVIPb3mCuAHT6K9zOmTC2y+yS9rtruLqfmGJSn9Jh8Wn38cPd1aend/9cUy6fZu7s8Z29yzMRa7vgueDmhumU9S6zQ7zhoSASpdkKpF7YK32UvYALek92sDbziDXxvmXSLADFv2N7IvCSgwq8rLR1s2t6r7gQcxCgUCEhGSDvtDA3s8MoFmO3z9l6nQPVA9mWGt6TWGcTBCFIFPOvyZRNx5Aon8sZaA2hbRTCM8kbJPcoyqCJLshIOSvKjPKiaGksazThkqnS1PfoGJV1BVOabRt97OzJwR3HIGRa7bCJ7TC0rO3K4iYn18l0QZFad2h3jN0t/v7O+8EezXqkjwt6wWiTmsEG/fJYRGimJNFsBmtJ4yLD+KOwylyVkP0Cyt0K5T13luxRb0koRV/gXK4T4BWXfgV+dIhO2FXwjR3AWsMvEdyXKAq2Mt2MRzmeKNdWrSEyN4uIh2PdJ21uhrnm0ZrKqAD7rkRyagScUiYPUDTgRsClTmw5muEfWnfe/2PUG+HE5yg7uYx/prnSc5C4FsTRjMNwo2yY2SynEdh8jlSxtGS4J3LojpsxLDHxUgAGDQDwqPP/Gfw/HF/Y/1cN/g8g1pKErPN+i96fuBf2/rDB+14S6ixxxTEH2TFwEKb0W2TianphJrL8ogDFh9DkAl3g+0sGvu5PY9F9FFKKfCdHAPsNIl+nmuDZyMfAvjR9zamH5wDz0UX/12PvFcdcv57L5si3lsP2zrmm3CcFoAt+2iagJvY9MwGNyU9CQBf9nAGCmhD4zBCMjkIQkDjoCGiTgJqA98wENGVBKQHoxO5B8MYZ0HEi9kXXyyEx/mlskD0elh6EX6EDpFUgRhcPFicVrzLqsyznRaME4IMk4jbXoqkxeWHUGjpvcw/GhUmC9y/TemdzX7LWYFJdHWaZMdty/aXw+29zK3RGKt1k2W0i7DJB4nq/FIVCLyPm3RIp70evzVtBFD1B4ph7qfKOi1KiXm2UqAvNUksZ8zRCYFUxrJXHjpjdBmg4gM+O8jOq50cxQTR/Lk/k7eGYVk6Ljy86BLId76GBzPFaWwHJsTg8EULc2wlwm4BrtsBzwIy5USSqQHjSFj1eUHCm5RR/Ut2b4xNS/LezfrWE/fD7Wn8wLlvfqcmjz2r+bPyC+Z/DpeCxXuLDMSRegCFD90j87x4/LKnVPQydsz4M3Wrp7K+4pkbWSoF43LBBL1EgfgPvHjj39A8T+kc+THidd5vqYmv0cVcXfXWs2wRERsCl3wi7TVUx4/+uKtq2/0fVgtiZ/d9UDokw4N+Aol1NrHUIJu29BEYx/7IyfZmWf546uP0B</diagram></mxfile>
|
BIN
pictures/diagram_klaspng.png
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
pictures/help_command.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
pictures/print_clients_command.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
pictures/print_images_command.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
pictures/screenshot-client-app-running.png
Normal file
After Width: | Height: | Size: 35 KiB |