% !TeX spellcheck = pl_PL
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                        %
% Szablon pracy dyplomowej inzynierskiej % 
% zgodny  z aktualnymi  przepisami  SZJK %
%                                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                        %
%  (c) Krzysztof Simiński, 2018-2022     %
%                                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                        %
% Najnowsza wersja szablonów jest        %
% podstępna pod adresem                  %
% github.com/ksiminski/polsl-aei-theses  %
%                                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
% Projekt LaTeXowy zapewnia odpowiednie formatowanie pracy,
% zgodnie z wymaganiami Systemu zapewniania jakości kształcenia.
% Proszę nie zmieniać ustawień formatowania (np. fontu,
% marginesów, wytłuszczeń, kursywy itd. ).
%
% Projekt można kompilować na kilka sposobów.
%
% 1. kompilacja pdfLaTeX
%
% pdflatex main
% bibtex   main
% pdflatex main
% pdflatex main 
%
%
% 2. kompilacja XeLaTeX
%
% Kompilatacja przy użyciu XeLaTeXa różni się tym, że na stronie
% tytułowej używany jest font Calibri. Wymaga to jego uprzedniego
% zainstalowania. 
%
% xelatex main
% bibtex  main
% xelatex main
% xelatex main 
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% W przypadku pytań, uwag, proszę pisać na adres:   %
%      krzysztof.siminski(małpa)polsl.pl            %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Chcemy ulepszać szablony LaTeXowe prac dyplomowych. 
% Wypełniając ankietę spod poniższego adresu pomogą 
% Państwo nam to zrobić. Ankieta jest całkowicie 
% anonimowa. Dziękujemy! 
% https://docs.google.com/forms/d/e/1FAIpQLScyllVxNKzKFHfILDfdbwC-jvT8YL0RSTFs-s27UGw9CKn-fQ/viewform?usp=sf_link
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% PERSONALIZACJA PRACY – DANE PRACY           %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Proszę wpisać swoje dane w poniższych definicjach.

% TODO
\newcommand{\FirstName}{Wojciech}
\newcommand{\Surname}{Janota}
\newcommand{\Supervisor}{$\langle$dr inż. Błażej Adamczyk$\rangle$}     % dane promotora (bez $\langle$ i $\rangle$)
\newcommand{\Title}{System do obsługi pracowni informatycznych z wykorzystaniem maszyn wirtualnych}           % tytuł pracy po polsku
\newcommand{\TitleAlt}{A system for supporting IT labs with the use of virtual machines}                     % thesis title in English
\newcommand{\Program}{$\langle$Informatyka$\rangle$}            % kierunek studiów  (bez $\langle$ i $\rangle$)
\newcommand{\Specialisation}{$\langle$Bazy Danych i Inżynieria Systemów$\rangle$}     % specjalność  (bez $\langle$ i $\rangle$)
\newcommand{\Id}{$\langle$290357$\rangle$}                 % numer albumu  (bez $\langle$ i $\rangle$)
\newcommand{\Departament}{$\langle$Katedra Sieci i Systemów Komputerowych$\rangle$}        % katedra promotora  (bez $\langle$ i $\rangle$)

% Jeżeli został wyznaczony promotor pomocniczy lub opiekun, proszę go/ją wpisać ...
\newcommand{\Consultant}{} % dane promotora pomocniczego, opiekuna (bez $\langle$ i $\rangle$)
% ... w przeciwnym razie proszę zostawić puste miejsce jak poniżej:
%\newcommand{\Consultant}{} % brak promotowa pomocniczego / opiekuna

% koniec fragmentu do modyfikacji
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% KONIEC PERSONALIZACJI PRACY                 %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% PROSZĘ NIE MODYFIKOWAĆ PONIŻSZYCH USTAWIEŃ! %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



\documentclass[a4paper,twoside,12pt]{book}
\usepackage[utf8]{inputenc}                                      
\usepackage[T1]{fontenc}  
\usepackage{amsmath,amsfonts,amssymb,amsthm}
\usepackage[british,polish]{babel} 
\usepackage{indentfirst}



\usepackage{ifxetex}

\ifxetex
	\usepackage{fontspec}
	\defaultfontfeatures{Mapping=tex—text} % to support TeX conventions like ``——-''
	\usepackage{xunicode} % Unicode support for LaTeX character names (accents, European chars, etc)
	\usepackage{xltxtra} % Extra customizations for XeLaTeX
\else
	\usepackage{lmodern}
\fi



\usepackage[margin=2.5cm]{geometry}
\usepackage{graphicx} 
\usepackage{hyperref}
\usepackage{booktabs}
\usepackage{tikz}
\usepackage{pgfplots}
\usepackage{mathtools}
\usepackage{geometry}
\usepackage{subcaption}   % subfigures
\usepackage[page]{appendix} % toc,
\renewcommand{\appendixtocname}{Dodatki}
\renewcommand{\appendixpagename}{Dodatki}
\renewcommand{\appendixname}{Dodatek}

\usepackage{csquotes}
\usepackage[natbib=true,backend=bibtex]{biblatex}  % kompilacja bibliografii BibTeXem
%\usepackage[natbib=true,backend=biber]{biblatex}  % kompilacja bibliografii Biberem
\bibliography{biblio}

\usepackage{ifmtarg}   % empty commands  

\usepackage{setspace}
\onehalfspacing


\frenchspacing



%%%% TODO LIST GENERATOR %%%%%%%%%

\usepackage{color}
\definecolor{brickred}      {cmyk}{0   , 0.89, 0.94, 0.28}

\makeatletter \newcommand \kslistofremarks{\section*{Uwagi} \@starttoc{rks}}
  \newcommand\l@uwagas[2]
    {\par\noindent \textbf{#2:} %\parbox{10cm}
{#1}\par} \makeatother


\newcommand{\ksremark}[1]{%
{%\marginpar{\textdbend}
{\color{brickred}{[#1]}}}%
\addcontentsline{rks}{uwagas}{\protect{#1}}%
}

\newcommand{\comma}{\ksremark{przecinek}}
\newcommand{\nocomma}{\ksremark{bez przecinka}}
\newcommand{\styl}{\ksremark{styl}}
\newcommand{\ortografia}{\ksremark{ortografia}}
\newcommand{\fleksja}{\ksremark{fleksja}}
\newcommand{\pauza}{\ksremark{pauza `--', nie dywiz `-'}}
\newcommand{\kolokwializm}{\ksremark{kolokwializm}}
\newcommand{\cudzyslowy}{\ksremark{,,polskie cudzysłowy''}}

%%%%%%%%%%%%%% END OF TODO LIST GENERATOR %%%%%%%%%%%

%%%%%%%%%%%% ZYWA PAGINA %%%%%%%%%%%%%%%
% brak kapitalizacji zywej paginy
\usepackage{fancyhdr}
\pagestyle{fancy}
\fancyhf{}
\fancyhead[LO]{\nouppercase{\it\rightmark}}
\fancyhead[RE]{\nouppercase{\it\leftmark}}
\fancyhead[LE,RO]{\it\thepage}


\fancypagestyle{tylkoNumeryStron}{%
   \fancyhf{} 
   \fancyhead[LE,RO]{\it\thepage}
}

\fancypagestyle{bezNumeracji}{%
   \fancyhf{} 
   \fancyhead[LE,RO]{}
}

\fancypagestyle{NumeryStronNazwyRozdzialow}{%
   \fancyhf{} 
   \fancyhead[LE]{\nouppercase{\FirstName\ \Surname}}
   \fancyhead[RO]{\nouppercase{\leftmark}} 
   \fancyfoot[CE, CO]{\thepage}
}


%%%%%%%%%%%%% OBCE WTRETY  
\newcommand{\obcy}[1]{\emph{#1}}
\newcommand{\ang}[1]{{\selectlanguage{british}\obcy{#1}}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% polskie oznaczenia funkcji matematycznych
\renewcommand{\tan}{\operatorname {tg}}
\renewcommand{\log}{\operatorname {lg}}

% jeszcze jakies drobiazgi

\newcounter{stronyPozaNumeracja}

%%%%%%%%%%%%%%%%%%%%%%%%%%% 
\usepackage{xstring}
\usepackage{ifthen}
\newcommand{\printOpiekun}[1]{%		

    \StrLen{\Consultant}[\mystringlen]
    \ifthenelse{\mystringlen > 0}%
    {%
       {\large{\bfseries OPIEKUN, PROMOTOR POMOCNICZY}\par}
       
       {\large{\bfseries \Consultant}\par}
    }%
    {}
} 
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
% Proszę nie modyfikować poniższych definicji!
\author{\FirstName\ \Surname}
\newcommand{\Author}{\FirstName\ \MakeUppercase{\Surname}}
\newcommand{\Type}{PROJEKT INŻYNIERSKI}
\newcommand{\Faculty}{Wydział Automatyki, Elektroniki i Informatyki} 
\newcommand{\Polsl}{Politechnika Śląska}
\newcommand{\Logo}{politechnika_sl_logo_bw_pion_pl.pdf}
\newcommand{\LeftId}{Nr albumu}
\newcommand{\LeftProgram}{Kierunek}
\newcommand{\LeftSpecialisation}{Specjalność}
\newcommand{\LeftSUPERVISOR}{PROWADZĄCY PRACĘ}
\newcommand{\LeftDEPARTMENT}{KATEDRA}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% KONIEC USTAWIEŃ                             %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% MOJE PAKIETY, USTAWIENIA ITD                %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Tutaj proszę umieszczać swoje pakiety, makra, ustawienia itd.


 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% listingi i fragmentu kodu źródłowego 
% pakiet: listings lub minted
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % 

% biblioteka listings
\usepackage{listings}
\lstset{%
morekeywords={string,exception,std,vector},% słowa kluczowe rozpoznawane przez pakiet listings
language=C++,% C, Matlab, Python, SQL, TeX, XML, bash, ... – vide https://www.ctan.org/pkg/listings
commentstyle=\textit,%
identifierstyle=\textsf,%
keywordstyle=\sffamily\bfseries, %\texttt, %
%captionpos=b,%
tabsize=3,%
frame=lines,%
numbers=left,%
numberstyle=\tiny,%
numbersep=5pt,%
breaklines=true,%
%morekeywords={descriptor_gaussian,descriptor,partition,fcm_possibilistic,dataset,my_exception,exception,std,vector},%
escapeinside={@*}{*@},%
}

% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % 
% pakiet minted
%\usepackage{minted}

% pakiet wymaga specjalnego kompilowania:
% pdflatex -shell-escape main.tex
% xelatex  -shell-escape main.tex

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% KONIEC MOICH USTAWIEŃ                       %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   


\begin{document}
%\kslistofremarks 

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% PROSZĘ NIE MODYFIKOWAĆ STRONY TYTUŁOWEJ!    %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%  STRONA TYTUŁOWA %%%%%%%%%%%%%%%%%%%
\pagestyle{empty}
{
	\newgeometry{top=1.5cm,%
	             bottom=2.5cm,%
	             left=3cm,
	             right=2.5cm}
 
	\ifxetex 
	  \begingroup
	  \setsansfont{Calibri}
	   
	\fi 
	 \sffamily
	\begin{center}
	\includegraphics[width=50mm]{\Logo}
	 
	
	{\Large\bfseries\Type\par}
	
	\vfill  \vfill  
			 
	{\large\Title\par}
	
	\vfill  
		
	{\large\bfseries\Author\par}
	
	{\normalsize\bfseries \LeftId: \Id}
	
	\vfill  		
 
	{\large{\bfseries \LeftProgram:} \Program\par} 
	
	{\large{\bfseries \LeftSpecialisation:} \Specialisation\par} 
	 		
	\vfill  \vfill 	\vfill 	\vfill 	\vfill 	\vfill 	\vfill  
	 
	{\large{\bfseries \LeftSUPERVISOR}\par}
	
	{\large{\bfseries \Supervisor}\par}
				
	{\large{\bfseries \LeftDEPARTMENT\ \Departament} \par}
		
	{\large{\bfseries \Faculty}\par}
		
	\vfill  \vfill  

    	
    \printOpiekun{\Consultant}
    
	\vfill  \vfill  
		
    {\large\bfseries  Gliwice \the\year}

   \end{center}	
       \ifxetex 
       	  \endgroup
       \fi
	\restoregeometry
}
  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                             %
% KONIEC STRONY TYTUŁOWEJ                     %
%                                             %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\cleardoublepage
 
\rmfamily\normalfont
\pagestyle{empty}

  
%%% No to zaczynamy pisać pracę :-) %%%%

% TODO
\subsubsection*{Tytuł pracy} 
\Title

\subsubsection*{Streszczenie}  
Tematem pracy jest stworzenie systemu do zarządzania pracowniami informatycznymi
używając możliwości oferowanych przez maszyny wirtualne.
Proponowana solucja umożliwia zdalne, zautomatyzowane przygotowanie pracowni informatycznej do zajęć lekcyjnych,
minimalizując wymaganą liczbę manualnych kroków. 

\subsubsection*{Słowa kluczowe} 
automatyzacja,PXE,Python,Ansible,Linux,QEMU

\subsubsection*{Thesis title} 
\begin{otherlanguage}{british}
\TitleAlt
\end{otherlanguage}

\subsubsection*{Abstract} 
\begin{otherlanguage}{british}
Topic of this thesis is a automated system for managing IT labs using virtual machines. Solution allows
for remote, automated preparation of the lab for classes, minimizing number of manual steps required.
\end{otherlanguage}
\subsubsection*{Key words}  
\begin{otherlanguage}{british}
automation,PXE,Python,Ansible,Linux,QEMU
\end{otherlanguage}




%%%%%%%%%%%%%%%%%% SPIS TRESCI %%%%%%%%%%%%%%%%%%%%%%
%\pagenumbering{Roman}
\thispagestyle{empty}
\tableofcontents
\thispagestyle{empty}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\setcounter{stronyPozaNumeracja}{\value{page}}
\mainmatter
\pagestyle{empty}
 
\cleardoublepage

\pagestyle{NumeryStronNazwyRozdzialow}

%%%%%%%%%%%%%% wlasciwa tresc pracy %%%%%%%%%%%%%%%%%

% TODO
\chapter{Wstęp}
\label{ch:wstep}

\paragraph{Wprowadzenie}
Jednym z wielu problemów, z jakimi musi zmierzyć się administrator systemów (na przykład w placówce edukacyjnej),
jest konfiguracja i zarządzanie flotą wielu maszyn, użytkowanych często przez osoby nietechniczne. Powstało wiele
narzędzi służących do ułatwienia tego zadania, wśród których zwrócono uwagę na kilka przykładów:

\begin{itemize}
	\item Microsoft Active Domain jako system do zarządzania już skonfigurowanymi maszynami opartymi o system Microsoft Windows
	\item Ansible jako system do zarządzania maszynami opartymi o systemy z rodziny UNIX
	\item Ubuntu Landscape jako system służący do zarządzania flotą maszyn opartych o system Ubuntu Linux
	\item Microsoft Windows Unattended Install, czyli narzędzie służące do automatycznego konfigurowania instalacji systemu Microsoft Windows
\end{itemize}

\paragraph{}
Każde z tych narzędzi pozwala na zautomatyzowanie jednego z podstawowych kroków w procesie zarządzania i utrzymania
pracowni informatycznej: instalacji systemu/systemów operacyjnych, konfiguracji systemu, aktualizacji i utrzymania systemu.
Pewne przypadki użycia wymagają jednak pewnych cech, które bardzo trudno osiągnąć używając powyższych narzędzi.
Przykładem takiej sytuacji jest resetowanie urządzeń po każdych zajęciach lekcyjnych, zapewniając przy tym, że
każde środowisko na którym pracują uczniowie/studenci jest identyczne. W takiej sytuacji najczęściej wykorzystuje
się maszyny wirtualne, które po zakończeniu zajęć są przywracane do migawki, lub ich obraz dysku 
jest podmieniany na oryginalny. Wymaga to jednak kilku manualnych kroków, które należy wykonać pomiędzy zajęciami.

\paragraph{}
Proponowane rozwiązanie automatyzuje proces dystrybucji obrazów maszyn wirtualnych, instalacji oraz konfiguracji
systemu operacyjnego, pod kontrolą którego będą pracować maszyny wirtualne. Celem tej pracy było:

\begin{itemize}
	\item napisanie programu serwera obrazów maszyn wirtualnych, którego zadaniem jest ich rejestrowanie, przypisywanie oraz dystrybuowanie
	\item stworzenie klienta synchronizującego stan maszyny klienckiej ze stanem obecnym na serwerze, pobierającego obrazy, wyświetlającego ekran wyboru systemy do uruchomienia oraz obsługującego ich uruchmianie poprzez mechanizm QEMU wraz z KVM
	\item przygotowanie konfiguracji dla serwera opartego o system operacyjny Linux:
		\begin{itemize}
			\item do automatycznego instalowania systemu nadzorcy dla maszyn klienckich
			\item do obsługi sieciowej podłączonych maszyn (przydzielanie adresów IP, wskazywanie na serwer konfiguracji)
			\item do zarządzania maszynami klienckimi
		\end{itemize}
	\item wdrożenie rozwiązania w symulowanym środowisku testowym
\end{itemize}

\paragraph{}
Prezentowana praca podzielona została na kilka rozdziałów:

\begin{itemize}
	\item analiza tematu: przybliżenie wykorzystanych technologii, ich charakterystyka, historia i zastosowania
	\item wymagania i narzędzia: jakie są wymagania dla aplikacji, jakie narzędzia zostały wykorzystane do rozwiązania problemu, ich opis oraz uzasadnienie wyboru
	\item specyfikacja zewnętrzna: specyfikacja opisująca całe rozwiązanie z perspektywy użytkowników końcowych, z wyszczególnionymi elementami składowymi rozwiązania
	\item specyfikacja wewnętrzna: specyfikacja opisująca techniczne aspekty rozwiązania, z perspektywy osoby technicznej zaznamiającej się z kodem źródłowym oprogramowania
	\item weryfikacja i walidacja: wyniki testów przeprowadzonych na testowym środowisku wdrożeniowym, ich analiza
	\item podsumowanie i wnioski: prezentacja wniosków wynikających z analizy wyników testów, krytyka proponowanego rozwiązania i propozycje poprawek
\end{itemize}

\paragraph{Wkład pracy autora}
Przedmiotem pracy było napisanie aplikacji kontrolera floty urządzeń, aplikacji klienta zarządzającej systemem nadzorcy,
konfiguracji fizycznego serwera oraz samo jego skonfigurowanie. Wszystkie te zadania zostały zrealizowane, wraz z zakupem maszyny w roli serwera oraz
skonfigurowaniem domowej sieci lokalnej do obsługi rozwiązania.

% \begin{itemize}
% \item wprowadzenie w problem/zagadnienie
% \item osadzenie problemu w dziedzinie
% \item cel pracy
% \item zakres pracy
% \item zwięzła charakterystyka rozdziałów
% \item jednoznaczne określenie wkładu autora, w przypadku prac wieloosobowych – tabela z autorstwem poszczególnych elementów pracy
% \end{itemize}

% TODO
\chapter{Analiza tematu}

\paragraph{}
Praca została podzielona na dwie główne części: obsługę maszyn wirtualnych i ich obrazów, oraz zarządzanie,
instalację i konfigurację systemu zarządcy maszyn wirtualnych. 

\paragraph{}
Istnieje kilka popularnych sposobów synchronizacji i przesyłania plików pomiędzy urządzeniami opartymi o systemy z rodziny Linux.
Wśród nich warto zwrócić uwagę na poniższe rozwiązania:

\begin{itemize}
	\item RSYNC \cite{bib:redhat_rsync}
	\item SFTP \cite{bib:ietf-secsh-filexfer-13}
	\item serwer HTTP serwujący pliki statyczne
\end{itemize}

\paragraph{RSYNC}
RSYNC to narzędzie służące do synchronizacji, kopiowania i przenoszenia plików na maszynach pracujących pod kontrolą systemów z rodziny UNIX.
Podstawą działania aplikacji RSYNC jest architektura klient-serwer, gdzie klient najpierw nawiązuje połączenie z serwerem poprzez
potok, a w przypadku połączenia sieciowego najpierw uruchamia powłokę na maszynie zdalnej, następnie uruchamia proces serwera i tworzy
potok do komunikacji między nimi. Po nawiązaniu połączenia, proces wysyłający dane tworzy listę wszystkich plików do wysłania, wraz z 
informacjami o własności, wielkości plików, trybie, uprawnieniach i czasie ostatniej zmiany. Następnie, każda ze stron transferu
sortuje te listy leksykograficznie, względem ścieżki do bazowego katalogu transferu. W kolejnym kroku tzw. generator iteruje się po liście
plików i sprawdza, czy mogą zostać pominięte (czy data ostatniej zmiany i wielkość nie uległy zmianie, lub, jeżeli została wybrana odpowiednia
flaga, czy sumy kontrolne poszczególnych plików nie uległy zmianie) oraz tworzy brakujące katalogi. Jeżeli plik nie został oznaczony
jako możliwy do pominięcia, jego obecna wersja staje się "plikiem bazowym'', a jej obliczone sumy kontrolne bloków plików są wysyłane do procesu
odbierającego dane. Proces odczytuje tablicę sum kontrolnych bloków, tworzy indeks funkcji skrótu, aby przyspieszyć operacje
wyszukiwania bloków. Następnie plik lokalny jest odczytywany i liczona jest suma kontrolna dla pierwszego bajtu pliku.
Jeżeli wykryta zostanie różnica w sumach kontrolnych, do pierwszego niepasującego bajtu dołaczony zostanie odpowiadający bajt z pliku
wysyłanego, a następnie obliczona zostanie suma kontrolna bloku zaczynającego się w kolejnym bajcie. Jeżeli znalezione zostanie dopasowanie
w tablicy indeksów funkcji skrótów, dany blok jest traktowany jako pasujący i jest pomijany. W ten sposób proces jest w stanie zrekontruować
plik źródłowy. Wszystkie dane z tej analizy wysyłane są do procesu odbierającego, który na ich podstawie odtwarza oryginalny plik.
Mechanizm ,,rolling checksum'' opisany powyżej jest integralną częścią algorytmu RSYNC, który sprawia, że nie ma potrzeby transferu
całych plików, jedynie zmian, które w nich nastąpiły.\cite{bib:rsync-article}\cite{bib:rsync-tech-report}\cite{bib:rsync-thesis}

\paragraph{SFTP}
SFTP (Secure File Transfer Protocol) to bezpieczny protokół przesyłu plików wykorzystujący protokół SSH do uwierzytelnienia oraz
szyfrowania przesyłanych danych. Pierwszym krokiem do przesyłu danych jest nawiązanie połączenia SSH pomiędzy urządzeniami, następnie
serwer SFTP sprawdza dostęp do maszyny klienta poprzez SSH (Secure SHell). Jeżeli test przebiegnie pomyślnie, nawiązywane jest połączenie SFTP, przez
które rozpoczyna się transfer plików. Protokół obsługuje przesył wielowątkowy, gdzie każda operacja transferu ma przypisany unikalny numer
identyfikacyjny, nadawany przez klienta, dzięki czemu serwer może odpowiadać na zapytania klienta asynchronicznie i bez zachowania kolejności.
Aby poprawić wydajność, klient wysyła często wiele zapytań zanim zatrzymuje się i czeka na odpowiedzi.\cite{bib:ssh-article}

\paragraph{SSH}
SSH (Secure SHell) to standard protokołów, który miał w założeniu stanowić bezpieczną alternatywę dla protokołu telnet. 
Do autoryzacji wykorzystuje kryptografię klucz publiczy - klucz prywatny, gdzie w najprostszej postaci
pary kluczy sa generowane automatycznie i służą do zabezpieczenia połączenia sieciowego, natomiast sama autoryzacja
odbywa się za pomocą hasła użytkownika systemu zdalnego.\cite{bib:ssh-rfc} Obecnie najpopularniejszą implementacją protokołu SSH jest OpenSSH, stworzona przez
część członków projektu OpenBSD. Jest wykorzystywana przez większość najpopularniejszych systemów operacyjnych, takich jak
różne dystrybucje Linux, macOS, Microsoft Windows, czy OpenBSD.\cite{bib:openssh-usage}

\paragraph{Serwer HTTP}
Protokół HTTP (HyperText Transfer Protocol) powstał jako część WWW (World Wide Web) i miał służyć do transferu dokumentów hipertekstowych.
Prace nad nim były prowadzone przez Tima Berners-Lee zatrudnionego w CERN (Conseil Européen pour la Recherche Nucléaire) od 1989 roku
(pierwsza propozycja systemu hipertekstowego opartego o Internet),
gdzie implementacja nastąpiła w 1990 roku, by już rok później pojawiły się pierwsze serwery poza organizacją macierzystą twórcy\cite{bib:http-history}.
W 1997 roku powstała pierwsza ustandaryzowana wersja protokołu, HTTP/1.1, która została wykorzystana w tej pracy.\cite{bib:http-rfc} 
HTTP to obecnie bardzo wszechstronne narzędzie, pozwalające obecnie na przesyłanie dowolnych danych poprzez sieć Internet.
Jako protokół jest podstawą współczesnej sieci Web, służy do obustronnego transferu danych pomiędzy serwerami i klientami.
Komunikacja jest rozpoczynana zawsze przez klienta. Tok takiej tranzakcji jest następujący (opis dotyczy wersji HTTP/1.1):

\begin{itemize}
	\item otwarcie połączenia TCP (Transmission Control Protocol) z serwerem
	\item wysłanie zapytania HTTP 
	\item odebranie odpowiedzi HTTP od serwera
	\item zamknięcie połączenia, lub ponowne jego użycie (do wysłania kolejnego zapytania)
\end{itemize}

Wiadomości HTTP (dla wersji HTTP/1.1 i starszych) mają ustandaryzowany format, czytelny dla człowieka i zapisywalny w postaci tekstu.
Format różni się dla zapytań i odpowiedzi, gdzie zapytanie posiada następujące pola\cite{bib:http-overview}:

\begin{itemize}
	\item metoda HTTP: definiuje operację, którą chce przeprowadzić klient. Może to być np. operacja pobrania danych (metoda GET), czy wysłania danych (metoda POST). Standard HTTP/1.1 zawiera poniższe metody\cite{bib:http-methods}:
		\begin{itemize}
			\item CONNECT
			\item DELETE
			\item GET
			\item HEAD
			\item OPTIONS
			\item POST
			\item PUT
			\item TRACE
		\end{itemize}
	\item ścieżka dostępu do danych
	\item wersja protokołu HTTP
	\item opcjonalne nagłówki 
	\item ciało zapytania, dla metod obsługujących przesył danych z klienta do serwera
\end{itemize}

Natomiast struktura odpowiedzi jest następująca\cite{bib:http-overview}:

\begin{itemize}
	\item wersja protokołu HTTP
	\item kod statusu: jeden z kodów HTTP oznaczający czy zapytanie zostało obsłużone oraz jaki był efekt jego obsługi
	\item wiadomość statusu: krótka wiadomość opisująca znaczenie kodu statusu
	\item nagłówki HTTP, podobnie do zapytania
	\item ciało odpowiedzi, jeżeli wymagane
\end{itemize}

Z perspektywy prezentowanego projektu ważną cechą protokołu HTTP jest możliwość przesyłu dowolnych danych w ten sam sposób. Zostało to wykorzystane do
stworzenia serwera, który potrafi przesyłać dane do klientów w formacie JSON (JavaScript Object Notation), czyli tekstowym formacie
opisującym (w tym konkretnym przypadku) konfigurację oraz w formacie binarnym, co jest wykorzystywane do przesyłu obrazów maszyn wirtualnych.
Powyższe rozwiązanie zostało wybrane właśnie z powodu łatwości połączenia części przesyłającej konfigurację z serwera do klientów oraz części
przesyłającej obrazy. W dalszej części pracy opisano dokładną architekturę tego rozwiązania, jej zalety oraz wady.

\paragraph{Maszyny wirtualne}
Maszyna wirtualna to w najprostszym ujęciu programowa implementacja fizycznego urządzenia, która wykonuje zadany program w sposób identyczny
do tego urządzenia. Aplikacja, która to umożliwia jest nazywana nadzorcą (ang. hypervisor). Jej zadaniem jest tłumaczenie zapytań programów
do natywnego sprzętu na zapytania do sprzętu, na którym działa uruchomiona maszyna wirtualna. Istnieje kilka popularnych rodzajów wirtualizacji\cite{bib:virtualization-article}:

\begin{itemize}
	\item pełna wirtualizacja z translacją binarną, rys. \ref{fig:fullvirt-diagram} przedstawia schemat działania takiego systemu
	\item wirtualizacja ze wsparciem sprzętowym, rys. \ref{fig:hwvirt-diagram} przedstawia schemat działania takiego systemu
	\item wirtualizacja wspierana przez system operacyjny i parawirtualizacja, rys. \ref{fig:paravirt-diagram} przedstawia schemat działania takiego systemu
\end{itemize}

\begin{figure}[hb]
\centering
\includegraphics[width=0.8\textwidth]{./pictures/paravirt-diagram.png}
\caption{Diagram przedstawiający schemat działania systemu z parawirtualizacją (za \cite{bib:virtualization-article}, rys. 1.6)}
\label{fig:paravirt-diagram}
\end{figure}

\begin{figure}[hb]
\centering
\includegraphics[width=0.8\textwidth]{./pictures/fullvirt-diagram.png}
\caption{Diagram przedstawiający schemat działania systemu z pełną wirtualizacją (za \cite{bib:virtualization-article}, rys 1.5)}
\label{fig:fullvirt-diagram}
\end{figure}

\begin{figure}[hb]
\centering
\includegraphics[width=0.8\textwidth]{./pictures/hwvirt-diagram.png}
\caption{Diagram przedstawiający schemat działania systemu ze sprzętowym wsparciem wirtualizacji (za \cite{bib:virtualization-article}, rys. 1.7)}
\label{fig:hwvirt-diagram}
\end{figure}
%Rys. \ref{fig:etykieta-rysunku} przestawia …

\paragraph{}
W prezentowanym projekcie wykorzystano model ze sprzętowym wsparciem dla wirtualizacji poprzez KVM (Kernel Virtual Machine) wraz z QEMU (Quick EMUlator) i technologie
Intel VT-d/AMD-V, pod kontrolą systemu operacyjnego Ubuntu Linux w wersji 22.04 LTS.

\paragraph{KVM}
KVM to technologia obsługi akceleratorów sprzętowych wirtualizacji wbudowana w systemy z rodziny Linux oparte o jądro w wersji co najmniej 2.6.20,
a jej część przeznaczona dla użytkownika została wbudowana w narzędzie QEMU w wersji 1.3.\cite{bib:kvm-main} 

\paragraph{Intel VT-d/AMD-V}
Technologie Intel VT-d/AMD-V to zbiór rozwiązań technicznych zaimplementowanych podczas tworzenia procesora oraz chipsetu płyty głównej,
które wspierają i ułatwiają używanie maszyn wirtualnych. Sposób działania został opisany na podstawie technologii Intel VT-d.\cite{bib:intel-vt-specs}
Wsparcie dla wirtualizacji zostało tam osiągnięte poprzez zapewnienie:

\begin{itemize}
	\item zestawu rozszerzeń dla procesora (nazwanych Intel VMX, Virtual Machine eXtensions)
	\item wirtualizacji urządzeń We/Wy (Wejścia/Wyjścia)
	\item wirtualizacji dostępu do pamięci
\end{itemize}

Wirtualizacja dostępu do pamięci jest zapewniana poprzez mechanizm MMU (Memory Management Unit). Jest to układ tłumaczący adresy logiczne
pamięci operacyjnej na jej fizyczne adresy i zapewniający ochronę dostępu procesów do pamięci. 

Wirtualizacja urządzeń We/Wy jest realizowana poprzez mechanizm IOMMU (Input/Output Memory Management Unit). Działa on na analogicznej zasadzie co MMU, zapewniając kontrolę
oraz tłumaczenie adresów logicznych urządzeń do ich adresów fizycznych.\cite{bib:amd64-specs} Pozwala to na przekierowanie 
urządzenia bezpośrednio pod kontrolę systemu operacyjnego uruchomionego w maszynie wirtualnej, pomijając sterownik systemu zarządcy.
Technologia ta może zostać wykorzystana do przekazania w taki sposób urządzeń wymagających bardzo niskich opóźnień i dużej przepustowości,
na przykład kart graficznych, lub kart sieciowych. Wtedy pełną kontrolę nad sprzętem otrzymuje system operacyjny gościa w maszynie
wirtualnej, a narzut wirtualizacji na wydajność jest zminimalizowany.

\paragraph{DHCP}
Protokół DHCP (Dynamic Host Configuration Protocol) odpowiada za automatyczne przypisywanie adresów IP oraz wysyłanie konfiguracji
sieciowej do urządzeń. Jego założeniem była także iteroperatywność z już wtedy istniejącym protokołem BOOTP (BOOTstrap Protocol), przez co
pojedyncze paczki danych (nazwane wiadomościami) są te same dla obu protokołów (z kilkoma odstępstwami).\cite{bib:dhcp-rfc}
Format wiadomości DHCP jest następujący:\cite{bib:dhcp-rfc}

\begin{itemize}
	\item OP (1 bajt): typ wiadomości
	\item HTYPE (1 bajt): typ adresu karty sieciowej
	\item HLEN (1 bajt): długość adresu karty sieciowej
	\item HOPS (1 bajt): ustawiane przez klienta na 0 (zero); używane przez agentów pośredniczących
	\item XID (4 bajty): numer identyfikacyjny (ID) tranzakcji; używany do rozpoznania wiadomości przeznaczonych dla konkretnego klienta
	\item SECS (2 bajty): liczba sekund od rozpoczęcia procesu odnawiania lub nabywania adresu; ustawiane przez klienta
	\item FLAGS (2 bajty): flagi
	\item CIADDR (4 bajty): adres IP klienta; uzupełniany tylko, jeżeli klient może odpowiedzieć na zapytanie ARP (Address Resolution Protocol) i jest w stanie BOUND, RENEW, lub REBINDING
	\item YIADDR (4 bajty): ,,twój'' (klienta) adres IP
	\item SIADDR (4 bajty): adres następnego serwera do użycia podczas pobierania
	\item GIADDR (4 bajty): adres agenta pośredniczącego
	\item CHADDR (16 bajtów): adres fizyczny klienta
	\item SNAME (64 bajty): (opcjonalnie) nazwa serwera, łańcuch znaków zakończony zerem (0)
	\item FILE (28 bajtów): nazwa pliku uruchomieniowego, łańcuch znaków zakończony zerem (0)
	\item OPTIONS (zmienna długość): opcjonalne parametry
\end{itemize}

Zdefiniowano następujące wiadomości w protokole DHCP:\cite{bib:dhcp-rfc}

\begin{itemize}
	\item DHCPDISCOVER -  Klient wysyła pakiet rozgłoszeniowy, aby zlokalizować dostępne serwery
	\item DHCPOFFER    -  Serwer odpowiada klientowi na zapytanie DHCPDISCOVER z proponowaną konfiguracją
	\item DHCPREQUEST  -  Klient odpowiada serwerowi (a) żądając oferowanych parametrów od jednego serwera i ignorując pozostałe, (b) potwierdzając prawidłowość otrzymanej wcześniej konfiguracji, lub (c) przedłużając dzierżawę adresu IP
	\item DHCPACK      -  Serwer odpowiada klientowi parametrami konfiguracji, wraz z przyznanym adresem IP
	\item DHCPNAK      -  Serwer odpowiada klientowi zaznaczając, że konfiguracja żądana przez klienta jest nieprawidłowa, lub dzierżawa adresu wygasła
	\item DHCPDECLINE  -  Klient odpowiada serwerowi, że dany adres sieciowy jest już w użytku
	\item DHCPRELEASE  -  Klient odpowiada serwerowi, zwalniając dany adres sieciowy i anulując bieżącą dzierżawę
	\item DHCPINFORM   -  Klient wysyła zapytanie serwerowi, prosząc o konfigurację lokalną; adres sieciowy skonfigurowany zewnętrznie
\end{itemize}

Proces konfiguracji w takiej sieci jest następujący\cite{bib:dhcp-rfc}:

\begin{itemize}
	\item klient wysyła zapytanie \texttt{DHCPDISCOVER}
	\item serwer wysyła klientowi proponowaną konfigurację poprzez wiadomość \texttt{DHCPOFFER}
	\item klient żąda zadanej konfiguracji poprzez wiadomość \texttt{DHCPREQUEST}
	\item serwer odpowiada klientowi wiadomością \texttt{DHCPACK}, jeżeli żądana konfiguracja jest poprawna, w przeciwnym przypadku odpowiada \texttt{DCHPNAK}
	\item przy odłączaniu od sieci, klient wysyła wiadomość \texttt{DHCPRELEASE}, zwalniając zajmowany adres sieciowy
\end{itemize}

\paragraph{TFTP}
TFTP (Trivial File Transfer Protocol) to nieskomplikowany protokół przesyłu plików. Jego jedynym zadaniem jest 
odczyt pliku po stronie serwera i przesłanie go do klienta. Nie obsługuje listowania plików, ani uwierzytelniania.\cite{bib:tftp-rfc}

Protokół obsługuje następujące tryby przesyłu danych\cite{bib:tftp-rfc}:

\begin{itemize}
	\item \texttt{NETASCII}, czyli zmodyfikowana forma formatu \texttt{ASCII}, rozszerzona do długości 8 bitów i zawierająca dodatkowe znaki kontrolne
	\item \texttt{OCTET}, czyli format przesyłu surowych bajtów danych
	\item \texttt{MAIL}, uznany za przestarzały w specyfikacji RFC1350\cite{bib:tftp-rfc}
\end{itemize}

Proces transferu plików jest następujący\cite{bib:tftp-rfc}:

\begin{itemize}
	\item klient wysyła zapytanie RRQ (read request/żądanie odczytu), lub WRQ (write request/żądanie zapisu), zawierające nazwę pliku i tryb transferu do serwera na port 69
	\item serwer odpowiada pakietem OPTIONS ACK (jeżeli były użyte) i pakietem ACK w przypadku zapytania WRQ; w przypadku zapytania RRQ odpowiedź to od razu pierwszy pakiet żądanych danych
	\item maszyna będąca źródłem pliku wysyła go w ponumerowanych segmentach (domyślnie o wielkości 512 bajtów); maszyna odbierająca na każdy segment odpowiada pakietem ACK
	\item ostatni segment jest rozpoznawany po wielkości, która jest mniejsza od poprzednich (domyslnie musi mieścić się w przedziale od 0 bajtów do 511 bajtów)
	\item jeżeli odpowiedź ACK dla danego segmentu nigdy nie została otrzymana przez maszynę wysyłającą, po upływie określonego czasu (timeout) segment jest retransmitowany
\end{itemize}

\paragraph{PXE}
PXE (Preboot eXecution Environment) to specyfikacja ustandaryzowanego środowiska pozwalającego na uruchamianie oprogramowania
poprzez sieć. Rozwiązanie takie pracuje w architekturze klient-serwer, gdzie od klienta wymagane jest jedynie posiadanie
odpowiedniej karty sieciowej (wspierającej to rozwiązanie) oraz wsparcie w oprogramowaniu inicjalizującym maszyny, odpowiedzialnym
za uruchamianie oprogramowania (na przykład BIOS/UEFI dla maszyn o architekturze X86). Część serwera jest zbiorem już wcześniej istniejących
rozwiązań, składającym się z serwera DHCP oraz serwera TFTP. \cite{bib:pxe-specs}

Proces uruchamiania składa się z następujących kroków\cite{bib:pxe-specs}:

\begin{itemize}
	\item wysłanie zapytania \texttt{DHCPDISCOVER} w trybie BROADCAST przez klienta
	\item serwer DHCP odpowiada poprzez wiadomość \texttt{DHCPOFFER}; jeżeli serwer DHCP nie implementuje obsługi PXE, wysyła poprawną wiadomość nie zawierającą informacji o lokalizacji plików potrzebnych do uruchomienia minimalnego systemu, a maszyna klienta nie uruchamia się poprzez PXE. W przeciwnym przypadku, serwer DHCP poza zwykłymi informacjami przesyłanymi we wiadomości \texttt{DHCPOFFER} dodaje także informacje o lokalizacji serwera TFTP, gdzie znajdują się pliki potrzebne do uruchomienia minimalnego środowiska uruchomienowego, oraz o nazwach tych plików
	\item klient PXE konfiguruje się danymi przesłanymi przez serwer DHCP oraz pobiera pliki uruchomieniowe do pamięci RAM (Random Access Memory); uruchamia otrzymane pliki
	\item minimalne środowisko uruchomieniowe powinno pobrać pełen obraz instalacyjny lub obraz systemu do uruchomienia i obsłużyć jego urchomienie/instalację; ten krok najczęściej jest wykonywany poprzez bardziej skomplikowane i niezawodne protokoły, takie jak HTTP, lub NFS
\end{itemize}

Jako minimalne środowisko uruchomieniowe wykorzystuje się często zestaw jądra Linux oraz prostego obrazu initrd, które mają za zadanie
pobrać i uruchomić instalator pełnego systemu operacyjnego.

\paragraph{WakeOnLAN (WOL)}
WakeOnLAN (w skrócie WOL) to technologia pozwalająca na zdalne uruchomienie urządzenia przez przesłanie specjalnego pakietu w sieci LAN (Local Area Network) poprzez adres rozgłoszeniowy.
Pakiet ten składa się z 6 bajtów wypełnionych jedynkami (w zapisie szesnastkowym: FF FF FF FF FF FF) oraz powtórzonego 16 razy adresu MAC urządzenia, które powinno zostać wzbudzone.
Aby maszyna potrafiła zinterpretować taki pakiet, wymagane jest wsparcie dla tej technologii w oprogramowaniu karty sieciowej oraz płyty głównej urządzenia.\cite{bib:wol-specs-amd}

\paragraph{Rozwiązania zarządzające flotą urządzeń klienckich}
Istnieje wiele rozwiązań mających na celu automatyzację instalacji i zarządzanie flotą komputerów w pracowniach informatycznych/biurach/itp.
Zapewniają one narzędzia do skonfigurowania automatycznej instalacji systemu i zdalnego nim zarządzania (między innymi dodawania, usuwania użytkowników, czy instalacji oprogramowania).

\paragraph{Microsoft Windows}
Dla systemów z rodziny Microsoft Windows zbiorem narzędzi do zarządzania instalacją systemu jest Windows Assessment and Deployment Kit (ADK).
Zawiera on pełny zestaw aplikacji służący do prekonfiguracji instalacji, czy stworzenia minimalnego środowiska uruchomieniowego dla PXE.
Zawarte w nim narzędzie WISM (Windows System Image Manager) pozwala utworzyć pliki odpowiedzi dla instalatora systemu, automatyzujące proces instalacji.
Z kolei narzędzie DISM (Deployment Image Servicing and Management) daje możliwość modyfikacji elementów obrazu systemu, na przykład pozwalając na wbudowanie zewnetrznych aplikacji bezpośrednio w obraz instalatora.\cite{bib:adk-docs}

Po zainstalowaniu, Microsoft zaleca dla takiego przypadku użycia przyłączenie maszyny do usługi Active Directory (AD).
Jest to zestaw narzędzi wbudowanych w system Microsoft Windows Server pozwalający na zdalne, scentralizowane zarządzanie 
wieloma klientami opartymi o system Microsoft Windows.\cite{bib:ad-docs} 

\paragraph{Linux}
Z kolei dla systemów z rodziny Linux podobny efekt można uzyskać poprzez kombinację kilku narzędzi. Do automatyzacji procesu instalacji powstało narzędzie
cloud-init, zaprezentowane przez firmę Canonical. Pozwala ono na stworzenie ,,przepisu'' na podstawie którego instalator systemu między innymi
konfiguruje parametry, instaluje pakiety, tworzy użytkowników, czy importuje klucze SSH. W połączeniu z serwerem PXE możliwe jest
w ten sposób instalowanie tak samo skonfigurowanego systemu na wielu maszynach, w sposób w pełni zautomatyzowany.\cite{bib:cloudinit-docs}

Z kolei do zarządzania flotą urządzeń można wykorzystać narzędzia takie jak Ansible, Chef, czy Puppet. Umożliwiają wykonywanie skryptów
na wielu maszynach w sposób zautomatyzowany. Pozwalają one na zarządzanie użytkownikami, aplikacjami, a nawet potrafią synchronizować pliki.
Chef oraz Puppet używają procesu agenta, który odpytuje serwer konfiguracji i aplikuje wykryte zmiany. Ansible natomiast wykorzystuje
podejście, w którym to maszyna nadzorcy wysyła pierwsza konfigurację na maszyny zarządzane. Nie wymaga także instalacji dodatkowego
oprogramowania na maszynie zarządzanej, wystarczy jedynie uruchomiony serwer SSH oraz zainstalowany interpreter języka Python.

%\begin{itemize}
%\item sformułowanie problemu
%\item osadzenie tematu w kontekście aktualnego stanu wiedzy (\ang{state of the art}) o poruszanym problemie
%\item  studia literaturowe \cite{bib:artykul,bib:ksiazka,bib:konferencja,bib:internet} -  opis znanych rozwiązań (także opisanych naukowo, jeżeli problem jest poruszany w publikacjach naukowych), algorytmów, 
%\end{itemize}
% 
% 
% Wzory  
% \begin{align}
% y = \frac{\partial x}{\partial t}
% \end{align}
% jak i pojedyncze symbole $x$ i $y$  składa się w trybie matematycznym.


% TODO
\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{}
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{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:

\begin{itemize}
	\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 (JSON Web Token), 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
%
%\begin{figure}
%\centering
%\includegraphics[width=0.5\textwidth]{./politechnika_sl_logo_bw_pion_pl.pdf}
%\caption{Podpis rysunku zawsze pod rysunkiem.}
%\label{fig:etykieta-rysunku}
%\end{figure}
%Rys. \ref{fig:etykieta-rysunku} przestawia …
%%%%%%%%%%%%%%%%%%%%%
%
%%%%%%%%%%%%%%%%%%%%%
%% WIELE RYSUNKÓW 
%
%\begin{figure}
%\centering
%\begin{subfigure}{0.4\textwidth}
%    \includegraphics[width=\textwidth]{./politechnika_sl_logo_bw_pion_pl.pdf}
%    \caption{Lewy górny rysunek.}
%    \label{fig:lewy-gorny}
%\end{subfigure}
%\hfill
%\begin{subfigure}{0.4\textwidth}
%    \includegraphics[width=\textwidth]{./politechnika_sl_logo_bw_pion_pl.pdf}
%    \caption{Prawy górny rysunek.}
%    \label{fig:prawy-gorny}
%\end{subfigure}
%
%\begin{subfigure}{0.4\textwidth}
%    \includegraphics[width=\textwidth]{./politechnika_sl_logo_bw_pion_pl.pdf}
%    \caption{Lewy dolny rysunek.}
%    \label{fig:lewy-dolny}
%\end{subfigure}
%\hfill
%\begin{subfigure}{0.4\textwidth}
%    \includegraphics[width=\textwidth]{./politechnika_sl_logo_bw_pion_pl.pdf}
%    \caption{Prawy dolny rysunek.}
%    \label{fig:prawy-dolny}
%\end{subfigure}
%        
%\caption{Wspólny podpis kilku rysunków.}
%\label{fig:wiele-rysunkow}
%\end{figure}
%Rys. \ref{fig:wiele-rysunkow} przestawia wiele ważnych informacji, np. rys. \ref{fig:prawy-gorny} jest na prawo u góry.
%%%%%%%%%%%%%%%%%%%%%


 
% \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{Specyfikacja wewnętrzna}
\label{ch:specyfikacja-wewnetrzna}

\paragraph{Idea rozwiązania}
Zamysł proponowanego rozwiązania jest dość prosty i opiera się na kilku elementach:

\begin{itemize}
	\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}

\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}

\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{}
Serwer wystawia następujące punkty końcowe (ang. endpoints):

\begin{itemize}
	\item GET \texttt{/} - przedstawia podstawowe dane o serwerze: nazwę, wersję oraz nazwę hosta, przykład odpowiedzi podano w listingu \ref{fig:response-main}
	\item POST \texttt{/login} - pozwala na zalogowanie się poprzez wysłanie nazwy użytkownika i hasła, zwraca token JWT służący do autoryzacji, id użytkownika oraz jego nazwę jako potwierdzenie, przykład ciała zapytania logowania pokazano w listingu \ref{fig:request-login}, przykłady możliwych odpowiedzi pokazano w listingu \ref{fig:response-login}
	\item POST \texttt{/clients} - pozwala na rejestrację klienta, przykład wymaganego ciała zapytania pokazano w listingu \ref{fig:response-register}
	\item PUT \texttt{/clients} - pozwala na modyfikację danych o już zarejestrowanym kliencie, zapytania i odpowiedzi są takie same, jak dla żądań rejestracji klientów
	\item GET \texttt{/clients/adres\_mac} - pozwala na pobranie danych o zadanym kliencie z serwera, możliwe odpowiedzi pokazano w listingu \ref{fig:response-client-data-get}
	\item GET \texttt{/clients/adres\_mac/vms} - pozwala na pobranie listy numerów id obrazów przypisanych do klienta o podanym adresie MAC, możliwe odpowiedzi ukazano w listingu \ref{fig:response-list-vms}
	\item GET \texttt{/images/id\_obrazu} - pozwala na pobranie danych o obrazie o zadanym numerze id, możliwe odpowiedzi pokazano w listingu \ref{fig:response-get-image-data}
	\item GET \texttt{/images/id\_obrazu/download} - pozwala na pobranie obrazu o zadanym numerze id
\end{itemize}

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
HTTP200:
{
	"server_name": "VALHALLA",
	"server_version": "v0.0.1",
	"host": "127.0.0.1"
}
	\end{lstlisting}
	\caption{Przykład możliwej odpowiedzi na zapytanie pod punkt końcowy /}
	\label{fig:response-main}
\end{figure}

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
		{
			"username": "user",
			"password": "sekret_password"
		}
	\end{lstlisting}
	\caption{Przykład prawidłowego ciała żądania logowania}
	\label{fig:request-login}
\end{figure}


\begin{figure}[hb]
	\centering
	\begin{lstlisting}
HTTP202 (poprawne dane):
{
    "token": "xxxxxxxxx",
    "user_id": "1",
    "username": "user"
}
HTTP401 (niepoprawne dane):
{
    "data": null,
    "error": "Auth error",
    "message": "Invalid login data"
}
	\end{lstlisting}
	\caption{Możliwe odpowiedzi na żądanie logowania od serwera}
	\label{fig:response-login}
\end{figure}

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
Poprawne zapytanie:
{
    "mac_address": "00:00:00:00:00:00:00:62",
    "ip_address": "192.168.1.12",
    "hostname": "test",
    "client_version": "v0.0.1alpha",
    "vm_list_on_machine": []
}
Odpowiedz: HTTP201
{
    "success": true
}
Niepoprawne zapytanie:
{
    "mac_address": "00:00:00:00:00:00:00:62",
    "ip_address": "192.168.1.12",
    "client_version": "v0.0.1alpha",
    "vm_list_on_machine": []
}
Odpowiedz: HTTP400
{
    "data": null,
    "error": "'hostname'",
    "message": "Internal server error"
}
	\end{lstlisting}
	\caption{Możliwe zapytania i odpowiedzi serwera na żądanie rejestracji klienta}
	\label{fig:response-register}
\end{figure}

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
HTTP200 (istniejacy adres MAC):
{
    "client_version": "v0.0.1alpha",
    "hostname": "test",
    "ip_address": "192.168.1.12",
    "mac_address": "00:00:00:00:00:00:00:62"
}
HTTP404 (nieistniejacy adres MAC):
{
    "data": null,
    "error": null,
    "message": "Client not found in database"
}
	\end{lstlisting}
	\caption{Możliwe odpowiedzi serwera na zapytanie o dane zadanego klienta}
	\label{fig:response-client-data-get}
\end{figure}

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
HTTP200 (istniejacy adres MAC):
[
    1
]
HTTP404 (nieistniejacy adres MAC):
{
    "data": null,
    "error": null,
    "message": "Client not found in database"
}
	\end{lstlisting}
	\caption{Mozliwe odpowiedzi serwera na zapytanie o obrazy przypisane do zadanego hosta}
	\label{fig:response-list-vms}
\end{figure}

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
HTTP200 (instniejacy obraz):
{
    "image_file": "ubuntu.qcow2",
    "image_hash": "dbdc4d7f10511387ef89ffc503080b92",
    "image_id": "1",
    "image_name": "ubuntu22",
    "image_name_version_combo": "ubuntu22@v1.0.0",
    "image_version": "v1.0.0"
}
HTTP404 (nieistniejacy obraz):
{
    "data": null,
    "error": null,
    "message": "Image not found in database"
}
	\end{lstlisting}
	\caption{Możliwe odpowiedzi serwera na zapytanie o dane zadanego obrazu}
	\label{fig:response-get-image-data}
\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{}
Sprawdzenie danych o maszynie odbywa się w kilku krokach: aby pobrać adres IP maszyny, program nawiązuje połączenie z serwerem
DNS Google (adres IP: \texttt{8.8.8.8}), a następnie sprawdza nazwę gniazda (ang. socket), które połączyło się z siecią.
Adres MAC jest sprawdzany przez bibliotekę \texttt{get\_mac\_address}, liczba rdzeni procesora przez bibliotekę \texttt{os}, a
ilość pamięci RAM poprzez bibliotekę \texttt{psutil} (bibiloteka zwraca liczbę bajtów pamięci, a reszta aplikacji wymaga liczby gigabajtów, stąd wymagana była konwersja).
Implementacja tych funkcjonalności, wraz z odczytem i parsowaniem plików konfiguracyjnych, znajduje się w klasie \texttt{MachineData}

\paragraph{}
Obsługa komunikacji z serwerem została umieszczona w klasie \texttt{ValhallaServer}. Za pomocą biblioteki \texttt{requests}
wysyłane są zapytania do serwera. Jeżeli wygaśnie token JWT, wysyłane jest zapytanie służące do zalogowania się do systemu,
a następnie ponawiane jest poprzednie zapytanie. Dane z serwera są przekazywane w formacie JSON. 
Zaraz po uruchomieniu aplikacji klienckiej wysyłane jest żądanie rejestracji maszyny, lub, jeżeli maszyna już jest zarejestrowana,
następuje aktualizacja danych o maszynie. Następnie pobierana jest lista obrazów przypisanych do konkretnej maszyny, a same obrazy są pobierane.
Wszystkie te operacje są obsługiwane przez klasę \texttt{ValhallaServer}.

\paragraph{}
Obsługa uruchamiania maszyn wirtualnych sprowadza się do skopiowania pliku-wzorca skryptu uruchamiającego maszynę wirtualną QEMU do odpowiedniego
katalogu, podmianie tymczasowych wartości liczby rdzeni, ilości pamięci RAM i ścieżki do obrazu dysku maszyny na prawidłowe wartości
wyznaczone przez program w klasie \texttt{MachineData} oraz na podstawie danych obrazów pobranych z serwera,
nadaniu odpowiednich uprawnień dla pliku skryptu (bit wykonywalności - execute) oraz na uruchomieniu skryptu i zablokowaniu wykonywania aplikacji.
Po wyjściu z maszyny wirtualnej, ekran wyboru znów się uruchamia i znów pozwala na wybór maszyny do uruchomienia.

\paragraph{Pliki konfiguracyjne PXE}
Najważniejszy fragment pliku konfiguracyjnego serwera DHCP zawarto w listingu \ref{fig:config-dhcp}. Ustawia on wskaźnik na serwer TFTP serwujący
pliki wymagane do uruchomienia środowiska instalacyjnego.

Z kolei w listingu \ref{fig:config-grub} zawarto plik \texttt{grub.cfg}, który konfiguruje ekran wyboru instalatora oraz obsługuje uruchomienie
minimalistycznego jądra systemu Linux, uruchamiającego pełny instalator systemu.

W listingu \ref{fig:config-apache} ukazano konfigurację serwera Apache2, który serwuje obrazy \texttt{.iso} instalatorów.

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
allow bootp;
allow booting;
# PXE/iPXE BOOT CONFIGURATION FOR VALHALLA SERVER
next-server 192.168.1.25;
filename "bootx64.efi";
	\end{lstlisting}
	\caption{Fragment konfiguracji serwera DHCP}
	\label{fig:config-dhcp}
\end{figure}
		
\begin{figure}[hb]
	\centering
	\begin{lstlisting}
set default="0"
set timeout=-30

if loadfont unicode ; then
  set gfxmode=auto
  set locale_dir=\$prefix/locale
  set lang=en_US
fi
terminal_output gfxterm

set menu_color_normal=white/black
set menu_color_highlight=black/light-gray
if background_color 44,0,30; then
  clear
fi

function gfxmode {
		set gfxpayload="\${1}"
		if [ "\${1}" = "keep" ]; then
				set vt_handoff=vt.handoff=7
		else
				set vt_handoff=
		fi
}

set linux_gfx_mode=keep

export linux_gfx_mode

menuentry 'Install Ubuntu 22.04' {
		gfxmode \$linux_gfx_mode
		linux vmlinuz  ip=dhcp  url=http://192.168.1.25/images/ubuntu22/ubuntu.iso autoinstall ds=nocloud-net\;s=http://192.168.1.25/ks/ cloud-config-url=/dev/null fsck.mode=skip
		initrd initrd
}
	\end{lstlisting}
	\caption{Plik konfiguracyjny \texttt{grub.cfg}}
	\label{fig:config-grub}
\end{figure}

\begin{figure}[hb]
	\centering
	\begin{lstlisting}
<VirtualHost 192.168.1.25:80>
	ServerAdmin root@192.168.1.25
	DocumentRoot /
	ServerName pxe-ks.nixenos.ovh
	ErrorLog \${APACHE_LOG_DIR}/ks-server.example.com-error_log
	CustomLog \${APACHE_LOG_DIR}/ks-server.example.com-access_log common
	<Directory /ks>
		Options Indexes MultiViews
		AllowOverride All
		Require all granted
	</Directory>
	<Directory /images>
		Options Indexes MultiViews
		AllowOverride All
		Require all granted
	</Directory>
</VirtualHost>
	\end{lstlisting}
	\caption{Fragment konfiguracji serwera Apache2}
	\label{fig:config-apache}
\end{figure}

% 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.

Do pomiaru czasu wykorzystano narzędzie \texttt{time}, dostępne w większości systemów wywodzących się z rodziny UNIX. 

W ramach trzeciej fazy testów, poddano ocenie wydajność i odczucia płynące z używania maszyny wirtualnej. 

\paragraph{Pomiary czasu}
Pomiary czasu, w jakim urządzenie przeprowadzało instalację, powtórzono dziesięciokrotnie. Wyniki zostały przedstawione w tabeli \ref{id:tab:czas-konfiguracja}.

Pomiary czasu pobierania obrazów także wykonano dziesięciokrotnie, a wyniki zamieszczono w tabeli \ref{id:tab:czas-pobieranie}.

Zauważono, że najdłuższym procesem jest ładowanie obrazu do pamięci serwera, samo jego przesyłanie trwa od 15 do 20\% zmierzonego czasu.

\paragraph{Wykryte błędy}
Podczas testów wykryto kilka błędów. Pierwszym z nich było błędne ustawianie uprawnień pliku skryptu uruchamiającego
maszynę wirtualną. Kolejny z nich dotyczył błędu w konfiguracji serwera PXE, który uniemożliwiał uruchomienie instalatora.
Po zmianie konfiguracji tak, by podstawowe środowisko uruchomieniowe korzystało z serwera HTTP do pobierania obrazów
\texttt{.iso}, uruchamianie instalatora działało prawidłowo.

\paragraph{Wyniki badań użytkowych}
System uruchamiany poprzez maszynę wirtualną działa sprawnie i możliwe jest korzystanie z niego.
Oczywiście wydajność, szczególnie graficzna, pozostawia wiele do życzenia. Problemy związane z niewystarczającą mocą obliczeniową
do wirtualizacji karty graficznej były najbardziej widoczne podczas korzystania z przeglądarki internetowej Mozilla Firefox, gdzie
przeglądanie stron WWW było możliwe, lecz wydajność przy otwartych 5-6 kartach znacząco malała i system stawał się niezdatny do użycia.

% \begin{itemize}
% \item sposób testowania w ramach pracy (np. odniesienie do modelu V)
% \item organizacja eksperymentów
% \item przypadki testowe zakres testowania (pełny/niepełny)
% \item wykryte i usunięte błędy
% \item opcjonalnie wyniki badań eksperymentalnych
% \end{itemize}



\begin{table}[hb]
\centering
\caption{Wyniki pomiaru czasu pobierania obrazu maszyny wirtualnej}
\label{id:tab:czas-pobieranie}
\begin{tabular}{|l|l|}
	\hline
	\textbf{Numer pomiaru} & \textbf{Zmierzony czas} \\ \hline
	1                      & 4min 40.885s            \\ \hline
	2                      & 4min 59.926s            \\ \hline
	3                      & 5min 1.590s             \\ \hline
	4                      & 5min 11.377s            \\ \hline
	5                      & 5min 5.292s             \\ \hline
	6                      & 4min 59.955s            \\ \hline
	7                      & 5min 2.235s             \\ \hline
	8                      & 4min 58.982s            \\ \hline
	9                      & 5min 3.758s             \\ \hline
	10                     & 5min 1.214s             \\ \hline
	\end{tabular}
\end{table}  

\begin{table}[hb]
\centering
\caption{Wyniki pomiaru czasu konfiguracji systemu zarządcy klienta}
\label{id:tab:czas-konfiguracja}
\begin{tabular}{|l|l|}
	\hline
	\textbf{Numer pomiaru} & \textbf{Zmierzony czas} \\ \hline
	1                      & 15min 48.290s            \\ \hline
	2                      & 13min 36.530s            \\ \hline
	3                      & 10min 40.210s             \\ \hline
	4                      & 10min 15.700s            \\ \hline
	5                      & 10min 46.600s             \\ \hline
	6                      & 9min 36.510s            \\ \hline
	7                      & 9min 06.420s             \\ \hline
	8                      & 9min 14.190s            \\ \hline
	9                      & 9min 15.530s             \\ \hline
	10                     & 10min 12.950s             \\ \hline
	\end{tabular}
\end{table}  


% TODO
\chapter{Podsumowanie i wnioski}
% \begin{itemize}
% \item uzyskane wyniki w świetle postawionych celów i zdefiniowanych wyżej wymagań
% \item kierunki ewentualnych danych prac (rozbudowa funkcjonalna …)
% \item problemy napotkane w trakcie pracy
% \end{itemize}

\paragraph{}
Uzyskano prawie pełną automatyzację procesu instalacji systemu nadzorcy. Administrator musi wykonać jedynie 4 manualne kroki:
dodanie adresów MAC obsługiwanych maszyn do konfiguracji serwera DHCP i konfiguracji skryptów Ansible, wywołanie komendy wysyłającej ,,magic packet'' do
wyznaczonych urządzeń, potwierdzenie instalacji na każdym z urządzeń oraz wywołanie skryptu Ansible do konfiguracji urządzeń.

Dzięki wykorzystaniu QEMU udało się zapewnić użycie maszyn wirtualnych oraz łatwość tworzenia własnych obrazów dla nich. Osiągnięto
także ,,bezstanowość'', maszyny wirtualne po restarcie wracają do swojego pierwotnego stanu sprzed wszsytkich zmian wprowadzonych
przez ostatniego użytkownika.

Użycie PXE, cloud-init oraz Ansible jako systemu automatyzującego instalację systemu nadzorcy pozwoliło na zapewnienie
modularności i możliwości wbudowania rozwiązania w już istniejącą architekturę sieciową. 

\paragraph{}
Niestety wydajność systemu zarządzania obrazami maszyn nie jest satysfakcjonująca. Największym problemem obecnego rozwiązania jest
konieczność załadowania całego wysyłanego pliku do pamięci aplikacji, przez co wydajność jest mocno ograniczona. Dobrym rozwiązaniem tego
problemu byłoby zintegrowanie serwera aplikacji z serwerem Apache2, lub Nginx, gdzie to dedykowany serwer HTTP wysyłałby duże pliki,
a serwer zarządzający obsługiwałby tylko przechowywanie danych. Ciekawym rozwiązaniem tego problemu byłoby też użycie narzędzia rsync,
którego zaawansowane wykrywanie różnic w plikach i podmiana jedynie tych właśnie róznic na pewno znacząco przyspieszyłoby
działanie serwera obrazów. Kolejnym problemem jest kwestia bezpieczeństwa. Aby możliwe było pełne zautomatyzowanie procesu
zdecydowano się na użycie tylko jednego użytkownika dla wszystkich klientów. Jest to duże ryzyko ze względów bezpieczeństwa,
ponieważ potencjalny atakujący może wtedy odczytać adresy MAC wszystkich urządzeń i podszywać się pod nie. 

\paragraph{}
Podobnie jak w przypadku serwera, wydajność systemu w maszynach wirtualnych nie jest satysfakcjonująca. Największym problemem jest
wydajność graficzna. Rozwiązaniem tego problemu byłoby wprowadzenie mechanizmu przekazywania kontroli nad kartą graficzną
systemowi gościa maszyny wirtualnej. Aby takie podejście było możliwe w przypadku posiadania tylko jednej karty graficznej,
wymagane byłoby jej wcześniejsze odpięcie od systemu zarządcy. Istnieje kilka projektów\cite{bib:joe-knock-git}, które wykorzystują mechanizm
,,zaczepów'' (ang. hooks) do odłączania urządzeń PCI przy uruchamianiu maszyny wirtualnej i podpinania ich z powrotem do systemu
zarządcy po wyłączeniu maszyny wirtualnej. Jednak to rozwiązanie wymaga skomplikowanej konfiguracji na maszynach klienckich,
między innymi wybrania odpowiednich urządzeń PCI do przekazania do maszyny wirtualnej, gdzie adresy tych urządzeń będą różne
na każdej z maszyn, a także ta konfiguracja byłaby różna dla każdego typu urządzeń. Napisanie programu, który w dynamiczny sposób
tworzyłby odpowiednie pliki konfiguracyjne, byłoby na pewno skomplikowane, ale możliwe. 

\paragraph{}
Potencjalnym kierunkiem rozwoju tej aplikacji byłoby przeprojektowanie metody synchronizacji obrazów. Optymalną opcją wydaje się
użycie narzędzia rsync, aby zapewnić inkrementalne aktualizacje obrazów, bez potrzeby pobierania całości. Sporym ułatwieniem
pracy dla administratora byłoby także przygotowanie graficznego interfejsu użytkownika do zarządzania serwerem.
Po stronie klienta
dobrym torem rozwoju byłoby opracowanie metody na przekazywanie kontroli nad kartą graficzną systemowi gościa w sposób w pełni
zautomatyzowany. Ważnym krokiem byłoby także dopracowanie interfejsu użytkownika.

\paragraph{}
Powyżej przedstawione propozycje rozwoju są tylko sugestią, ponieważ architektura aplikacji pozwala na łatwą integrację z innymi
rozwiązaniami automatyzującymi. Dzięki temu przedstawiony projekt jest silnie rozwojowy, a przez użycie rozwiązań na licencjach
Wolnego Oprogramowania możliwe jest wykorzystanie go w placówkach naukowych bardzo niskim kosztem.

\backmatter 

%\bibliographystyle{plplain}  % bibtex
%\bibliography{biblio} % bibtex
\printbibliography           % biblatex 
\addcontentsline{toc}{chapter}{Bibliografia}

\begin{appendices}

% TODO
\chapter{Spis skrótów i symboli}

\begin{itemize}
\item[SFTP] Protokół Bezpiecznego Przesyłu Plików (ang. \ang{Secure File Transfer Protocol})
\item[SSH] Bezpieczna Powłoka (ang. \ang{Secure SHell}) 
\item[HTTP] Protokół Przesyłu HiperTekstu (ang. \ang{HyperText Transfer Protocol})
\item[WWW] OgólnoŚwiatowa Sieć (ang. \ang{World Wide Web})
\item[CERN] Europejska Organizacja Badań Jądrowych (fr. \ang{Organisation Européenne pour la Recherche Nucléaire})
\item[TCP] Protokół Sterowania Transmisją (ang. \ang{Transmission Control Protocol})
\item[KVM] Maszyna Wirtualna Jądra (ang. \ang{Kernel Virtual Machine})
\item[MMU] Jednostka Zarządzająca Pamięcią (ang. \ang{Memory Management Unit})
\item[IOMMU] Jednostka Zarządzająca Pamięcią Wejścia Wyjścia (ang. \ang{Input Output Memory Management Unit})
\item[DHCP] Protokół Dynamicznego Konfigurowania Hostów (ang. \ang{Dynamic Host Configuration Protocol})
\item[BOOTP] Protokół Bootstrap (ang. \ang{BOOTstrap Protocol})
\item[TFTP] Trywialny Protokół Przesyłu Plików (ang. \ang{Trivial File Transfer Protocol})
\item[PXE] Przeduruchomieniowe Środowisko Uruchomieniowe (ang. \ang{Preboot Execution Environment})
\item[WOL] Uruchom Poprzez LAN (ang. \ang{Wake On LAN})
\item[WISM] ang. \ang{Windows System Image Manager}
\item[DISM] ang. \ang{Deployment Image Servicing and Management}
\item[AD] ang. \ang{Active Directory}
\item[JWT] ang. \ang{JSON Web Token}
\item[JSON] Notacja Obiektów JavaScript (ang. \ang{JavaScript Object Notation})
\item[ORM] Mapowanie obiektowo-relacyjne (ang. \ang{Object-Relational Mapping})
\end{itemize}


% TODO
% \chapter{Źródła}
% 
% Jeżeli w pracy konieczne jest umieszczenie długich fragmentów kodu źródłowego, należy je przenieść w to miejsce.
% 
% \begin{lstlisting}
% if (_nClusters < 1)
% 	throw std::string ("unknown number of clusters");
% if (_nIterations < 1 and _epsilon < 0)
% 	throw std::string ("You should set a maximal number of iteration or minimal difference -- epsilon.");
% if (_nIterations > 0 and _epsilon > 0)
% 	throw std::string ("Both number of iterations and minimal epsilon set -- you should set either number of iterations or minimal epsilon.");
% \end{lstlisting}


% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % 
% Pakiet minted wymaga odkomentowania w pliku config/settings.tex   %
% importu pakietu minted: \usepackage{minted}                       %
% i specjalnego kompilowania:                                       %
% pdflatex -shell-escape praca                                      %
% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % 

%\begin{minted}[linenos,breaklines,frame=lines]{c++}
%if (_nClusters < 1)
%   throw std::string ("unknown number of clusters");
%if (_nIterations < 1 and _epsilon < 0)
%   throw std::string ("You should set a maximal number of iteration or minimal difference -- epsilon.");
%if (_nIterations > 0 and _epsilon > 0)
%   throw std::string ("Both number of iterations and minimal epsilon set -- you should set either number of iterations or minimal epsilon.");
%\end{minted}


% TODO
\chapter{Lista dodatkowych plików, uzupełniających tekst pracy} 


W systemie do pracy dołączono dodatkowe pliki zawierające:
\begin{itemize}
\item źródła programów oraz pliki konfiguracyjne i skrypty
\item film pokazujący działanie opracowanego oprogramowania
\end{itemize}


\listoffigures
\addcontentsline{toc}{chapter}{Spis rysunków}
\listoftables
\addcontentsline{toc}{chapter}{Spis tabel}
	
\end{appendices}

\end{document}


%% Finis coronat opus.

