Wojciech Janota 2 years ago
parent 677d91ca71
commit c4a9a9531b

BIN
.DS_Store vendored

Binary file not shown.

Binary file not shown.

@ -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{Wymagania funkcjonalne}
Rozwiązanie powinno spełniać następujące wymagania funkcjonalne:
\begin{itemize}
\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{}
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.
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{}
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.
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{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:
\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 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:
% TODO
\chapter{[Właściwy dla kierunku -- np. Specyfikacja zewnętrzna]}
\label{ch:04}
\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:
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 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,99 +1118,262 @@ 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.
\begin{figure}[hb]
\centering
\includegraphics[width=\textwidth]{./pictures/architektura-pracy-inzynierskiej-sieciowa.png}
\caption{Proponowana architektura sieciowa dla rozwiązania}
\label{fig:prop-network}
\end{figure}
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.
\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}
\begin{figure}
\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}
\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}
%\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}
\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{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}
% \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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Loading…
Cancel
Save