diff --git a/README.md b/README.md
index e6bb7586a4d58518bc340b587317971c9aab5099..68e4cfa76ba1b0ab7d5bc142b965204787b94688 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,34 @@
 # Bootiful
 
-![Log book](doc/logbook.md)
\ No newline at end of file
+![Logo du projet Bootiful](doc/images/bootiful_logo_final.svg)
+
+Le sujet de ce travail de diplôme est le développement d’une solution de
+déploiement de systèmes d’exploitation à la demande, pour une
+utilisation dans le cadre d’une école d’informatique. À chaque démarrage
+d’un poste de travail, l’utilisateur peut choisir quel système il
+souhaite utiliser dans une liste prédéfinie. Il est aussi possible de
+définir une liste de personnalisations qui permettent de configurer ce
+système, comme par exemple l’installation de certains logiciels ou une
+configuration de réseau spécifique. La première fois qu’un système
+d’exploitation est choisi, une image contenant les données du système
+d’exploitation est téléchargée depuis un serveur central. Cette image
+est déployée sur le disque dur pour permettre son utilisation. Une copie
+de l’image est aussi sauvegardée dans un cache situé à la fin du disque
+dur, dans un format compressé, pour permettre de ne plus avoir à la
+télécharger à nouveau les prochaines fois qu’elle devra être installée.
+Une fois le déploiement terminé, les personnalisations choisies sont
+appliquées, puis le système choisi est démarré et est utilisable jusqu’à
+l’extinction de l’ordinateur. Au prochain démarrage, un nouveau système
+d’exploitation sera de nouveau déployé. Ce mode de fonctionnement permet
+aux élèves de l’école de toujours utiliser un système propre et
+spécifique à leurs besoins immédiats. Des efforts ont été menés pour
+faire en sorte que les déploiements se fassent le plus rapidement
+possible, en économisant un maximum les ressources disque et réseau,
+tout en fonctionnant avec des ordinateurs modernes. Le développement de
+ce projet étant destiné à être continué après ce travail de diplôme, un
+soin particulier a été apporté pour automatiser et simplifier au maximum
+la construction et la mise en fonctionnement du système dans un
+environnement réel.
+
+- [Documentation](doc/rapport.md)
+- [Journal de bord](doc/logbook.md)
\ No newline at end of file
diff --git a/doc/rapport.gpp.md b/doc/rapport.gpp.md
index ce17b30d520ea0491a917bf3886b2c65111174ad..a1d81464719738d07d58ead5a068c20017b03452 100644
--- a/doc/rapport.gpp.md
+++ b/doc/rapport.gpp.md
@@ -223,6 +223,13 @@ d'un diagramme de Gantt. Ce diagramme est visible dans la figure
 
 !!pdfref{planning_gantt}{Diagramme de Gantt du planning}{images/planning}
 
+Le logiciel de gestion de révisions _Git_ a été utilisé pour gérer les
+différentes versions du code source du projet. Un dépôt a été créé sur
+le serveur Git de !!acronym{HEPIA}. Il est disponible à l'adresse
+suivante:
+
+<https://gitedu.hesge.ch/dimitri.lizzi/bootiful>
+
 ## Analyse
 
 ## Cas d'utilisation
diff --git a/doc/rapport.md b/doc/rapport.md
index 2b7986895079976aa6fe9afeb99c704ce26e1ae2..db114069de08452b315bc3c801487ce4a5012572 100644
--- a/doc/rapport.md
+++ b/doc/rapport.md
@@ -199,6 +199,13 @@ d'un diagramme de Gantt. Ce diagramme est visible dans la figure
 </figure>
 
 
+Le logiciel de gestion de révisions _Git_ a été utilisé pour gérer les
+différentes versions du code source du projet. Un dépôt a été créé sur
+le serveur Git de <abbr title="Haute École du Paysage, d’Ingénierie et d’Architecture de Genève ">HEPIA</abbr>. Il est disponible à l'adresse
+suivante:
+
+<https://gitedu.hesge.ch/dimitri.lizzi/bootiful>
+
 ## Analyse
 
 ## Cas d'utilisation
@@ -1879,6 +1886,13 @@ Le lancement de ces trois machines en simultané ainsi que leur
 configuration est assuré par l'outil _docker-compose_ (voir source dans
 la section ).
 
+Pour simplifier le lancement du serveur, une cible `start-server` a été
+créée dans le _Makefile_ du projet. Il suffit de lancer la commande
+suivante pour construire et démarrer un serveur:
+
+```bash
+make start-server
+```
 
 ## Personnalisation d'images post-déploiement
 
@@ -2147,7 +2161,7 @@ LATEST_LOG := $(shell ls -1 nfs/nfsshared/log/*.log | tail -n 1)
 .PHONY: doc grub deployer start-server reprovision-server clean print_last_log help
 
 # Builds everything
-all: doc grub deployer
+all: grub deployer
 
 # Builds PDF and markdown documents
 doc:
@@ -2242,7 +2256,7 @@ services:
       - type: tmpfs
         target: /nfsroot
       - type: bind
-        source: /run/media/araxor/bigdata/nfsshared
+        source: ./nfs/nfsshared
         target: /nfsshared
       - type: bind
         source: /lib/modules
@@ -3648,20 +3662,26 @@ echo "Starting logging stdout and stderr to $log_file..."
 
     if [[ -n "$customization_choices"  ]]; then
         start_step_batch "customizations deployment"
-
+        readonly customization_partitions_mount_dir="/bootiful/mounted_customization_partitions"
         for customization_choice in $customization_choices; do
-            customization="${customizations[customization_choice]}"
+            customization="${customizations[$customization_choice]}"
             customization_dir="$remote_image_customizations_dir/$customization"
 
-            echo "Deploying customization '$customization' from '$customization_dir'"
-            for customization_partition in "$customization_dir"/*; do
+            echo "Deploying customization '$customization' ($customization_choice) from '$customization_dir'"
+            for customization_partition_full in "$customization_dir"/*; do
+                customization_partition=$(basename "$customization_partition_full")
                 validate_with_regex "$customization_partition" '^sda[0-9]$' "customization sub-directory name does not match a partition of sda"
-                customization_partition_mount_point="/bootiful/mounted_customization_partitions/$customization_partition"
+                customization_partition_mount_point="$customization_partitions_mount_dir/$customization_partition"
                 customization_partition_device="/dev/$customization_partition"
                 ensure_mounted "$customization_partition_device" "$customization_partition_mount_point"
-                cp -RT "$customization_dir/$customization_partition/"
+                cp -RTf "$customization_partition_full/" "$customization_partition_mount_point/"
             done
         done
+
+        for customization_partition_mount_dir in "$customization_partitions_mount_dir"/*; do
+            umount "$customization_partition_mount_dir" ||
+                fatal_error "Cannot unmount '$customization_partition_mount_dir'"
+        done
     fi
 
     start_step_batch "EFI entrypoint file creation"
diff --git a/doc/rapport.pdf b/doc/rapport.pdf
index b73cdd9ee8cc55b07ebf52ea9ad154c296b11cb1..efd361dea0e56bfffd2c91ce32fafbc159339297 100644
Binary files a/doc/rapport.pdf and b/doc/rapport.pdf differ
diff --git a/doc/rapport.tex b/doc/rapport.tex
deleted file mode 100644
index 19a3c6b53d30a3eafeb71e8cb9fa21b62bac2e9c..0000000000000000000000000000000000000000
--- a/doc/rapport.tex
+++ /dev/null
@@ -1,5085 +0,0 @@
-% Options for packages loaded elsewhere
-\PassOptionsToPackage{unicode}{hyperref}
-\PassOptionsToPackage{hyphens}{url}
-%
-\documentclass[
-  12pt,
-  french,
-  a4paper,
-]{memoir}
-\usepackage{lmodern}
-\usepackage{amssymb,amsmath}
-\usepackage{ifxetex,ifluatex}
-\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex
-  \usepackage[T1]{fontenc}
-  \usepackage[utf8]{inputenc}
-  \usepackage{textcomp} % provide euro and other symbols
-\else % if luatex or xetex
-  \usepackage{unicode-math}
-  \defaultfontfeatures{Scale=MatchLowercase}
-  \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1}
-  \setmonofont[]{JetBrains Mono}
-\fi
-% Use upquote if available, for straight quotes in verbatim environments
-\IfFileExists{upquote.sty}{\usepackage{upquote}}{}
-\IfFileExists{microtype.sty}{% use microtype if available
-  \usepackage[]{microtype}
-  \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts
-}{}
-\makeatletter
-\@ifundefined{KOMAClassName}{% if non-KOMA class
-  \IfFileExists{parskip.sty}{%
-    \usepackage{parskip}
-  }{% else
-    \setlength{\parindent}{0pt}
-    \setlength{\parskip}{6pt plus 2pt minus 1pt}}
-}{% if KOMA class
-  \KOMAoptions{parskip=half}}
-\makeatother
-\usepackage{xcolor}
-\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available
-\IfFileExists{bookmark.sty}{\usepackage{bookmark}}{\usepackage{hyperref}}
-\hypersetup{
-  pdftitle={Bootiful},
-  pdfauthor={Dimitri Lizzi},
-  pdflang={fr-CH},
-  pdfkeywords={Bachelor, HEPIA, HESSO, Bootiful},
-  hidelinks,
-  pdfcreator={LaTeX via pandoc}}
-\urlstyle{same} % disable monospaced font for URLs
-\usepackage[includeheadfoot,margin=2.5cm]{geometry}
-\usepackage{color}
-\usepackage{fancyvrb}
-\newcommand{\VerbBar}{|}
-\newcommand{\VERB}{\Verb[commandchars=\\\{\}]}
-\DefineVerbatimEnvironment{Highlighting}{Verbatim}{commandchars=\\\{\}}
-% Add ',fontsize=\small' for more characters per line
-\newenvironment{Shaded}{}{}
-\newcommand{\AlertTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
-\newcommand{\AnnotationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
-\newcommand{\AttributeTok}[1]{\textcolor[rgb]{0.49,0.56,0.16}{#1}}
-\newcommand{\BaseNTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
-\newcommand{\BuiltInTok}[1]{#1}
-\newcommand{\CharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
-\newcommand{\CommentTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textit{#1}}}
-\newcommand{\CommentVarTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
-\newcommand{\ConstantTok}[1]{\textcolor[rgb]{0.53,0.00,0.00}{#1}}
-\newcommand{\ControlFlowTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
-\newcommand{\DataTypeTok}[1]{\textcolor[rgb]{0.56,0.13,0.00}{#1}}
-\newcommand{\DecValTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
-\newcommand{\DocumentationTok}[1]{\textcolor[rgb]{0.73,0.13,0.13}{\textit{#1}}}
-\newcommand{\ErrorTok}[1]{\textcolor[rgb]{1.00,0.00,0.00}{\textbf{#1}}}
-\newcommand{\ExtensionTok}[1]{#1}
-\newcommand{\FloatTok}[1]{\textcolor[rgb]{0.25,0.63,0.44}{#1}}
-\newcommand{\FunctionTok}[1]{\textcolor[rgb]{0.02,0.16,0.49}{#1}}
-\newcommand{\ImportTok}[1]{#1}
-\newcommand{\InformationTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
-\newcommand{\KeywordTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{\textbf{#1}}}
-\newcommand{\NormalTok}[1]{#1}
-\newcommand{\OperatorTok}[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
-\newcommand{\OtherTok}[1]{\textcolor[rgb]{0.00,0.44,0.13}{#1}}
-\newcommand{\PreprocessorTok}[1]{\textcolor[rgb]{0.74,0.48,0.00}{#1}}
-\newcommand{\RegionMarkerTok}[1]{#1}
-\newcommand{\SpecialCharTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
-\newcommand{\SpecialStringTok}[1]{\textcolor[rgb]{0.73,0.40,0.53}{#1}}
-\newcommand{\StringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
-\newcommand{\VariableTok}[1]{\textcolor[rgb]{0.10,0.09,0.49}{#1}}
-\newcommand{\VerbatimStringTok}[1]{\textcolor[rgb]{0.25,0.44,0.63}{#1}}
-\newcommand{\WarningTok}[1]{\textcolor[rgb]{0.38,0.63,0.69}{\textbf{\textit{#1}}}}
-\usepackage{longtable,booktabs}
-% Correct order of tables after \paragraph or \subparagraph
-\usepackage{etoolbox}
-\makeatletter
-\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{}
-\makeatother
-% Allow footnotes in longtable head/foot
-\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}}
-\makesavenoteenv{longtable}
-\usepackage{graphicx}
-\makeatletter
-\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
-\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
-\makeatother
-% Scale images if necessary, so that they will not overflow the page
-% margins by default, and it is still possible to overwrite the defaults
-% using explicit options in \includegraphics[width, height, ...]{}
-\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
-% Set default figure placement to htbp
-\makeatletter
-\def\fps@figure{htbp}
-\makeatother
-\setlength{\emergencystretch}{3em} % prevent overfull lines
-\providecommand{\tightlist}{%
-  \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}}
-\setcounter{secnumdepth}{5}
-\usepackage{pdfpages}
-\usepackage{fancyhdr}
-\usepackage{graphicx}
-\usepackage{float}
-\usepackage{lastpage}
-\usepackage{fvextra}
-\DefineVerbatimEnvironment{Highlighting}{Verbatim}{frame=single,breaklines,commandchars=\\\{\},fontsize=\footnotesize}
-
-\pagestyle{fancy}
-\setlength{\headheight}{14pt}
-
-\renewcommand{\headrulewidth}{0.4pt}
-\renewcommand{\footrulewidth}{0.4pt}
-
-\fancyhead[LO,LE]{Bootiful}
-\fancyhead[CO,CE]{Déploiement d'OS à choix durant le processus de boot}
-\fancyhead[RO,RE]{Dimitri Lizzi}
-\fancyfoot[LO,LE]{août 2020}
-\fancyfoot[CO,CE]{}
-\fancyfoot[RE,RO]{\thepage /\pageref{LastPage}}
-
-\setcounter{tocdepth}{4}
-
-\setlength{\parindent}{0pt}
-\setlength{\parskip}{9pt}
-\setlength{\beforechapskip}{-10pt}
-
-\OnehalfSpacing
-\ifxetex
-  % Load polyglossia as late as possible: uses bidi with RTL langages (e.g. Hebrew, Arabic)
-  \usepackage{polyglossia}
-  \setmainlanguage[]{french}
-\else
-  \usepackage[shorthands=off,main=french]{babel}
-\fi
-\newlength{\cslhangindent}
-\setlength{\cslhangindent}{1.5em}
-\newenvironment{cslreferences}%
-  {}%
-  {\par}
-
-\title{Bootiful}
-\usepackage{etoolbox}
-\makeatletter
-\providecommand{\subtitle}[1]{% add subtitle to \maketitle
-  \apptocmd{\@title}{\par {\large #1 \par}}{}{}
-}
-\makeatother
-\subtitle{Déploiement d'OS à choix durant le processus de boot}
-\author{Dimitri Lizzi}
-\date{Août 2020}
-
-\begin{document}
-% Nom conformes des tables
-\renewcommand*\listfigurename{Liste des illustrations}
-\renewcommand*\listtablename{Liste des tableaux}
-% Sets the page numbering style to roman
-%\pagestyle{headings}
-%\setcounter{page}{1}
-%\pagenumbering{roman}
-
-% Hides the page number for the cover page
-\thispagestyle{empty}
-\addtolength{\voffset}{-5pt}
-% Hides the header for the cover page
-% Cover page
-\begin{figure}
-    \vspace*{-5cm}
-    \begin{sffamily}
-        \begin{minipage}{.4\textwidth}
-            \centering
-            \hspace*{-3cm}\includegraphics[height=1.25cm]{images/logo_hepia.pdf}
-        \end{minipage}\qquad
-        \begin{minipage}{.4\textwidth}
-            \centering
-            \hspace*{5cm}\includegraphics[height=1.25cm]{images/logo-hesso-geneve.pdf}
-        \end{minipage}
-    \end{sffamily}
-\end{figure}
-
-\begin{center}
-    \vspace{1.5cm}
-    \includegraphics[height=5cm]{images/bootiful_logo_final.pdf}\\
-    \vspace{5mm}
-
-    \huge{Déploiement d'OS à choix durant le processus de boot}\\
-    \vspace{2cm}
-
-    \large{Thèse de Bachelor présentée par}\\
-    \vspace{5mm}
-    \textbf{\Large{Dimitri Lizzi}}\\
-    \vspace{5mm}
-
-    \large{pour l’obtention du titre Bachelor of Science HES-SO en}\\
-    \vspace{5mm}
-    \textbf{\Large{Ingénierie des technologies de l’information \\avec orientation en \\logiciels
-et systèmes complexes}}
-
-    \vspace{5mm}
-    \textbf{Août 2020\\}
-    \vspace{8mm}
-    \begin{tabular}{ p{6cm} }
-      \multicolumn{1}{c}{Professeur-e HES responsable}\\
-      \multicolumn{1}{c}{\textbf{Florent Glück}}\\
-    \end{tabular}
-\end{center}
-
-
-\mainmatter
-\tableofcontents
-\newpage
-
-\chapter*{Remerciements}
-\addcontentsline{toc}{chapter}{Remerciements}
-
-\textbf{TODO: remerciements}
-
-\addcontentsline{toc}{chapter}{Résumé}
-\includepdf{abstract.pdf}
-
-\addcontentsline{toc}{chapter}{Énoncé}
-\includepdf{statement.pdf}
-
-\chapter*{Liste des acronymes}
-\addcontentsline{toc}{chapter}{Liste des acronymes}
-
-\begin{description}
-\tightlist
-\item[BIOS \protect\hypertarget{acronym__BIOS}{}{}]
-\emph{Basic Input Output System}: système de base d'entrée sortie
-\item[DHCP \protect\hypertarget{acronym__DHCP}{}{}]
-\emph{Dynamic Host Configuration Protocol}: protocole de configuration
-dynamique des hôtes
-\item[EFI \protect\hypertarget{acronym__EFI}{}{}]
-\emph{Extensible Firmware Interface}: interface micrologicielle
-extensible unifiée
-\item[ESP \protect\hypertarget{acronym__ESP}{}{}]
-\emph{EFI System Partition}: partition système EFI
-\item[FOG \protect\hypertarget{acronym__FOG}{}{}]
-\emph{Free Open-source Ghost}
-\item[FTP \protect\hypertarget{acronym__FTP}{}{}]
-\emph{File Transfer Protocol}: protocole de transfert de fichier
-\item[GPT \protect\hypertarget{acronym__GPT}{}{}]
-\emph{GUID Partition Table}: table de partitionnement GUID
-\item[GRUB \protect\hypertarget{acronym__GRUB}{}{}]
-\emph{GRand Unified Bootloader}
-\item[HEPIA \protect\hypertarget{acronym__HEPIA}{}{}]
-Haute école du paysage, d'ingénierie et d'architecture de Genève
-\item[HTTPS \protect\hypertarget{acronym__HTTPS}{}{}]
-\emph{HyperText Transfer Protocol Secure}: protocole de transfert
-hypertexte sécurisé
-\item[HTTP \protect\hypertarget{acronym__HTTP}{}{}]
-\emph{HyperText Transfer Protocol}: protocole de transfert hypertexte
-\item[IBM \protect\hypertarget{acronym__IBM}{}{}]
-\emph{International Business Machines corporation}
-\item[IPFS \protect\hypertarget{acronym__IPFS}{}{}]
-\emph{InterPlanetary File System}: système de fichier inter-planétaire
-\item[IP \protect\hypertarget{acronym__IP}{}{}]
-\emph{Internet Protocol}: protocole internet
-\item[LDAP \protect\hypertarget{acronym__LDAP}{}{}]
-\emph{Lightweight Directory Access Protocol}: protocole léger d'accès à
-un annuaire
-\item[MAC \protect\hypertarget{acronym__MAC}{}{}]
-\emph{Media Access Control (address)}: adresse physique
-\item[MBR \protect\hypertarget{acronym__MBR}{}{}]
-\emph{Master Boot Record}: enregistrement d'amorcage maître
-\item[NAT \protect\hypertarget{acronym__NAT}{}{}]
-\emph{Network Address Translation}: traduction d'adresse réseau
-\item[NFS \protect\hypertarget{acronym__NFS}{}{}]
-\emph{Network File System}: système de fichiers en réseau
-\item[NVRAM \protect\hypertarget{acronym__NVRAM}{}{}]
-\emph{Non-Volatile Random Access Memory}: mémoire vive non volatile
-\item[OS \protect\hypertarget{acronym__OS}{}{}]
-\emph{Operating System}: système d'exploitation
-\item[PC \protect\hypertarget{acronym__PC}{}{}]
-\emph{Personal Computer}: ordinateur personnel
-\item[PXE \protect\hypertarget{acronym__PXE}{}{}]
-\emph{Pre-boot eXecution Environment}: environnement d'exécution
-pré-démarrage
-\item[SCP \protect\hypertarget{acronym__SCP}{}{}]
-\emph{Secure CoPy}: protocole de copie sécurisée sur le réseau
-\item[SI \protect\hypertarget{acronym__SI}{}{}]
-Système d'Information
-\item[SMB \protect\hypertarget{acronym__SMB}{}{}]
-\emph{Server Message Block}
-\item[SSH \protect\hypertarget{acronym__SSH}{}{}]
-\emph{Secure SHell}: protocole de terminal à distance securisé
-\item[TFTP \protect\hypertarget{acronym__TFTP}{}{}]
-\emph{Trivial File Transfer Protocol}: protocole simplifié de transfert
-de fichiers
-\item[UEFI \protect\hypertarget{acronym__UEFI}{}{}]
-\emph{Unified Extensible Firmware Interface}: interface micrologicielle
-extensible unifiée
-\item[WWW \protect\hypertarget{acronym__WWW}{}{}]
-\emph{World Wide Web}: toile mondiale / réseau mondial
-\end{description}
-
-\newpage
-
-\listoffigures
-\newpage
-
-\listoftables
-
-\hypertarget{introduction}{%
-\chapter{Introduction}\label{introduction}}
-
-\hypertarget{contexte}{%
-\section{Contexte}\label{contexte}}
-
-Aujourd'hui les machines des salles de cours à
-\protect\hyperlink{acronym__HEPIA}{HEPIA} sont installées avec une image
-spécifique d'un système d'exploitation. Dans le cadre de certains cours,
-on désirerait pouvoir utiliser un autre système d'exploitation
-(\protect\hyperlink{acronym__OS}{OS}) et aussi avoir la possibilité
-d'être administrateur sur la machine physique. En effet, utiliser une
-machine virtuelle n'est pas toujours souhaitable, surtout lorsqu'il y a
-interaction avec du matériel, typiquement lors du développement pour
-l'embarqué. Le but de ce projet est de développer un système de
-déploiement répondant à ces besoins. Lors de la mise sous tension d'une
-machine, le système proposerait à l'utilisateur un choix d'OSes et
-celui-ci s'installerait à la volée (distributions Linux, différentes
-versions de Windows, etc.). Afin de minimiser le temps d'attente lors de
-l'installation de l'\protect\hyperlink{acronym__OS}{OS}, un mécanisme de
-cache évitant le téléchargement des images préalablement téléchargées
-sera mis en place. On désire aussi que le système de déploiement
-permette de customiser certains aspects de l'image choisie. Ce travail
-ce base sur une ébauche d'un travail déjà existant.
-
-\hypertarget{objectifs}{%
-\section{Objectifs}\label{objectifs}}
-
-\begin{itemize}
-\tightlist
-\item
-  Etude du travail existant.
-\item
-  Mise en place d'un déploiement automatisé et reproductible du travail
-  existant.
-\item
-  Ajout du support d'images Windows.
-\item
-  Optimisation du format d'image afin d'en accélérer sensiblement la
-  vitesse de téléchargement.
-\item
-  Mise en place d'un mécanisme de personnalisation des images en
-  post-installation.
-\item
-  Implémenter une gestion administrative aisée du système de déploiement
-
-  \begin{itemize}
-  \tightlist
-  \item
-    Il doit être aisé de créer des images et configurer les opérations à
-    effectuer en post-installation.
-  \end{itemize}
-\item
-  Le système doit pouvoir supporter l'authentification des utilisateurs
-  via un serveur \protect\hyperlink{acronym__LDAP}{LDAP} (Linux
-  seulement)
-
-  \begin{itemize}
-  \tightlist
-  \item
-    Les OS déployés (Linux), doivent pouvoir s'intégrer au processus
-    d'authentification utilisé dans les salles de laboratoires ITI.
-  \end{itemize}
-\item
-  Gestion du système aussi simple et aisée que possible.
-\item
-  Si le temps le permet: optimisation de la bande passante du réseau
-  dans le cas de nombreux téléchargements effectués en parallèle.
-\end{itemize}
-
-\hypertarget{duxe9roulement}{%
-\section{Déroulement}\label{duxe9roulement}}
-
-Ce projet n'a pas n'a pas été réalisé dans les locaux
-d'\protect\hyperlink{acronym__HEPIA}{HEPIA} mais à distance, depuis la
-maison, en partie à cause de la situation sanitaire due au COVID-19 mais
-aussi parce qu'il est effectué dans le cadre d'un bachelor en cours du
-soir, en parallèle à une activité professionnelle à 80\%.
-
-Des rendez-vous hebdomadaires avec le professeur responsable Florent
-Glück ainsi que l'assistant Sébastien Chassot ont été organisés tous les
-mercredis, afin d'assurer un suivi du projet.
-
-\hypertarget{matuxe9riel-uxe0-disposition}{%
-\section{Matériel à disposition}\label{matuxe9riel-uxe0-disposition}}
-
-Deux mini-ordinateurs ont étés prêtés par
-\protect\hyperlink{acronym__HEPIA}{HEPIA} pour la durée du projet, afin
-d'effectuer des tests sur du matériel réel. Les spécifications de ces
-ordinateurs sont définies dans la table \ref{mini_pc_specs}.
-
-\begin{longtable}[]{@{}ll@{}}
-\caption{Spécifications techniques des ordinateurs mis à disposition
-\label{mini_pc_specs}}\tabularnewline
-\toprule
-\begin{minipage}[b]{0.19\columnwidth}\raggedright
-Caractéristique\strut
-\end{minipage} & \begin{minipage}[b]{0.75\columnwidth}\raggedright
-Description\strut
-\end{minipage}\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-\begin{minipage}[b]{0.19\columnwidth}\raggedright
-Caractéristique\strut
-\end{minipage} & \begin{minipage}[b]{0.75\columnwidth}\raggedright
-Description\strut
-\end{minipage}\tabularnewline
-\midrule
-\endhead
-\begin{minipage}[t]{0.19\columnwidth}\raggedright
-Constructeur\strut
-\end{minipage} & \begin{minipage}[t]{0.75\columnwidth}\raggedright
-\emph{DELL}\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.19\columnwidth}\raggedright
-Modèle\strut
-\end{minipage} & \begin{minipage}[t]{0.75\columnwidth}\raggedright
-\emph{Optiplex 7060 micro}\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.19\columnwidth}\raggedright
-Processeur\strut
-\end{minipage} & \begin{minipage}[t]{0.75\columnwidth}\raggedright
-\emph{Intel® Core™ i7-8700 3.20GHz}\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.19\columnwidth}\raggedright
-Mémoire vive\strut
-\end{minipage} & \begin{minipage}[t]{0.75\columnwidth}\raggedright
-8 GiB (2 barettes 4GiB \emph{SODIMM DDR4 Synchronous} 2666 MHz (0.4
-ns))\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.19\columnwidth}\raggedright
-Disque\strut
-\end{minipage} & \begin{minipage}[t]{0.75\columnwidth}\raggedright
-\emph{TOSHIBA KSG60ZMV} SSD 476GiB (512GB)\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.19\columnwidth}\raggedright
-Réseau\strut
-\end{minipage} & \begin{minipage}[t]{0.75\columnwidth}\raggedright
-\emph{Intel e1000e Gigabit Ethernet}\strut
-\end{minipage}\tabularnewline
-\bottomrule
-\end{longtable}
-
-\hypertarget{muxe9thodologie}{%
-\section{Méthodologie}\label{muxe9thodologie}}
-
-Le travail a été découpé en plusieurs parties, dont la durée a été
-estimée en semaines de travail. Un planning a été effectué sous la forme
-d'un diagramme de Gantt. Ce diagramme est visible dans la figure
-\ref{planning_gantt}.
-
-\begin{figure}
-\centering
-\includegraphics{images/planning.pdf}
-\caption{Diagramme de Gantt du planning\label{planning_gantt}}
-\end{figure}
-
-\hypertarget{analyse}{%
-\section{Analyse}\label{analyse}}
-
-\hypertarget{cas-dutilisation}{%
-\section{Cas d'utilisation}\label{cas-dutilisation}}
-
-L'aspect fonctionnel du système à réaliser est décrit avec un diagramme
-de cas d'utilisations dans la figure \ref{diagram_usecases}.
-
-\begin{figure}
-\centering
-\includegraphics{images/diagram_usecases.svg}
-\caption{Diagramme des cas d'utilisation du
-système.\label{diagram_usecases}}
-\end{figure}
-
-\hypertarget{uxe9tude-des-solutions-existantes}{%
-\section{Étude des solutions
-existantes}\label{uxe9tude-des-solutions-existantes}}
-
-De nombreux systèmes de déploiement
-d'\protect\hyperlink{acronym__OS}{OS} existent, mais aucun d'entre eux
-ne répond précisément aux objectifs précis du cahier des charges de ce
-projet.
-
-Les sous-sections qui suivent décrivent quelques-uns de ces systèmes,
-leurs points forts et points faibles et pourquoi ils ne sont pas adaptés
-tels-quel pour ce projet.
-
-\hypertarget{bpbatch-rembo-ibm-tivoli}{%
-\subsection{\texorpdfstring{BpBatch / Rembo /
-\protect\hyperlink{acronym__IBM}{IBM}
-Tivoli}{BpBatch / Rembo / IBM Tivoli}}\label{bpbatch-rembo-ibm-tivoli}}
-
-Ce système est l'inspiration directe de ce projet. Son développement a
-commencé en 1996 au département informatique de l'université de Genève
-par Marc Vuilleumier Stückelberg et David Clerc.
-
-Les fonctionnalités de ce projet sont similaires à celles visée par le
-projet \emph{Bootiful}. Il permet aux postes clients de lancer un mini
-système d'exploitation via \protect\hyperlink{acronym__PXE}{PXE} au
-démarrage de la machine. Ce mini-système permet de télécharger et
-déployer des images de système d'exploitation sur la machine, tout en
-créant une copie en cache à la fin du disque pour éviter de la
-télécharger plusieurs fois.
-
-La première version, nommée \emph{BpBatch} fut distribuée gratuitement
-sur internet. Une entreprise nommée \emph{Rembo Technology Sàrl} a
-ensuite été fondée en 1999 pour continuer un développement commercial de
-ce projet sous le nom de \emph{Rembo}. En 2006, la société a été
-rachetée par IBM et le projet a été intégré à leur solution \emph{Tivoli
-Provisionning Manager}.
-
-Ce système réponde aux besoins de
-\protect\hyperlink{acronym__HEPIA}{HEPIA}, et il a même déjà été utilisé
-au sein de l'institution par le passé. Il a cependant été abandonné à
-cause de sa licence devenue très couteuse et de sa complexité devenue
-trop grande pour les besoins simple de l'école.
-
-Le développement d'une solution alternative \emph{open-source} plus
-simple et se basant sur des briques logicielles existantes serait donc
-très intéressante.
-
-\hypertarget{fog-project}{%
-\subsection{\texorpdfstring{\protect\hyperlink{acronym__FOG}{FOG}
-project}{FOG project}}\label{fog-project}}
-
-\protect\hyperlink{acronym__FOG}{FOG} est une solution open-source
-gratuite permettant de déployer des images de systèmes d'exploitation
-sur des postes clients.
-
-Elle fonctionne avec une architecture client-serveur. Le serveur est
-accédé par une interface web, où un administrateur peut gérer ses images
-et les déployer sur des clients qui démarrent un logiciel de déploiement
-avec \protect\hyperlink{acronym__PXE}{PXE}.
-
-Cette solution est utilisées dans certaines classes à
-\protect\hyperlink{acronym__HEPIA}{HEPIA} pour déployer des images sur
-certains postes, notemment pour les travaux de laboratoire de réseau.
-
-Malheureusement, ce système ne répond pas exactement au cahier des
-charges de ce projet: il est plutôt conçu pour ``pousser'' des images
-sur des clients, depuis le serveur, après une initiation du déploiement
-par un administrateur. Nous souhaitons plutôt un système ne nécessitant
-pas d'intervention d'un administrateur pour initier un déploiement.
-
-De plus,\protect\hyperlink{acronym__FOG}{FOG} ne dispose pas de
-mécanisme de cache sur les clients permettant de ne pas télécharger les
-images plusieurs fois. À chaque fois qu'un image doit être déployée,
-elle doit être téléchargée à nouveau depuis le serveur, ce qui peut
-prendre beaucoup de temps et doit être planifié à l'avance.
-
-\hypertarget{clonezilla}{%
-\subsection{Clonezilla}\label{clonezilla}}
-
-\emph{Clonezilla} est une solution open-source et gratuite de création
-et de restauration d'images.
-
-Cet outil peut être utilisé de deux manières:
-
-\begin{itemize}
-\tightlist
-\item
-  En faisant démarrer les clients sur le réseau. Ils chargent un petit
-  système d'exploitation de déploiement depuis un un serveur
-  \protect\hyperlink{acronym__PXE}{PXE}. Ils peuvent ensuite initier le
-  déploiement ou la restauration d'une image depuis/vers ce serveur.
-\item
-  En faisant démarrer les clients sur un CD ou une clé USB. Ils peuvent
-  ensuite initier le déploiement ou la restauration d'une image
-  d'\protect\hyperlink{acronym__OS}{OS} depuis/vers sur un autre disque
-  ou un serveur distant.
-\end{itemize}
-
-Un avantage de \emph{Clonezilla} est le format utilisé pour la
-sauvegarde des images. L'outil \emph{Partclone}, développé par la même
-équipe, est utilisé. Il permet de créer des images de partitions en ne
-copiant que les blocs utilisés dans le système de fichiers. Les parties
-non utilisées de la partition ne sont pas comprises dans l'image créée,
-ce qui permet de réduire sa taille et d'accélérer le processus de
-sauvegarde et de restauration.
-
-Malheureusement, comme pour \protect\hyperlink{acronym__FOG}{FOG},
-\emph{Clonezilla} ne dispose pas de mécanisme de cache sur les clients
-permettant de ne pas télécharger les images depuis un serveur distant
-plusieurs fois. À chaque fois qu'un image doit être déployée, elle doit
-être téléchargée à nouveau depuis le serveur, ce qui peut prendre
-beaucoup de temps et doit être planifié à l'avance.
-
-\emph{Clonezilla} ne peut donc pas être utilisé tel-quel. Cependant, il
-est possible de l'utiliser uniquement pour la création d'images et
-d'intégrer son mécanisme de restauration à un autre système de
-déploiement. Cette possibilité sera étudiée plus tard dans ce document.
-
-\hypertarget{architecture-initiale-du-projet}{%
-\chapter{Architecture initiale du
-projet}\label{architecture-initiale-du-projet}}
-
-Le projet \emph{Bootiful} n'a pas été initié dans le cadre de ce travail
-de bachelor: une implémentation basique
-(\protect\hyperlink{ref-venkatesh_remote_imaging}{1}) avait déjà été
-réalisée afin de prouver que l'idée fonctionne. Cette version initiale a
-été créée par Abhilash Venkatesh, un étudiant indien qui est venu à
-\protect\hyperlink{acronym__HEPIA}{HEPIA} effectuer un stage pendant la
-période de mai à juillet 2019.
-
-Les premières étapes de ce travail diplôme ont été de reproduire le
-système réalisé dans le projet initial afin de valider son
-fonctionnement, d'analyser en détail son fonctionnement et sa structure
-et de documenter son architecture.
-
-Ce chapitre est l'aboutissement de cette étude. Il décrit les détails de
-l'architecture du projet initial qui a été reproduite, afin d'apporter
-un contexte aux chapitres suivants qui décrivent les ajouts et
-modifications de cette architecture.
-
-\hypertarget{composants-initiaux}{%
-\section{Composants initiaux}\label{composants-initiaux}}
-
-Le système est composé de multiples clients qui communiquent avec un
-serveur central à travers un réseau \protect\hyperlink{acronym__IP}{IP}.
-
-\hypertarget{postes-clients}{%
-\subsection{Postes clients}\label{postes-clients}}
-
-Les postes clients supportés par le système sont des ordinateurs
-compatibles \protect\hyperlink{acronym__PC}{PC} x86.
-
-Ils doivent nécessairement être équipés d'une carte réseau et d'un
-micrologiciel \protect\hyperlink{acronym__BIOS}{BIOS} ou
-\protect\hyperlink{acronym__UEFI}{UEFI} capables et configurés pour
-amorcer un système d'exploitation à partir du réseau à chaque démarrage
-en utilisant le standard \protect\hyperlink{acronym__PXE}{PXE}.
-
-Ils doivent aussi disposer d'un disque dur sur lequel les images de
-système d'exploitation seront déployées et mises en cache. L'espace
-disque est subdivisé en trois parties distinctes ayant chacune un rôle
-précis.
-
-La première partie du disque est l'espace dédié au déploiement d'un
-\protect\hyperlink{acronym__OS}{OS}. Elle prend 80\% de l'espace total
-disponible, au début du disque. Au tout début de cette partie du disque,
-dans le premier secteur addressable du disque, se trouve le secteur
-d'amorçage au format \protect\hyperlink{acronym__MBR}{MBR}. Ce premier
-secteur contient deux informations nécessaires pour le chargement d'un
-système d'exploitation:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\item
-  \textbf{La routine d'amorcage}: c'est le premier programme exécuté
-  lors du démarrage sur le disque. Sa taille est très limitée: 440
-  octets. Il sert généralement à initier un chargeur d'amorcage ou
-  \emph{bootloader} présent un peu plus loin sur le disque, qui est un
-  petit programme qui va initier un système d'exploitation.
-\item
-  \textbf{La table des partitions}: définit une liste de partitions, qui
-  sont des subdivisions logiques de l'espace du disque. Selon le système
-  d'exploitation installé et la manière dont il a été configuré lors de
-  son installation initiale les partitions peuvent varier en nombre et
-  en taille. Les données à l'intérieur de chaque partition sont
-  généralement structurées en utilisant un système de fichiers. Les
-  partitions vont varier en nombre, taille, et format selon l'image
-  déployée.
-\end{enumerate}
-
-La seconde partie du disque est l'espace dédié à la mise en cache
-d'images d'\protect\hyperlink{acronym__OS}{OS}, qui prend 20\% de
-l'espace total disponible, moins 4096 octets, à la fin du disque. Ce
-cache permet de stocker des images disques compressées qui peuvent être
-décompressées sur la première partie du disque. Lors du premier
-déploiement d'une image disque compressée disponible sur le serveur,
-cette dernière est transmise depuis le serveur jusqu'au client en
-version compressée à travers le réseau. Au fur et à mesure que les
-données compressées de l'image sont réceptionnées par le client, elles
-sont simultanément copiées dans le cache et décompressées sur la
-première partie du disque.
-
-Ce mécanisme de cache permet de ne plus avoir à télécharger à nouveau
-l'image lors des prochains déploiements car elle sera disponible
-localement. Il suffira de décompresser le fichier présent dans le cache
-et d'écrire les données extraites séquentiellement sur la première
-partie du disque. Cela permet d'éviter de surcharger la bande passante
-du réseau et les ressources du serveur, en particulier quand un grand
-nombre de clients vont fréquemment déployer la même image en même temps,
-comme cela sera souvent le cas dans le contexte d'une école
-d'informatique où les élèves déploient la même image au début de chaque
-session d'un même cours.
-
-Enfin, les 4096 octets restants à la fin du disque sont dédiés à
-l'écriture d'une signature servant à signaler si une image vient d'être
-deployée sur le disque. La présence cette signature est verifiée à
-chaque démarrage pour déterminer s'il faut démarrer une image
-fraichement déployée ou si au contraire l'image déployée a déjà été
-utilisée et qu'il faut lancer un nouveau déploiement. Ainsi, le système
-peut s'assurer qu'une image disque déployée n'est exécutée qu'une seule
-fois, ce qui laisse la liberté à l'utilisateur du poste client de faire
-ce qu'il veut sur le système déployé sans se soucier de rendre le
-système inutilisable, car il suffit de redémarrer la machine pour
-repartir sur une base propre.
-
-Le mécanisme de signature est nécessaire à cause du moyen choisi pour
-déployer les images: un système d'exploitation Linux minimaliste est est
-chargé en mémoire depuis le réseau afin de lancer le processus de choix
-d'une image et de la déployer. Une fois le déploiement terminé, la
-machine redémarre. La signature à la fin du disque est un moyen simple
-et efficace de faire persister l'information qu'une image vient d'être
-déployée et de la vérifier au démarrage.
-
-\hypertarget{serveur}{%
-\subsection{Serveur}\label{serveur}}
-
-Le composant central du système est un \emph{serveur} linux qui
-inter-agit avec les postes clients pour leur permettre d'effectuer
-plusieurs actions:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  Recevoir une configuration IP et un chargeur d'amorcage
-  \protect\hyperlink{acronym__GRUB}{GRUB} à exécuter pour démarrer sur
-  le réseau en utilisant le standard PXE.
-\item
-  Analyser la signature présente sur le disque dur depuis le chargeur
-  d'amorçage chargeur d'amorcage
-  \protect\hyperlink{acronym__GRUB}{GRUB}.
-
-  \begin{itemize}
-  \tightlist
-  \item
-    Si elle n'est pas présente, amorcer un système d'exploitation
-    minimaliste servant à effectuer le choix d'une image et
-    d'automatiser son déploiement et sa mise en cache.
-  \item
-    Si elle est présente, l'effacer et démarrer sur le disque dur pour
-    initier l'amorçage de l'\protect\hyperlink{acronym__OS}{OS} déployé.
-  \end{itemize}
-\item
-  Lister les images disponible et les méta-données de chacune d'entre
-  elle:
-
-  \begin{itemize}
-  \tightlist
-  \item
-    Le nom de l'image, pour permettre aux utilisateurs d'effectuer un
-    choix.
-  \item
-    La taille de l'image décompressée, pour pouvoir vérifier que la
-    taille du disque client est suffisante pour déployer l'image.
-  \item
-    La taille de l'image compressée, pour pouvoir vérifier que l'image
-    puisse être mise en cache.
-  \item
-    Un \emph{hash} de l'image pour pouvoir l'identifier de manière
-    unique et vérifier si elle est déjà présente dans le cache ou s'il
-    faut la télécharger.
-  \end{itemize}
-\item
-  Télécharger une image choisie.
-\item
-  Sauvegarder et charger une copie du
-  \protect\hyperlink{acronym__MBR}{MBR} contenant la table des
-  partitions qui contient la partition cachée, afin de pouvoir le
-  restaurer et remonter cette partition.
-\item
-  Sauvegarder un log du déploiement afin de pouvoir garder une trace des
-  temps de déploiement et des éventuelles erreurs rencontrées.
-\end{enumerate}
-
-Trois protocoles réseau standard sont utilisés pour permettre au client
-d'effectuer ces actions:
-
-\begin{itemize}
-\item
-  \protect\hyperlink{acronym__DHCP}{DHCP}: fournit aux clients initiant
-  un démarrage sur le réseau une configuration IP, et l'adresse d'un
-  serveur TFTP et le nom du fichier exécutable du chargeur d'amorçage à
-  récupérer sur ce dernier
-\item
-  \protect\hyperlink{acronym__TFTP}{TFTP}: permet au clients de
-  télécharger:
-
-  \begin{itemize}
-  \tightlist
-  \item
-    le fichier exécutable du chargeur d'amorçage
-  \item
-    la configuration du chargeur d'amorçage
-  \item
-    les modules optionels du chargeur d'amorçage, téléchargés selon la
-    configuration
-  \item
-    l'image initrd permettant d'initialiser le système linux de
-    déploiement
-  \item
-    le noyeau linux de l'OS de déploiement
-  \item
-    l'image du système de fichier racine de l'OS de déploiement
-  \end{itemize}
-\item
-  \protect\hyperlink{acronym__NFS}{NFS}: permet au système linux de
-  monter un partage distant qui contient:
-
-  \begin{itemize}
-  \tightlist
-  \item
-    les scripts permettant d'effectuer le déploiement automatique
-  \item
-    un dossier contenant les images et leurs métadonnées
-  \item
-    un dossier dans lequel enregistrer une copie du MBR
-  \item
-    un dossier dans lequel enregistrer les logs du déploiement
-  \end{itemize}
-\end{itemize}
-
-\hypertarget{diagramme-des-composants-du-serveur}{%
-\subsection{Diagramme des composants du
-serveur}\label{diagramme-des-composants-du-serveur}}
-
-La figure \ref{diagram_components} est un diagramme qui détaille les
-différents composants et leurs interactions.
-
-\begin{figure}
-\centering
-\includegraphics{images/diagram_components.svg}
-\caption{Diagramme des composants du système\label{diagram_components}}
-\end{figure}
-
-\hypertarget{processus-de-duxe9ploiement-initial}{%
-\section{Processus de déploiement
-initial}\label{processus-de-duxe9ploiement-initial}}
-
-\textbf{TODO: décrire pas à pas les différentes étapes du processus de
-déploiement telles que montrées sur le diagramme.}
-
-Les différentes étapes du processus de déploiement d'images sont
-décrites dans la figure \ref{diagram_activity_deployment} qui est un
-diagrame d'activité détaillant les différentes étapes du processus de
-déploiement d'images.
-
-\begin{figure}
-\centering
-\includegraphics{images/diagram_activity_deployment.svg}
-\caption{Diagramme d'activité du processus de déploiement
-initial\label{diagram_activity_deployment}}
-\end{figure}
-
-\hypertarget{architecture-ruxe9seau-initiale}{%
-\section{Architecture réseau
-initiale}\label{architecture-ruxe9seau-initiale}}
-
-Pour faire fonctionner le système, il faut que les machines clientes et
-le serveur puissent communiquer à travers un réseau local.
-
-Les tests ont été effectués dans un réseau domestique classique: une
-\emph{box} internet sert à la fois de passerelle internet et de routeur
-DHCP dans le réseau local.
-
-Il y a un problème pour tester le système dans ce réseau local: le
-serveur de déploiement doit aussi jouer le rôle de serveur DHCP et il y
-aura des collisions entre les deux. La solution choisie pour palier à ce
-problème, est d'utiliser deux interfaces réseau sur le serveur pour le
-connecter à deux réseaux locaux distincts.
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\item
-  L'interface \texttt{eth0} du serveur de déploiement est connectée au
-  réseau \texttt{192.168.1.0/24}, dont les adresses IP sont distribuées
-  par la box internet, qui sert aussi de passerelle vers internet.
-\item
-  L'interface \texttt{eth1} du serveur de déploiement est connectée au
-  réseau \texttt{192.168.56.0/24}, dont les adresses IP sont distribuées
-  par le serveur de déploiement d'images. Il n'y a pas de passerelle
-  vers internet.
-\end{enumerate}
-
-Le serveur étant une machine virtuelle \emph{VirtualBox} créée par
-l'outil \emph{Vagrant}, ses interfaces réseau sont aussi virtuelles. Ces
-interfaces virtuelles ont été ratachées aux interfaces de la machine
-hôte de la manière suivante:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  L'interface \texttt{eth0} de la machine virtuelle est ratachée à
-  l'interface \texttt{wlan0} de la machine hôte en utilisant le mode
-  \protect\hyperlink{acronym__NAT}{NAT}.
-\item
-  L'interface \texttt{eth1} de la machine virtuelle est ratachée à
-  l'interface \texttt{eth0} de la machine hôte en utilisant le mode
-  \texttt{bridged}.
-\end{enumerate}
-
-La figure \ref{diagram_home_network} illustre les détails de la
-configuration réseau décrite ci-dessus.
-
-\begin{figure}
-\centering
-\includegraphics{images/diagram_home_network.svg}
-\caption{Diagramme montrant la configuration des équipements réseaux
-utilisée pendant le test du système
-initial.\label{diagram_home_network}}
-\end{figure}
-
-\hypertarget{mise-en-opuxe9ration-du-projet-initial}{%
-\section{Mise en opération du projet
-initial}\label{mise-en-opuxe9ration-du-projet-initial}}
-
-La mise en fonctionnement du système initial à partir de la
-documentation et des fichiers du dépôt git a été fastidieuse car il
-contient des fichiers de configuration, des binaires et des sources et
-des scripts non documentés. Il faut parcourir les différents fichiers
-\texttt{readme} éparpillés dans les dossiers pour tenter de comprendre
-comment installer un serveur. Aussi, certaines configurations ne
-semblaient pas être à jour et ne fonctionnaient pas en étant utilisées
-telles quel.
-
-La configuration du serveur \protect\hyperlink{acronym__DHCP}{DHCP} a du
-être modifiée pour qu'en plus du
-\texttt{option\ tftp-server-name\ "192.168.56.100"}, le paramètre
-\texttt{next-server\ 192.168.56.100} soit aussi envoyé aux clients. Le
-premier paramètre sert au client à savoir sur quel serveur TFTP
-l'exécutable d'amorçage (dans ce cas,
-\protect\hyperlink{acronym__GRUB}{GRUB}) doit être téléchargé.
-Cependant, une fois \protect\hyperlink{acronym__GRUB}{GRUB} démarré, il
-n'était pas capable de trouver l'image du système linux de déploiement.
-L'option \texttt{next-server} a permis de renseigner
-\protect\hyperlink{acronym__GRUB}{GRUB} sur le fait qu'il doit par
-défaut rechercher les fichiers mentionnés dans la configuration dans le
-serveur \protect\hyperlink{acronym__TFTP}{TFTP} accessible par l'adresse
-IP mentionnée.
-
-Ensuite, une fois capable de démarrer l'OS de déploiement, il a fallu
-résoudre de nombreux petits bugs dans les scripts de déploiement, qui ne
-s'exécutaient pas complètement à cause d'erreurs dans certaines
-commandes. Une fois les scripts corrigés, le démarrage de l'image
-déployée ne fonctionnait pas. Pour des raisons non documentées,
-\protect\hyperlink{acronym__GRUB}{GRUB} était configuré pour lancer le
-programme \texttt{ipxe} depuis le serveur
-\protect\hyperlink{acronym__TFTP}{TFTP}, qui lui même initie le
-démarrage depuis le premier disque. Ce système ne fonctionnait pas:
-\texttt{ipxe} ne se lançait même pas à cause d'un chemin invalide. De
-plus ce système rajoutait une étape inutile:
-\protect\hyperlink{acronym__GRUB}{GRUB} est tout à fait capable de
-démarrer sur le premier disque. Le fichier de configuration de
-\protect\hyperlink{acronym__GRUB}{GRUB} a donc été modifié pour
-directement démarrer sur le disque quand la signature est détectée à la
-fin du disque. Enfin, le système était fonctionnel.
-
-Pour faciliter l'utilisation et le développement du système dans le
-futur, il a été décidé d'automatiser la création d'une machine virtuelle
-du serveur, afin que la mise en fonctionnement d'un nouveau serveur de
-déploiement d'images soit le plus simple possible nécessite le moins
-d'intervention possible. Le programme \emph{Vagrant} a été utilisé dans
-un premier temps pour automatiser la création d'une machine virtuelle à
-partir d'un fichier \texttt{Vagrantfile} définissant la configuration de
-la machine et les commandes à lancer pour l'installer et la configurer.
-Une fois ce fichier de configuration créé, une seule commande est
-nécessaire pour créer, configurer et lancer un serveur fonctionnel dans
-une machine virtuelle: \texttt{vagrant\ up}.
-
-\begin{figure}
-\centering
-\includegraphics{images/vagrant_logo.svg}
-\caption{Logo du logiciel \emph{Vagrant} utilisé pour automatiser la
-création du serveur du système initial.}
-\end{figure}
-
-La distribution \emph{Linux} \emph{Debian} a été choisie comme
-\protect\hyperlink{acronym__OS}{OS} de base de cette machine virtuelle,
-car elle est \emph{open-source}, populaire, stable et dispose de
-nombreux paquets. Elle est utilisée dans la version \emph{Buster}, qui
-est la version stable au moment de ce travail.
-
-\begin{figure}
-\centering
-\includegraphics{images/debian_logo.svg}
-\caption{Logo de la distribution \emph{Linux} \emph{Debian} utilisée
-comme base du serveur.}
-\end{figure}
-
-\hypertarget{limitations-du-projet-initial}{%
-\section{Limitations du projet
-initial}\label{limitations-du-projet-initial}}
-
-Bien que le système du projet initial ait pu être mis en fonctionnement,
-il comporte de nombreuses limitations auxquelles il faudrait palier:
-
-\begin{itemize}
-\tightlist
-\item
-  Les systèmes EFI ne sont pas supportés.
-\item
-  Les images prennent beaucoup de place et sont longues à transférer.
-\item
-  Les grosses images prennent beaucoup de temps à être déployées.
-\item
-  La création d'images nécessite plusieurs opérations en ligne de
-  commande, ce n'est pas très facile à utiliser.
-\item
-  Les scripts de déploiement sont fragiles et gèrent mal les erreurs.
-\item
-  Il n'y a pas de système de personnalisation d'image. Si on veut faire
-  \(n\) personnalisation partant sur la base du même
-  \protect\hyperlink{acronym__OS}{OS}, il faut faire \(n\) images: une
-  pour chaque personnalisation.
-\item
-  L'installation de nouveaux outils sur le système d'exploitation de
-  l'\protect\hyperlink{acronym__OS}{OS} de déploiement créé avec
-  \emph{Buildroot} peut être compliqué si l'outil a beaucoup de
-  dépendances.
-\item
-  Les dépendances du projet sont difficile à reproduire: il faut
-  disposer des bonnes dépendances et du bon environnement.
-\item
-  Les scripts de déploiement ne fonctionnent que si le client utilise
-  une interface réseau nommée \texttt{eth0}.
-\item
-  Les logs sauvés sur le serveur ne sont pas très complets et il est
-  difficile de diagnostiquer les erreurs et les timings des différentes
-  étapes à partir de ceux-ci.
-\item
-  Le système de déploiement doit sauver et restaurer un
-  \protect\hyperlink{acronym__MBR}{MBR} sur le serveur pour utiliser sa
-  partition cachée de cache des images. Cela implique des
-  lectures/écritures sur le disque et sur le partage NFS du serveur qui
-  prennent du temps et rajoutent de la complexité. Étant donné que la
-  position du cache est fixe (elle est calculée à partir de la taille du
-  disque, qui ne devrait pas changer), le client devrait être capable de
-  détecter et monter la partition sans dépendre du serveur.
-\end{itemize}
-
-\hypertarget{recherche-et-duxe9veloppement}{%
-\chapter{Recherche et
-développement}\label{recherche-et-duxe9veloppement}}
-
-\hypertarget{compatibilituxe9-efi}{%
-\section{\texorpdfstring{Compatibilité
-\protect\hyperlink{acronym__EFI}{EFI}}{Compatibilité EFI}}\label{compatibilituxe9-efi}}
-
-Lors des tests du système initial sur les PC fournis par l'école (DELL
-Optiplex 7060 micro), il s'est avéré que bien que le système de
-déploiement était fonctionnel, l'initialisation des images
-d'\protect\hyperlink{acronym__OS}{OS} qui venaient d'être déployées par
-le logiciel d'amorçage \protect\hyperlink{acronym__GRUB}{GRUB} ne
-fonctionnait pas: un écran noir était affiché, avec parfois une suite de
-caractères étranges affichée à l'écran, parfois non, alors que sur des
-machines virtuelles \emph{VirtualBox}, le démarrage des mêmes images ne
-posait aucun problème.
-
-Ces mini-ordinateurs sont capables de démarrer sur le réseau avec le
-protocole \protect\hyperlink{acronym__PXE}{PXE} en mode émulation
-\emph{legacy} ou en mode natif \protect\hyperlink{acronym__EFI}{EFI}. Le
-système initial fonctionne uniquement en mode \emph{legacy} et il est
-soupçonné que c'est un bug ou une limitation dans l'émulation du mode
-\emph{legacy} sur ces machines qui empêchait le démarrage de
-l'\protect\hyperlink{acronym__OS}{OS} déployé, bien qu'il n'ait pas été
-possible de le prouver avec certitude.
-
-Cela a conduit à effectuer un autre test sur un ordinateur portable
-personnel à disposition (Lenovo U530), sur lequel il s'est avéré que le
-boot \protect\hyperlink{acronym__PXE}{PXE} \emph{legacy} n'était même
-pas supporté: seul le démarrage en mode
-\protect\hyperlink{acronym__EFI}{EFI} était possible.
-
-À ce moment, il a été décidé de modifier le système pour le rendre
-compatible
-\protect\hyperlink{acronym__EFI}{EFI}/\protect\hyperlink{acronym__UEFI}{UEFI},
-en partant du principe qu'il serait utilisé sur des
-\protect\hyperlink{acronym__PC}{PC} récents qui sont compatibles avec ce
-mode de démarrage.
-
-La première étape de cette transition vers
-\protect\hyperlink{acronym__EFI}{EFI} a été de recompiler le logiciel
-d'amorçage \protect\hyperlink{acronym__GRUB}{GRUB} dans sa version
-\protect\hyperlink{acronym__EFI}{EFI} pour une architecture x86 64 bits.
-Jusqu'à présent, l'exécutable déjà compilé de
-\protect\hyperlink{acronym__GRUB}{GRUB} présent dans les dossiers du
-projet initial avait été utilisé. Il avait été compilé pour une
-architecture x86 32 bits en mode \protect\hyperlink{acronym__PC}{PC}
-\emph{legacy} uniquement. La compilation du système est nécessaire car
-le système de déploiement initial comporte un module
-\protect\hyperlink{acronym__GRUB}{GRUB} développé spécifiquement pour le
-projet, qui permet d'effectuer la vérification et l'effacement de la
-signature à la fin du disque et de changer l'option de démarrage par
-défaut en fonction de sa présence. Il n'est donc pas possible d'utiliser
-un exécutable déjà compilé de \protect\hyperlink{acronym__GRUB}{GRUB}
-car il faut que ce module soit aussi compilé.
-
-Dans le projet initial, le code source de
-\protect\hyperlink{acronym__GRUB}{GRUB} dans sa version 2.02 avait
-simplement été recopié dans un dossier du dépôt git, le fichier source
-du module de vérification de la signature \texttt{isign.c} avait été
-rajouté au code source et les fichiers de \texttt{Makefile} avaient été
-modifiés pour que le nouveau module soit compilé. Le problème avec cette
-approche est qu'il est difficile de mettre à jour
-\protect\hyperlink{acronym__GRUB}{GRUB} sur une nouvelle version.
-
-Une nouvelle approche a été choisie pour intégrer le module
-\texttt{isign} à \protect\hyperlink{acronym__GRUB}{GRUB}, qui permet de
-mettre à jour plus facilement \protect\hyperlink{acronym__GRUB}{GRUB},
-qui a d'ailleurs été utilisé en version 2.04, la dernière version sortie
-au moment où cela a été fait. La nouvelle approche est la suivante:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  Un clone du dépôt officiel de \protect\hyperlink{acronym__GRUB}{GRUB}
-  a été créé sur le serveur git de
-  \protect\hyperlink{acronym__HEPIA}{HEPIA}. Il a été nommé
-  \texttt{bootiful-grub}.
-\item
-  Un commit a été fait sur ce clone du dépôt git, contenant l'ajout du
-  fichier source \texttt{isign.c} et la modification du fichier générant
-  le \texttt{Makefile} pour prendre en compte ce module lors de la
-  compilation.
-\item
-  Le dépôt git cloné a été rajouté comme sous module du dépôt principal
-  du projet \emph{Bootiful} dans le sous dossier
-  \texttt{grub/bootiful-grub}.
-\end{enumerate}
-
-L'avantage de cette nouvelle approche est qu'il est maintenant facile
-d'intégrer les changements survenus dans le dépôt git officiel sur son
-clone pour bénéficier des dernières mises à jour de
-\protect\hyperlink{acronym__GRUB}{GRUB}.
-
-\textbf{TODO: expliquer les problèmes rencontrés sans
-\protect\hyperlink{acronym__EFI}{EFI} avec lesmachines récentes, des
-modifications nécessaires pour supporter ce nouveau système et des
-limitations que cela apporte.}
-
-\hypertarget{amuxe9lioration-de-la-vitesse-de-transfert-des-images}{%
-\section{Amélioration de la vitesse de transfert des
-images}\label{amuxe9lioration-de-la-vitesse-de-transfert-des-images}}
-
-Le protocole \protect\hyperlink{acronym__NFS}{NFS} est utilisé dans le
-système initial pour transférer une image depuis le client vers le
-serveur. Peut-être que la vitesse de transfert des images à travers le
-réseau pourrait être améliorée en utilisant un autre protocole. Pour
-décider si le choix de ce protocole est adapté ou si au contraire il
-serait bénéfique d'en utiliser un autre, la vitesse de transfert d'une
-grosse image a été mesurée sur différents protocoles de transfert de
-fichier.
-
-\hypertarget{protocoles-considuxe9ruxe9s}{%
-\subsection{Protocoles considérés}\label{protocoles-considuxe9ruxe9s}}
-
-Les différents protocoles qui ont été mesurés sont:
-
-\begin{itemize}
-\tightlist
-\item
-  \protect\hyperlink{acronym__SCP}{SCP}: ce protocole, utilisable avec
-  le programme éponyme \texttt{scp}, permet le transfert de fichiers
-  sécurisé entre un client et un serveur utilisant le protocole d'accès
-  à distance sécurisé \protect\hyperlink{acronym__SSH}{SSH}. Bien que le
-  chiffrage de la communication n'est pas nécessaire dans notre cas, il
-  est intéressant d'observer si ce dernier a un impact sur le temps de
-  transfert.
-\item
-  \protect\hyperlink{acronym__HTTP}{HTTP}: c'est le protocole
-  client-serveur utilisé sur le World Wide Web
-  (\protect\hyperlink{acronym__WWW}{WWW}) pour la communication entre en
-  les navigateurs (client) et les serveurs. Il est souvent utilisé pour
-  le téléchargement de fichiers sur internet et offre probablement des
-  performances acceptables. Il existe aussi une version chiffrée de ce
-  protocole, \protect\hyperlink{acronym__HTTPS}{HTTPS}, mais uniquement
-  la version non-chiffrée sera testée ici, car le chiffrement de la
-  communication ne semble pas nécessaire et pourrait impacter les
-  performances.
-\item
-  \protect\hyperlink{acronym__FTP}{FTP}: ce protocole standard fait
-  exactement ce que nous avons besoin: transférer des fichiers à travers
-  le réseau. Il y a de forte chances qu'il offre de très bonnes
-  performances.
-\item
-  \protect\hyperlink{acronym__NFS}{NFS}: le protocole standard pour
-  monter à distance des dossiers partagés entre des
-  \protect\hyperlink{acronym__OS}{OS} Linux. C'est ce système qui est
-  utilisé par le projet initial, mais ce n'est probablement pas le plus
-  rapide, car permet de faire plus qu'un simple transfert de fichiers.
-\item
-  \protect\hyperlink{acronym__SMB}{SMB}: le protocole standard pour
-  monter à distance des dossier partagés entre des
-  \protect\hyperlink{acronym__OS}{OS} Windows. Une implémentation existe
-  sous linux, \emph{Samba}, et elle est courremment utilisée pour une
-  meilleure compatiblité avec les systèmes Windows que sont équivalent
-  \protect\hyperlink{acronym__NFS}{NFS}.
-\item
-  \protect\hyperlink{acronym__IPFS}{IPFS}: ce protocole pair à pair
-  décentralisé permet à chacun de des pairs de mettre à disposition ou
-  de télécharger des fichiers. Il pourrait être intéressant d'utiliser
-  ce protocole pour soulager la charge du serveur, car tous les clients
-  connectés peuvent se partager des parties d'images qu'ils ont déjà. Le
-  serveur de déploiement ne serait qu'un pair de plus, qui dispose de
-  toutes les images. Il est cependant possible que ce protocole ne soit
-  pas le plus performant à cause de sa jeunesse et de son mode de
-  fonctionnement complexe qui apporte un surcout à l'échange, en tout
-  cas dans le cas ou il n'y a que deux pairs.
-\end{itemize}
-
-\hypertarget{environnement-des-tests-de-performance-des-protocoles-de-transfert-de-fichiers}{%
-\subsection{Environnement des tests de performance des protocoles de
-transfert de
-fichiers}\label{environnement-des-tests-de-performance-des-protocoles-de-transfert-de-fichiers}}
-
-Deux machines de test identiques ont été utilisées: il s'agit de mini-PC
-DELL Optiplex 7060 micro avec les spécifications suivantes:
-
-\begin{itemize}
-\tightlist
-\item
-  Processeur: Intel® Core™ i7-8700 CPU cadencé à 3.20GHz,
-\item
-  Mémoire vive: 8 GiB (2 barettes 4GiB SODIMM DDR4 Synchronous 2666 MHz
-  (0.4 ns))
-\item
-  Disque: TOSHIBA KSG60ZMV SSD 476GiB (512GB)
-\item
-  Réseau: Intel e1000e Gigabit Ethernet
-\end{itemize}
-
-Les deux machines de test sont connectées en réseau avec un switch
-Gigabit Ethernet. Le système d'exploitation Debian 10.4.0 (nom de code
-\emph{buster}) AMD64 a été installé sur deux machines de test, sans
-interface graphique. La première machine est nommée \texttt{debian1} et
-la seconde \texttt{debian2}. Les noms \texttt{debian1.home} et
-\texttt{debian2.home} permettent aux deux machines de communiquer entre
-elles en faisant abstraction de leur adresse
-\protect\hyperlink{acronym__IP}{IP}. L'utilisateur \texttt{debian} avec
-le mot de passe \texttt{debian} est utilisé sur chacune des deux
-machines.
-
-Le fichier à copier, \texttt{win10.tar.gz} est une image brute de
-windows 10 compressée avec \texttt{gzip}, qui fait une taille totale de
-13743592907 B (12.8 GiB). Il est présent dans le dossier
-\texttt{/home/debian} de la machine \texttt{debian1}.
-
-La commande \texttt{perf} est utilisée pour tester 4 exécutions d'une
-commande de copie lancée depuis la machine \texttt{debian2}. Elle est
-installée à l'aide de la commande suivante:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{apt}\NormalTok{ install linux{-}perf}
-\end{Highlighting}
-\end{Shaded}
-
-Pour faire fonctionner la commande sans être root, le kernel doit être
-configuré avec la commande suivante:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\BuiltInTok{echo}\NormalTok{ 1 }\OperatorTok{\textgreater{}}\NormalTok{ /proc/sys/kernel/perf\_event\_paranoid}
-\end{Highlighting}
-\end{Shaded}
-
-Les sections suivantes détaillent les configurations spécifiques à
-chaque protocole effectuées sur chacune des machines et les résultats du
-test. La dernière section récapitule les résultats et explique quel
-protocole est choisi pour la suite du travail et pourquoi.
-
-\hypertarget{tests-de-performance-du-protocole-de-transfert-de-fichiers-scp}{%
-\subsection{\texorpdfstring{Tests de performance du protocole de
-transfert de fichiers
-\protect\hyperlink{acronym__SCP}{SCP}}{Tests de performance du protocole de transfert de fichiers SCP}}\label{tests-de-performance-du-protocole-de-transfert-de-fichiers-scp}}
-
-Tout d'abord, des clés SSH ont été générées sur chaque machine avec la
-commande suivante:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\FunctionTok{ssh{-}keygen}
-\end{Highlighting}
-\end{Shaded}
-
-Ensuite, les clés ont été échangées. Sur \texttt{debian1}, la commande
-suivante a été utilisée:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{ssh{-}copy{-}id}\NormalTok{ debian2.home}
-\end{Highlighting}
-\end{Shaded}
-
-Sur \texttt{debian2}, la commande suivante a été utilisée:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{ssh{-}copy{-}id}\NormalTok{ debian1.home}
-\end{Highlighting}
-\end{Shaded}
-
-Finalement, le benchmark de la copie a été lancé sur \texttt{debian2}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\ExtensionTok{perf}\NormalTok{ stat {-}r 4 {-}d scp debian1.home:/home/debian/win10.tar.gz /home/debian/win10.tar.gz}
-\ExtensionTok{win10.tar.gz}\NormalTok{                                                                       100\%   13GB 109.6MB/s   01:59    }
-\ExtensionTok{win10.tar.gz}\NormalTok{                                                                       100\%   13GB 109.6MB/s   01:59    }
-\ExtensionTok{win10.tar.gz}\NormalTok{                                                                       100\%   13GB 109.7MB/s   01:59    }
-\ExtensionTok{win10.tar.gz}\NormalTok{                                                                       100\%   13GB 109.6MB/s   01:59    }
-
- \ExtensionTok{Performance}\NormalTok{ counter stats for }\StringTok{\textquotesingle{}scp debian1.home:/home/debian/win10.tar.gz /home/debian/win10.tar.gz\textquotesingle{}}\NormalTok{ (4 runs)}\BuiltInTok{:}
-
-         \ExtensionTok{60}\NormalTok{,349.20 msec task{-}clock                \#    0.504 CPUs utilized            ( +{-}  3.61\% )}
-           \ExtensionTok{808}\NormalTok{,243      context{-}switches          \#    0.013 M/sec                    ( +{-}  0.26\% )}
-                \ExtensionTok{16}\NormalTok{      cpu{-}migrations            \#    0.000 K/sec                    ( +{-} 14.73\% )}
-            \ExtensionTok{16}\NormalTok{,862      page{-}faults               \#    0.279 K/sec                    ( +{-} 18.95\% )}
-   \ExtensionTok{191}\NormalTok{,612,352,176      cycles                    \#    3.175 GHz                      ( +{-}  0.33\% )  }\KeywordTok{(}\ExtensionTok{50.09\%}\KeywordTok{)}
-   \ExtensionTok{406}\NormalTok{,400,076,305      instructions              \#    2.12  insn per cycle           ( +{-}  0.25\% )  }\KeywordTok{(}\ExtensionTok{62.64\%}\KeywordTok{)}
-    \ExtensionTok{13}\NormalTok{,334,327,547      branches                  \#  220.953 M/sec                    ( +{-}  1.42\% )  }\KeywordTok{(}\ExtensionTok{62.43\%}\KeywordTok{)}
-       \ExtensionTok{246}\NormalTok{,499,018      branch{-}misses             \#    1.85\% of all branches          ( +{-}  3.10\% )  }\KeywordTok{(}\ExtensionTok{62.36\%}\KeywordTok{)}
-    \ExtensionTok{64}\NormalTok{,653,696,732      L1{-}dcache{-}loads           \# 1071.326 M/sec                    ( +{-}  0.44\% )  }\KeywordTok{(}\ExtensionTok{62.40\%}\KeywordTok{)}
-     \ExtensionTok{4}\NormalTok{,559,992,550      L1{-}dcache{-}load{-}misses     \#    7.05\% of all L1{-}dcache hits    ( +{-}  0.41\% )  }\KeywordTok{(}\ExtensionTok{62.43\%}\KeywordTok{)}
-       \ExtensionTok{784}\NormalTok{,218,339      LLC{-}loads                 \#   12.995 M/sec                    ( +{-}  0.64\% )  }\KeywordTok{(}\ExtensionTok{50.01\%}\KeywordTok{)}
-       \ExtensionTok{121}\NormalTok{,317,304      LLC{-}load{-}misses           \#   15.47\% of all LL{-}cache hits     ( +{-}  0.52\% )  }\KeywordTok{(}\ExtensionTok{50.29\%}\KeywordTok{)}
-
-          \ExtensionTok{119.8094}\NormalTok{ +{-} 0.0182 seconds time elapsed  ( +{-}  0.02\% )}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tests-de-performance-du-protocole-de-transfert-de-fichiers-http}{%
-\subsection{\texorpdfstring{Tests de performance du protocole de
-transfert de fichiers
-\protect\hyperlink{acronym__HTTP}{HTTP}}{Tests de performance du protocole de transfert de fichiers HTTP}}\label{tests-de-performance-du-protocole-de-transfert-de-fichiers-http}}
-
-Le serveur \protect\hyperlink{acronym__HTTP}{HTTP} \emph{Apache} a été
-installé sur la machine \texttt{debian1} et le fichier a été mis à
-disposition sur ce serveur avec les commandes suivantes:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{apt}\NormalTok{ install apache2}
-\FunctionTok{cp}\NormalTok{ win10.tar.gz /var/www/html/}
-\end{Highlighting}
-\end{Shaded}
-
-Finalement, le benchmark du téléchargement du fichier avec la commande
-\texttt{wget} a été lancé sur \texttt{debian2}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\ExtensionTok{perf}\NormalTok{ stat {-}r 4 {-}d wget http://debian1.home/win10.tar.gz}
-\ExtensionTok{{-}{-}2020{-}05{-}20}\NormalTok{ 09:53:53{-}{-}  http://debian1.home/win10.tar.gz}
-\ExtensionTok{Resolving}\NormalTok{ debian1.home (debian1.home)}\ExtensionTok{...}\NormalTok{ 2a02:120b:c3e2:cab0:e6b9:7aff:feed:e0cd, 192.168.1.29}
-\ExtensionTok{Connecting}\NormalTok{ to debian1.home (debian1.home)}\KeywordTok{|}\ExtensionTok{2a02}\NormalTok{:120b:c3e2:cab0:e6b9:7aff:feed:e0cd}\KeywordTok{|}\NormalTok{:}\ExtensionTok{80...}\NormalTok{ connected.}
-\ExtensionTok{HTTP}\NormalTok{ request sent, awaiting response... 200 OK}
-\ExtensionTok{Length}\NormalTok{: 13743592907 (13G) [}\ExtensionTok{application}\NormalTok{/}\ExtensionTok{x{-}gzip}\NormalTok{]}
-\ExtensionTok{Saving}\NormalTok{ to: ‘win10.tar.gz.2’}
-
-\ExtensionTok{win10.tar.gz.2}\NormalTok{                100\%[==============================================}\OperatorTok{\textgreater{}}\NormalTok{]  12.80G   110MB/s    in 2m 0s   }
-
-\ExtensionTok{2020{-}05{-}20}\NormalTok{ 09:55:53 (110 MB/s) }\ExtensionTok{{-}}\NormalTok{ ‘win10.tar.gz.2’ saved [13743592907/13743592907]}
-
-\ExtensionTok{{-}{-}2020{-}05{-}20}\NormalTok{ 09:55:53{-}{-}  http://debian1.home/win10.tar.gz}
-\ExtensionTok{Resolving}\NormalTok{ debian1.home (debian1.home)}\ExtensionTok{...}\NormalTok{ 2a02:120b:c3e2:cab0:e6b9:7aff:feed:e0cd, 192.168.1.29}
-\ExtensionTok{Connecting}\NormalTok{ to debian1.home (debian1.home)}\KeywordTok{|}\ExtensionTok{2a02}\NormalTok{:120b:c3e2:cab0:e6b9:7aff:feed:e0cd}\KeywordTok{|}\NormalTok{:}\ExtensionTok{80...}\NormalTok{ connected.}
-\ExtensionTok{HTTP}\NormalTok{ request sent, awaiting response... 200 OK}
-\ExtensionTok{Length}\NormalTok{: 13743592907 (13G) [}\ExtensionTok{application}\NormalTok{/}\ExtensionTok{x{-}gzip}\NormalTok{]}
-\ExtensionTok{Saving}\NormalTok{ to: ‘win10.tar.gz.3’}
-
-\ExtensionTok{win10.tar.gz.3}\NormalTok{                100\%[==============================================}\OperatorTok{\textgreater{}}\NormalTok{]  12.80G   108MB/s    in 2m 0s   }
-
-\ExtensionTok{2020{-}05{-}20}\NormalTok{ 09:57:52 (109 MB/s) }\ExtensionTok{{-}}\NormalTok{ ‘win10.tar.gz.3’ saved [13743592907/13743592907]}
-
-\ExtensionTok{{-}{-}2020{-}05{-}20}\NormalTok{ 09:57:52{-}{-}  http://debian1.home/win10.tar.gz}
-\ExtensionTok{Resolving}\NormalTok{ debian1.home (debian1.home)}\ExtensionTok{...}\NormalTok{ 2a02:120b:c3e2:cab0:e6b9:7aff:feed:e0cd, 192.168.1.29}
-\ExtensionTok{Connecting}\NormalTok{ to debian1.home (debian1.home)}\KeywordTok{|}\ExtensionTok{2a02}\NormalTok{:120b:c3e2:cab0:e6b9:7aff:feed:e0cd}\KeywordTok{|}\NormalTok{:}\ExtensionTok{80...}\NormalTok{ connected.}
-\ExtensionTok{HTTP}\NormalTok{ request sent, awaiting response... 200 OK}
-\ExtensionTok{Length}\NormalTok{: 13743592907 (13G) [}\ExtensionTok{application}\NormalTok{/}\ExtensionTok{x{-}gzip}\NormalTok{]}
-\ExtensionTok{Saving}\NormalTok{ to: ‘win10.tar.gz.4’}
-
-\ExtensionTok{win10.tar.gz.4}\NormalTok{                100\%[==============================================}\OperatorTok{\textgreater{}}\NormalTok{]  12.80G   108MB/s    in 2m 1s   }
-
-\ExtensionTok{2020{-}05{-}20}\NormalTok{ 09:59:53 (109 MB/s) }\ExtensionTok{{-}}\NormalTok{ ‘win10.tar.gz.4’ saved [13743592907/13743592907]}
-
-\ExtensionTok{{-}{-}2020{-}05{-}20}\NormalTok{ 09:59:53{-}{-}  http://debian1.home/win10.tar.gz}
-\ExtensionTok{Resolving}\NormalTok{ debian1.home (debian1.home)}\ExtensionTok{...}\NormalTok{ 2a02:120b:c3e2:cab0:e6b9:7aff:feed:e0cd, 192.168.1.29}
-\ExtensionTok{Connecting}\NormalTok{ to debian1.home (debian1.home)}\KeywordTok{|}\ExtensionTok{2a02}\NormalTok{:120b:c3e2:cab0:e6b9:7aff:feed:e0cd}\KeywordTok{|}\NormalTok{:}\ExtensionTok{80...}\NormalTok{ connected.}
-\ExtensionTok{HTTP}\NormalTok{ request sent, awaiting response... 200 OK}
-\ExtensionTok{Length}\NormalTok{: 13743592907 (13G) [}\ExtensionTok{application}\NormalTok{/}\ExtensionTok{x{-}gzip}\NormalTok{]}
-\ExtensionTok{Saving}\NormalTok{ to: ‘win10.tar.gz.5’}
-
-\ExtensionTok{win10.tar.gz.5}\NormalTok{                100\%[==============================================}\OperatorTok{\textgreater{}}\NormalTok{]  12.80G   110MB/s    in 2m 0s   }
-
-\ExtensionTok{2020{-}05{-}20}\NormalTok{ 10:01:52 (110 MB/s) }\ExtensionTok{{-}}\NormalTok{ ‘win10.tar.gz.5’ saved [13743592907/13743592907]}
-
-
- \ExtensionTok{Performance}\NormalTok{ counter stats for }\StringTok{\textquotesingle{}wget http://debian1.home/win10.tar.gz\textquotesingle{}}\NormalTok{ (4 runs)}\BuiltInTok{:}
-
-         \ExtensionTok{46}\NormalTok{,792.73 msec task{-}clock                \#    0.390 CPUs utilized            ( +{-}  0.64\% )}
-           \ExtensionTok{417}\NormalTok{,641      context{-}switches          \#    0.009 M/sec                    ( +{-}  0.31\% )}
-                \ExtensionTok{18}\NormalTok{      cpu{-}migrations            \#    0.000 K/sec                    ( +{-}  8.25\% )}
-               \ExtensionTok{292}\NormalTok{      page{-}faults               \#    0.006 K/sec                    ( +{-}  0.30\% )}
-    \ExtensionTok{61}\NormalTok{,311,321,905      cycles                    \#    1.310 GHz                      ( +{-}  0.25\% )  }\KeywordTok{(}\ExtensionTok{49.71\%}\KeywordTok{)}
-    \ExtensionTok{55}\NormalTok{,652,602,418      instructions              \#    0.91  insn per cycle           ( +{-}  0.20\% )  }\KeywordTok{(}\ExtensionTok{61.93\%}\KeywordTok{)}
-    \ExtensionTok{10}\NormalTok{,835,524,321      branches                  \#  231.564 M/sec                    ( +{-}  0.14\% )  }\KeywordTok{(}\ExtensionTok{62.04\%}\KeywordTok{)}
-       \ExtensionTok{229}\NormalTok{,073,690      branch{-}misses             \#    2.11\% of all branches          ( +{-}  1.03\% )  }\KeywordTok{(}\ExtensionTok{62.77\%}\KeywordTok{)}
-    \ExtensionTok{16}\NormalTok{,218,621,768      L1{-}dcache{-}loads           \#  346.606 M/sec                    ( +{-}  0.16\% )  }\KeywordTok{(}\ExtensionTok{62.94\%}\KeywordTok{)}
-     \ExtensionTok{1}\NormalTok{,767,713,664      L1{-}dcache{-}load{-}misses     \#   10.90\% of all L1{-}dcache hits    ( +{-}  0.17\% )  }\KeywordTok{(}\ExtensionTok{62.78\%}\KeywordTok{)}
-       \ExtensionTok{392}\NormalTok{,258,789      LLC{-}loads                 \#    8.383 M/sec                    ( +{-}  1.79\% )  }\KeywordTok{(}\ExtensionTok{50.19\%}\KeywordTok{)}
-       \ExtensionTok{113}\NormalTok{,116,138      LLC{-}load{-}misses           \#   28.84\% of all LL{-}cache hits     ( +{-}  0.25\% )  }\KeywordTok{(}\ExtensionTok{49.57\%}\KeywordTok{)}
-
-           \ExtensionTok{119.871}\NormalTok{ +{-} 0.235 seconds time elapsed  ( +{-}  0.20\% )}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tests-de-performance-du-protocole-de-transfert-de-fichiers-ftp}{%
-\subsection{\texorpdfstring{Tests de performance du protocole de
-transfert de fichiers
-\protect\hyperlink{acronym__FTP}{FTP}}{Tests de performance du protocole de transfert de fichiers FTP}}\label{tests-de-performance-du-protocole-de-transfert-de-fichiers-ftp}}
-
-Le serveur \protect\hyperlink{acronym__FTP}{FTP} \texttt{vsftpd} a été
-installé sur la machine \texttt{debian1} avec la commande suivante:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{apt}\NormalTok{ install vsftpd}
-\end{Highlighting}
-\end{Shaded}
-
-Le client \protect\hyperlink{acronym__FTP}{FTP} \texttt{ftp} a été
-installé sur la machine \texttt{debian2} avec la commande suivante:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{apt}\NormalTok{ install ftp}
-\end{Highlighting}
-\end{Shaded}
-
-Par défaut, un utilisateur se connecte sur son dossier \texttt{home} sur
-le serveur, donc il n'y a pas besoin de créer de configuration spéciale
-car le fichier à \texttt{win10.tar.gz} est déjà présent dans le dossier
-\texttt{/home/debian}. La commande suivante est lancée pour mesurer le
-temps de transfert:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\ExtensionTok{perf}\NormalTok{ stat {-}r 4 {-}d lftp {-}u debian,debian {-}e }\StringTok{"get {-}e win10.tar.gz;quit"}\NormalTok{ debian1.home}
-\ExtensionTok{13743592907}\NormalTok{ bytes transferred in 120 seconds (109.61 MiB/s)             }
-\ExtensionTok{13743592907}\NormalTok{ bytes transferred in 120 seconds (109.11 MiB/s)             }
-\ExtensionTok{13743592907}\NormalTok{ bytes transferred in 120 seconds (108.81 MiB/s)             }
-\ExtensionTok{13743592907}\NormalTok{ bytes transferred in 120 seconds (109.01 MiB/s)             }
-
- \ExtensionTok{Performance}\NormalTok{ counter stats for }\StringTok{\textquotesingle{}lftp {-}u debian,debian {-}e get {-}e win10.tar.gz;quit debian1.home\textquotesingle{}}\NormalTok{ (4 runs)}\BuiltInTok{:}
-
-         \ExtensionTok{43}\NormalTok{,760.05 msec task{-}clock                \#    0.364 CPUs utilized            ( +{-}  3.19\% )}
-           \ExtensionTok{416}\NormalTok{,480      context{-}switches          \#    0.010 M/sec                    ( +{-}  0.21\% )}
-                \ExtensionTok{20}\NormalTok{      cpu{-}migrations            \#    0.000 K/sec                    ( +{-} 17.44\% )}
-               \ExtensionTok{768}\NormalTok{      page{-}faults               \#    0.018 K/sec                    ( +{-}  1.76\% )}
-    \ExtensionTok{50}\NormalTok{,319,107,200      cycles                    \#    1.150 GHz                      ( +{-}  1.87\% )  }\KeywordTok{(}\ExtensionTok{49.42\%}\KeywordTok{)}
-    \ExtensionTok{41}\NormalTok{,925,907,326      instructions              \#    0.83  insn per cycle           ( +{-}  2.58\% )  }\KeywordTok{(}\ExtensionTok{61.97\%}\KeywordTok{)}
-     \ExtensionTok{8}\NormalTok{,345,354,967      branches                  \#  190.707 M/sec                    ( +{-}  2.51\% )  }\KeywordTok{(}\ExtensionTok{62.63\%}\KeywordTok{)}
-       \ExtensionTok{192}\NormalTok{,939,322      branch{-}misses             \#    2.31\% of all branches          ( +{-}  3.57\% )  }\KeywordTok{(}\ExtensionTok{62.66\%}\KeywordTok{)}
-    \ExtensionTok{12}\NormalTok{,148,795,763      L1{-}dcache{-}loads           \#  277.623 M/sec                    ( +{-}  2.11\% )  }\KeywordTok{(}\ExtensionTok{63.06\%}\KeywordTok{)}
-     \ExtensionTok{1}\NormalTok{,646,404,955      L1{-}dcache{-}load{-}misses     \#   13.55\% of all L1{-}dcache hits    ( +{-}  0.76\% )  }\KeywordTok{(}\ExtensionTok{62.79\%}\KeywordTok{)}
-       \ExtensionTok{516}\NormalTok{,891,020      LLC{-}loads                 \#   11.812 M/sec                    ( +{-}  0.79\% )  }\KeywordTok{(}\ExtensionTok{49.87\%}\KeywordTok{)}
-       \ExtensionTok{112}\NormalTok{,961,435      LLC{-}load{-}misses           \#   21.85\% of all LL{-}cache hits     ( +{-}  0.29\% )  }\KeywordTok{(}\ExtensionTok{49.56\%}\KeywordTok{)}
-
-           \ExtensionTok{120.151}\NormalTok{ +{-} 0.213 seconds time elapsed  ( +{-}  0.18\% )}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tests-de-performance-du-protocole-de-transfert-de-fichiers-nfs}{%
-\subsection{\texorpdfstring{Tests de performance du protocole de
-transfert de fichiers
-\protect\hyperlink{acronym__NFS}{NFS}}{Tests de performance du protocole de transfert de fichiers NFS}}\label{tests-de-performance-du-protocole-de-transfert-de-fichiers-nfs}}
-
-Le serveur \protect\hyperlink{acronym__NFS}{NFS} est installé et
-configuré avec les commandes suivantes sur \texttt{debian1}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{apt}\NormalTok{ install nfs{-}kernel{-}server}
-\FunctionTok{mkdir}\NormalTok{ /nfsroot}
-\FunctionTok{cp}\NormalTok{ win10.tar.gz /nfsroot/}
-\BuiltInTok{echo} \StringTok{\textquotesingle{}/nfsroot/         *(rw,fsid=0,no\_root\_squash,no\_subtree\_check,async,insecure)\textquotesingle{}} \OperatorTok{\textgreater{}\textgreater{}}\NormalTok{ /etc/exports}
-\ExtensionTok{systemctl}\NormalTok{ restart nfs{-}server}
-\end{Highlighting}
-\end{Shaded}
-
-Le client partage est monté sur le client \texttt{debian2} avec les
-commandes suivantes:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\FunctionTok{su}
-\ExtensionTok{apt}\NormalTok{ install nfs{-}common}
-\FunctionTok{mkdir}\NormalTok{ /nfsroot}
-\FunctionTok{mount}\NormalTok{ {-}t nfs debian1.home:/nfsroot /nfsroot}
-\BuiltInTok{exit}
-\end{Highlighting}
-\end{Shaded}
-
-Finalement, le benchmark de la copie a été lancé sur \texttt{debian2}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\ExtensionTok{perf}\NormalTok{ stat {-}r 4 {-}d cp {-}f /nfsroot/win10.tar.gz \textasciitilde{}/win10.tar.gz}
-
- \ExtensionTok{Performance}\NormalTok{ counter stats for }\StringTok{\textquotesingle{}cp {-}f /nfsroot/win10.tar.gz /home/debian/win10.tar.gz\textquotesingle{}}\NormalTok{ (4 runs)}\BuiltInTok{:}
-
-         \ExtensionTok{17}\NormalTok{,076.43 msec task{-}clock                \#    0.142 CPUs utilized            ( +{-}  7.26\% )}
-            \ExtensionTok{13}\NormalTok{,716      context{-}switches          \#    0.803 K/sec                    ( +{-}  3.93\% )}
-                 \ExtensionTok{3}\NormalTok{      cpu{-}migrations            \#    0.000 K/sec                    ( +{-} 22.88\% )}
-               \ExtensionTok{360}\NormalTok{      page{-}faults               \#    0.021 K/sec                    ( +{-}  0.24\% )}
-    \ExtensionTok{29}\NormalTok{,329,681,962      cycles                    \#    1.718 GHz                      ( +{-}  0.84\% )  }\KeywordTok{(}\ExtensionTok{50.10\%}\KeywordTok{)}
-    \ExtensionTok{39}\NormalTok{,303,308,222      instructions              \#    1.34  insn per cycle           ( +{-}  0.27\% )  }\KeywordTok{(}\ExtensionTok{62.64\%}\KeywordTok{)}
-     \ExtensionTok{7}\NormalTok{,592,336,916      branches                  \#  444.609 M/sec                    ( +{-}  0.28\% )  }\KeywordTok{(}\ExtensionTok{62.68\%}\KeywordTok{)}
-        \ExtensionTok{79}\NormalTok{,751,186      branch{-}misses             \#    1.05\% of all branches          ( +{-}  0.28\% )  }\KeywordTok{(}\ExtensionTok{62.46\%}\KeywordTok{)}
-    \ExtensionTok{10}\NormalTok{,749,309,904      L1{-}dcache{-}loads           \#  629.482 M/sec                    ( +{-}  0.40\% )  }\KeywordTok{(}\ExtensionTok{62.54\%}\KeywordTok{)}
-     \ExtensionTok{1}\NormalTok{,097,825,933      L1{-}dcache{-}load{-}misses     \#   10.21\% of all L1{-}dcache hits    ( +{-}  1.45\% )  }\KeywordTok{(}\ExtensionTok{62.44\%}\KeywordTok{)}
-       \ExtensionTok{230}\NormalTok{,105,352      LLC{-}loads                 \#   13.475 M/sec                    ( +{-}  1.25\% )  }\KeywordTok{(}\ExtensionTok{49.92\%}\KeywordTok{)}
-        \ExtensionTok{13}\NormalTok{,665,720      LLC{-}load{-}misses           \#    5.94\% of all LL{-}cache hits     ( +{-}  8.55\% )  }\KeywordTok{(}\ExtensionTok{49.87\%}\KeywordTok{)}
-
-           \ExtensionTok{120.417}\NormalTok{ +{-} 0.119 seconds time elapsed  ( +{-}  0.10\% )}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tests-de-performance-du-protocole-de-transfert-de-fichiers-smb}{%
-\subsection{\texorpdfstring{Tests de performance du protocole de
-transfert de fichiers
-\protect\hyperlink{acronym__SMB}{SMB}}{Tests de performance du protocole de transfert de fichiers SMB}}\label{tests-de-performance-du-protocole-de-transfert-de-fichiers-smb}}
-
-Le serveur \protect\hyperlink{acronym__SMB}{SMB} \texttt{samba} est
-installé et configuré avec les commandes suivantes sur \texttt{debian1}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{apt}\NormalTok{ install samba}
-\ExtensionTok{smbpasswd}\NormalTok{ {-}a debian }
-\FunctionTok{cat} \StringTok{\textquotesingle{}[debian]}
-\StringTok{path = /home/debian}
-\StringTok{valid users = debian}
-\StringTok{read only = no\textquotesingle{}} \OperatorTok{\textgreater{}\textgreater{}}\NormalTok{ /etc/samba/smb.conf}
-\ExtensionTok{systemctl}\NormalTok{ restart smbd}
-\end{Highlighting}
-\end{Shaded}
-
-Le client \protect\hyperlink{acronym__SMB}{SMB} \texttt{samba} est
-installé sur le client avec la commande suivante:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{apt}\NormalTok{ install samba{-}client}
-\end{Highlighting}
-\end{Shaded}
-
-Finalement, le benchmark de la copie est lancé sur \texttt{debian2}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\ExtensionTok{perf}\NormalTok{ stat {-}r 4 {-}d smbclient {-}U debian\%debian //debian1.home/debian {-}c }\StringTok{\textquotesingle{}get win10.tar.gz\textquotesingle{}}
-\ExtensionTok{Unable}\NormalTok{ to initialize messaging context}
-\ExtensionTok{getting}\NormalTok{ file \textbackslash{}win10.tar.gz of size 13743592907 as win10.tar.gz (109684.9 KiloBytes/sec) }\KeywordTok{(}\ExtensionTok{average}\NormalTok{ 109684.9 KiloBytes/sec}\KeywordTok{)}
-\ExtensionTok{Unable}\NormalTok{ to initialize messaging context}
-\ExtensionTok{getting}\NormalTok{ file \textbackslash{}win10.tar.gz of size 13743592907 as win10.tar.gz (109443.4 KiloBytes/sec) }\KeywordTok{(}\ExtensionTok{average}\NormalTok{ 109443.4 KiloBytes/sec}\KeywordTok{)}
-\ExtensionTok{Unable}\NormalTok{ to initialize messaging context}
-\ExtensionTok{getting}\NormalTok{ file \textbackslash{}win10.tar.gz of size 13743592907 as win10.tar.gz (110095.1 KiloBytes/sec) }\KeywordTok{(}\ExtensionTok{average}\NormalTok{ 110095.1 KiloBytes/sec}\KeywordTok{)}
-\ExtensionTok{Unable}\NormalTok{ to initialize messaging context}
-\ExtensionTok{getting}\NormalTok{ file \textbackslash{}win10.tar.gz of size 13743592907 as win10.tar.gz (109244.7 KiloBytes/sec) }\KeywordTok{(}\ExtensionTok{average}\NormalTok{ 109244.7 KiloBytes/sec}\KeywordTok{)}
-
- \ExtensionTok{Performance}\NormalTok{ counter stats for }\StringTok{\textquotesingle{}smbclient {-}U debian\%debian //debian1.home/debian {-}c get win10.tar.gz\textquotesingle{}}\NormalTok{ (4 runs)}\BuiltInTok{:}
-
-         \ExtensionTok{35}\NormalTok{,488.67 msec task{-}clock                \#    0.290 CPUs utilized            ( +{-}  0.49\% )}
-           \ExtensionTok{352}\NormalTok{,535      context{-}switches          \#    0.010 M/sec                    ( +{-}  0.24\% )}
-                \ExtensionTok{14}\NormalTok{      cpu{-}migrations            \#    0.000 K/sec                    ( +{-} 19.12\% )}
-             \ExtensionTok{3}\NormalTok{,915      page{-}faults               \#    0.110 K/sec                    ( +{-}  3.20\% )}
-    \ExtensionTok{35}\NormalTok{,420,663,303      cycles                    \#    0.998 GHz                      ( +{-}  0.45\% )  }\KeywordTok{(}\ExtensionTok{50.50\%}\KeywordTok{)}
-    \ExtensionTok{35}\NormalTok{,124,728,140      instructions              \#    0.99  insn per cycle           ( +{-}  2.40\% )  }\KeywordTok{(}\ExtensionTok{62.99\%}\KeywordTok{)}
-     \ExtensionTok{6}\NormalTok{,843,251,403      branches                  \#  192.829 M/sec                    ( +{-}  2.43\% )  }\KeywordTok{(}\ExtensionTok{62.60\%}\KeywordTok{)}
-       \ExtensionTok{115}\NormalTok{,346,267      branch{-}misses             \#    1.69\% of all branches          ( +{-}  1.05\% )  }\KeywordTok{(}\ExtensionTok{62.27\%}\KeywordTok{)}
-     \ExtensionTok{9}\NormalTok{,922,177,546      L1{-}dcache{-}loads           \#  279.587 M/sec                    ( +{-}  1.82\% )  }\KeywordTok{(}\ExtensionTok{61.98\%}\KeywordTok{)}
-     \ExtensionTok{1}\NormalTok{,307,137,276      L1{-}dcache{-}load{-}misses     \#   13.17\% of all L1{-}dcache hits    ( +{-}  0.23\% )  }\KeywordTok{(}\ExtensionTok{62.22\%}\KeywordTok{)}
-       \ExtensionTok{437}\NormalTok{,456,998      LLC{-}loads                 \#   12.327 M/sec                    ( +{-}  4.03\% )  }\KeywordTok{(}\ExtensionTok{50.00\%}\KeywordTok{)}
-       \ExtensionTok{159}\NormalTok{,643,085      LLC{-}load{-}misses           \#   36.49\% of all LL{-}cache hits     ( +{-}  8.69\% )  }\KeywordTok{(}\ExtensionTok{50.44\%}\KeywordTok{)}
-
-           \ExtensionTok{122.565}\NormalTok{ +{-} 0.215 seconds time elapsed  ( +{-}  0.18\% )}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tests-de-performance-du-protocole-de-transfert-de-fichiers-ipfs}{%
-\subsection{\texorpdfstring{Tests de performance du protocole de
-transfert de fichiers
-\protect\hyperlink{acronym__IPFS}{IPFS}}{Tests de performance du protocole de transfert de fichiers IPFS}}\label{tests-de-performance-du-protocole-de-transfert-de-fichiers-ipfs}}
-
-Sur chacune des machines, le langage \emph{Go} doit être installé avec
-les commandes suivantes:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\FunctionTok{wget}\NormalTok{ https://dl.google.com/go/go1.14.3.linux{-}amd64.tar.gz}
-\FunctionTok{tar}\NormalTok{ {-}C /usr/local {-}xzf go1.14.3.linux{-}amd64.tar.gz}
-\BuiltInTok{echo} \StringTok{\textquotesingle{}export PATH=$PATH:/usr/local/go/bin\textquotesingle{}} \OperatorTok{\textgreater{}\textgreater{}}\NormalTok{ /etc/profile}
-\BuiltInTok{export} \VariableTok{PATH=$PATH}\NormalTok{:/usr/local/go/bin}
-\end{Highlighting}
-\end{Shaded}
-
-Ensuite, \protect\hyperlink{acronym__IPFS}{IPFS} est installé sur
-chacune des machines:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\FunctionTok{wget}\NormalTok{ https://dist.ipfs.io/go{-}ipfs/v0.5.1/go{-}ipfs\_v0.5.1\_linux{-}amd64.tar.gz}
-\FunctionTok{tar}\NormalTok{ xvzf go{-}ipfs\_v0.5.1\_linux{-}amd64.tar.gz}
-\FunctionTok{mv}\NormalTok{ go{-}ipfs/ipfs /usr/local/bin/ipfs}
-\end{Highlighting}
-\end{Shaded}
-
-Un noeud \protect\hyperlink{acronym__IPFS}{IPFS} est ensuite initialisé
-sur chacune des machines:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\VariableTok{IPFS\_PATH=}\NormalTok{\textasciitilde{}/.ipfs }\ExtensionTok{ipfs}\NormalTok{ init}
-\end{Highlighting}
-\end{Shaded}
-
-Pour avoir un réseau IPFS privé, on génère une clé de \emph{swarm} sur
-\texttt{debian1} et on la copie sur \texttt{debian2}, en lançant les
-commandes suivantes sur la machine \texttt{debian1}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\BuiltInTok{echo}\NormalTok{ {-}e }\StringTok{"/key/swarm/psk/1.0.0/\textbackslash{}n/base16/\textbackslash{}n}\KeywordTok{\textasciigrave{}}\FunctionTok{tr}\NormalTok{ {-}dc }\StringTok{\textquotesingle{}a{-}f0{-}9\textquotesingle{}} \OperatorTok{\textless{}}\NormalTok{ /dev/urandom }\KeywordTok{|} \FunctionTok{head}\NormalTok{ {-}c64}\KeywordTok{\textasciigrave{}}\StringTok{"} \OperatorTok{\textgreater{}}\NormalTok{ \textasciitilde{}/.ipfs/swarm.key}
-\FunctionTok{scp}\NormalTok{ /home/debian/.ipfs/swarm.key debian2.home:/home/debian/.ipfs/swarm.key}
-\end{Highlighting}
-\end{Shaded}
-
-Maintenant, il faut configurer un noeud d'amorçage (\emph{bootstrap
-node}) sur \texttt{debian1}, qui sera utilisé par \texttt{debian2} pour
-se connecter au réseau \protect\hyperlink{acronym__IPFS}{IPFS} privé
-séparé du réseau public qui utilise d'autres noeuds d'amorçage. Pour
-faire cela, il faut commencer par supprimer la liste des noeuds
-d'amorçage publics sur les deux machines avec la commande suivante:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\VariableTok{IPFS\_PATH=}\NormalTok{\textasciitilde{}/.ipfs }\ExtensionTok{ipfs}\NormalTok{ bootstrap rm {-}{-}all}
-\end{Highlighting}
-\end{Shaded}
-
-Ensuite, il faut récupérer l'identifiant unique \texttt{PeerID} de
-\texttt{debian1} pour pouvoir le configurer comme un noeud d'amorçage
-dans \texttt{debian2}. La commande suivante est lancée sur
-\texttt{debian1}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\VariableTok{IPFS\_PATH=}\NormalTok{\textasciitilde{}/.ipfs }\ExtensionTok{ipfs}\NormalTok{ config show }\KeywordTok{|} \FunctionTok{grep} \StringTok{"PeerID"}
-    \StringTok{"PeerID"}\NormalTok{: }\StringTok{"QmX9MYUQhjKxua6HQMtpzaZd9ui4gGT75FJgAxeQJC47Ei"}
-\end{Highlighting}
-\end{Shaded}
-
-L'identitfiant unique \texttt{PeerID} de \texttt{debian1} retourné par
-la commande est:
-
-\texttt{QmX9MYUQhjKxua6HQMtpzaZd9ui4gGT75FJgAxeQJC47Ei}
-
-On peutmaintenant le rajouter dans la configuration des noeuds
-d'amorçage des deux machines en lançant la commande suivante sur chacune
-d'entre elle:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\VariableTok{IPFS\_PATH=}\NormalTok{\textasciitilde{}/.ipfs }\ExtensionTok{ipfs}\NormalTok{ bootstrap add /dnsaddr/debian1.home/p2p/QmX9MYUQhjKxua6HQMtpzaZd9ui4gGT75FJgAxeQJC47Ei}
-\end{Highlighting}
-\end{Shaded}
-
-Maintenant, le \emph{daemon} \protect\hyperlink{acronym__IPFS}{IPFS}
-peut être lancé sur chacune des machines. La variable d'environnement
-\texttt{LIBP2P\_FORCE\_PNET=1} est définie pour forcer les échanges à se
-faire sur un réseau privé.
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\BuiltInTok{export} \VariableTok{LIBP2P\_FORCE\_PNET=}\NormalTok{1}
-\VariableTok{IPFS\_PATH=}\NormalTok{\textasciitilde{}/.ipfs }\ExtensionTok{ipfs}\NormalTok{ daemon}
-\end{Highlighting}
-\end{Shaded}
-
-Dans ce cas, le \emph{daemon} a été exécuté en avant plan et un second
-terminal sera ouvert pour la suite des commandes. Dans une configuration
-plus durable, il faudrait le faire tourner en arrière plan, par exemple
-avec une unité systemd.
-
-Maintenant on peut partager l'image sur le réseau avec la commande
-suivante sur \texttt{debian1}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\VariableTok{IPFS\_PATH=}\NormalTok{\textasciitilde{}/.ipfs }\ExtensionTok{ipfs}\NormalTok{ add win10.tar.gz }
-\ExtensionTok{added}\NormalTok{ QmRm8As8ECuQoLq3UWowsxJ8mh89txLvpUh7A2mgw5pMhv win10.tar.gz}
- \ExtensionTok{12.80}\NormalTok{ GiB / 12.80 GiB [==============================================================================] 100.00\%}
-\end{Highlighting}
-\end{Shaded}
-
-Le temps d'ajout de l'image a pris plus de trois minutes. À la fin, la
-référence du fichier, qui l'identifie de manière unique sur le réseau,
-est affichée: \texttt{QmRm8As8ECuQoLq3UWowsxJ8mh89txLvpUh7A2mgw5pMhv}.
-
-On peut maintenant tenter de récupérer le fichier depuis
-\texttt{debian2}:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{$ }\VariableTok{IPFS\_PATH=}\NormalTok{\textasciitilde{}/.ipfs }\ExtensionTok{ipfs}\NormalTok{ get QmRm8As8ECuQoLq3UWowsxJ8mh89txLvpUh7A2mgw5pMhv}
-\ExtensionTok{Saving}\NormalTok{ file(s) }\ExtensionTok{to}\NormalTok{ QmRm8As8ECuQoLq3UWowsxJ8mh89txLvpUh7A2mgw5pMhv}
- \ExtensionTok{12.80}\NormalTok{ GiB / 12.80 GiB [==============================================================================] 100.00\% 7m27s}
-\end{Highlighting}
-\end{Shaded}
-
-Le transfert a pris \(7m27s = 447s\). C'est beaucoup trop long pour nos
-besoins. Le benchmark avec \texttt{perf} n'a même pas été effectué au vu
-de ce résultat.
-
-\hypertarget{choix-du-protocole-de-transfert-de-fichiers}{%
-\subsection{Choix du protocole de transfert de
-fichiers}\label{choix-du-protocole-de-transfert-de-fichiers}}
-
-La table \ref{table_protocols} ainsi que la figure \ref{chart_protocols}
-récapitulent les résultats mesurés pour chacun des protocoles testés. On
-peut remarquer que pour tous les protocoles, sauf
-\protect\hyperlink{acronym__IPFS}{IPFS}, les résultats sont proches de
-120 secondes. Cette durée montre que pour ces protocoles, on est proches
-de la limite théorique de gigabit ethernet:
-
-\[ \frac{13743592907 [B]}{120 [s]} = \frac{109948743256 [b]}{120 [s]} \approx 916239527 [b/s] \approx 0.916 [Gb/s] \approx 1 [Gb/s] \]
-
-On peut donc conclure que le choix du protocole
-\protect\hyperlink{acronym__NFS}{NFS} est approprié car les autres
-protocole n'accélèrent pas considérablement la vitesse de transfert
-d'une image.
-
-\clearpage
-
-\begin{longtable}[]{@{}llll@{}}
-\caption{Table des mesures de la durée de la copie d'un fichier avec
-différents protocoles \label{table_protocols}}\tabularnewline
-\toprule
-\begin{minipage}[b]{0.22\columnwidth}\raggedright
-Protocole\strut
-\end{minipage} & \begin{minipage}[b]{0.22\columnwidth}\raggedright
-Durée (secondes)\strut
-\end{minipage} & \begin{minipage}[b]{0.22\columnwidth}\raggedright
-Écart entre les mesures (± secondes)\strut
-\end{minipage} & \begin{minipage}[b]{0.22\columnwidth}\raggedright
-Nombre de mesures\strut
-\end{minipage}\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-\begin{minipage}[b]{0.22\columnwidth}\raggedright
-Protocole\strut
-\end{minipage} & \begin{minipage}[b]{0.22\columnwidth}\raggedright
-Durée (secondes)\strut
-\end{minipage} & \begin{minipage}[b]{0.22\columnwidth}\raggedright
-Écart entre les mesures (± secondes)\strut
-\end{minipage} & \begin{minipage}[b]{0.22\columnwidth}\raggedright
-Nombre de mesures\strut
-\end{minipage}\tabularnewline
-\midrule
-\endhead
-\begin{minipage}[t]{0.22\columnwidth}\raggedright
-SCP\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-119.8094\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-0.0182\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-4\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.22\columnwidth}\raggedright
-HTTP\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-119.871\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-0.235\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-4\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.22\columnwidth}\raggedright
-FTP\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-120.151\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-0.213\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-4\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.22\columnwidth}\raggedright
-NFS\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-120.417\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-0.119\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-4\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.22\columnwidth}\raggedright
-SMB\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-122.565\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-0.215\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-4\strut
-\end{minipage}\tabularnewline
-\begin{minipage}[t]{0.22\columnwidth}\raggedright
-IPFS\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-447\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-0\strut
-\end{minipage} & \begin{minipage}[t]{0.22\columnwidth}\raggedright
-1\strut
-\end{minipage}\tabularnewline
-\bottomrule
-\end{longtable}
-
-\begin{figure}
-\centering
-\includegraphics{charts/chart_protocols.svg}
-\caption{Graphique des mesures de la durée de la copie d'un fichier avec
-différents protocoles\label{chart_protocols}}
-\end{figure}
-
-\clearpage
-
-\hypertarget{ruxe9duction-de-la-taille-des-images}{%
-\section{Réduction de la taille des
-images}\label{ruxe9duction-de-la-taille-des-images}}
-
-Dans le système initial, une image prend beaucoup de place. Chaque image
-est une copie exacte des partitions d'un système effectuée avec l'outil
-\texttt{dd}, qui est ensuite compressée avec \texttt{gzip}. Cette taille
-massive a plusieurs impacts négatifs:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  Ralentissement de la vitesse de déploiement: il y a plus de données à
-  transmettre à travers le réseau et à copier sur le disque à chaque
-  déploiement.
-\item
-  Réduction du nombre d'images pouvant être mise en cache en même temps.
-\item
-  Réduction du nombre d'images pouvant être stockées sur le serveur.
-\end{enumerate}
-
-L'outil \emph{Clonezilla} a été considéré pour créer des images de
-taille plus réduites. Les images clonezilla sont créées avec l'outil
-\emph{Partclone}. Cet outil utilise une approche différente de
-\texttt{dd}: seuls les blocs utilisés sur les partitions sont copiés
-dans le fichier de l'image et seuls les blocs utilisés sont ensuite
-restaurés. Les images contentant uniquement les blocs utilisés sont
-ensuite compressées avec \texttt{gzip}.
-
-La taille des images créées avec clonezilla a été comparée à la taille
-des images déployées et à la taille des images juste compressées avec
-\texttt{gzip}, avec trois images:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  Une petite image (environ 3.2 GB) du système \emph{Debian}, dont les
-  tailles sont comparées dans le tableau \ref{table_image_sizes_debian}
-  et la figure \ref{chart_image_sizes_debian}
-\item
-  Une image moyenne (environ 200GB) du système \emph{Xubuntu}, dont les
-  tailles sont comparées dans le tableau \ref{table_image_sizes_xubuntu}
-  et la figure \ref{chart_image_sizes_xubuntu}
-\item
-  Une grande image (environ 512GB) du système \emph{Windows 10}, dont
-  les tailles sont comparées dans le tableau
-  \ref{table_image_sizes_win10} et la figure
-  \ref{chart_image_sizes_win10}
-\end{enumerate}
-
-\clearpage
-
-\begin{longtable}[]{@{}ll@{}}
-\caption{Table des tailles d'une petite image \emph{Debian} dans
-plusieurs formats \label{table_image_sizes_debian}}\tabularnewline
-\toprule
-Type & Taille (GB)\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-Type & Taille (GB)\tabularnewline
-\midrule
-\endhead
-Déployé & 3.220176384\tabularnewline
-Gzip & 0.496763976\tabularnewline
-Clonezilla & 0.29615293\tabularnewline
-\bottomrule
-\end{longtable}
-
-\begin{figure}
-\centering
-\includegraphics{charts/chart_image_sizes_debian.svg}
-\caption{Graphique des tailles d'une petite image \emph{Debian} dans
-plusieurs formats\label{chart_image_sizes_debian}}
-\end{figure}
-
-\clearpage
-
-\begin{longtable}[]{@{}ll@{}}
-\caption{Table des tailles d'une image \emph{Xubuntu} moyenne dans
-plusieurs formats \label{table_image_sizes_xubuntu}}\tabularnewline
-\toprule
-Type & Taille (GB)\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-Type & Taille (GB)\tabularnewline
-\midrule
-\endhead
-Déployé & 200.511847936\tabularnewline
-Gzip & 2.031040094\tabularnewline
-Clonezilla & 1.840064982\tabularnewline
-\bottomrule
-\end{longtable}
-
-\begin{figure}
-\centering
-\includegraphics{charts/chart_image_sizes_xubuntu.svg}
-\caption{Graphique des tailles d'une image \emph{Xubuntu} moyenne dans
-plusieurs formats\label{chart_image_sizes_xubuntu}}
-\end{figure}
-
-\clearpage
-
-\begin{longtable}[]{@{}ll@{}}
-\caption{Table des tailles d'une grande image \emph{Windows 10} dans
-plusieurs formats \label{table_image_sizes_win10}}\tabularnewline
-\toprule
-Type & Taille (GB)\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-Type & Taille (GB)\tabularnewline
-\midrule
-\endhead
-Déployé & 512.09515776\tabularnewline
-Gzip & 31.9568621077\tabularnewline
-Clonezilla & 12.855020882\tabularnewline
-\bottomrule
-\end{longtable}
-
-\begin{figure}
-\centering
-\includegraphics{charts/chart_image_sizes_win10.svg}
-\caption{Graphique des tailles d'une grande image \emph{Windows 10} dans
-plusieurs formats\label{chart_image_sizes_win10}}
-\end{figure}
-
-On peut voir que les images créées avec \emph{Clonezilla} prennent
-environ la moitié de la taille des images simplement compressées avec
-\texttt{gzip}. Les résultats de ces mesures de tailles ont donc motivé
-la modification du système de déploiement pour que des images
-\emph{Clonezilla} puissent être utilisées.
-
-\hypertarget{amuxe9lioration-de-los-de-duxe9ploiement}{%
-\section{Amélioration de l'OS de
-déploiement}\label{amuxe9lioration-de-los-de-duxe9ploiement}}
-
-\hypertarget{buildroot-loutil-de-construction-de-los-de-duxe9ploiement-initial}{%
-\subsection{\texorpdfstring{\emph{Buildroot}: l'outil de construction de
-l'\protect\hyperlink{acronym__OS}{OS} de déploiement
-initial}{Buildroot: l'outil de construction de l'OS de déploiement initial}}\label{buildroot-loutil-de-construction-de-los-de-duxe9ploiement-initial}}
-
-L'image du système d'exploitation \emph{Linux} servant à l'exécution des
-scripts de déploiement dans le système initial est construit avec
-\emph{Buildroot}. Cet outil permet de générer compiler un noyau linux,
-de créer un système de fichier racine minimal et de générer un chargeur
-d'amorçage (\emph{bootloader}). Cet outil est principalement utilisé
-pour générer des systèmes embarqués. Il avait été choisi dans le système
-initial car il permettait de créer une image
-d'\protect\hyperlink{acronym__OS}{OS} très petite qui peut être
-téléchargée très rapidement sur le réseau.
-
-\hypertarget{probluxe8mes-avec_buildroot_-pour-construire-los-de-duxe9ploiement}{%
-\subsection{\texorpdfstring{Problèmes avec\_Buildroot\_ pour construire
-l'\protect\hyperlink{acronym__OS}{OS} de
-déploiement}{Problèmes avec\_Buildroot\_ pour construire l'OS de déploiement}}\label{probluxe8mes-avec_buildroot_-pour-construire-los-de-duxe9ploiement}}
-
-Buildroot permet d'installer facilement les paquets de nombreuses
-applications dans le système de fichiers de l'image. Malheureusement,
-aucun paquet n'existe pour \emph{Clonezilla}. L'idée de créer un paquet
-pour ce logiciel a été étudiée, mais n'a pas été retenue, car il
-nécessite de nombreuses dépendances, et bien que cela aurait été
-possible de le faire, le temps à investir dans cette tâche aurait été
-considérable, et le résultat n'aurait été testable qu'une fois cette
-tâche accomplie. De plus, pour chaque mise à jour de \emph{Clonezilla}
-que l'on souhaiterait utiliser, par exemple pour profiter de
-l'implémentation d'un nouveau système de fichier ou des résolutions de
-bugs, il faudrait remettre à jour ce paquet.
-
-\hypertarget{choix-de-debian-pour-remplauxe7er-buildroot}{%
-\subsection{\texorpdfstring{Choix de \emph{Debian} pour remplaçer
-\emph{Buildroot}}{Choix de Debian pour remplaçer Buildroot}}\label{choix-de-debian-pour-remplauxe7er-buildroot}}
-
-Pour simplifier l'utilisation de \emph{Clonezilla} et de nombreux autres
-outils, le passsage à une solution alternative à \emph{Buildroot} a été
-décidé. De nombreuses distributions Linux proposent des paquets pour
-\emph{Clonezilla}. Les plus intéressantes sont \emph{Debian} et
-\emph{Ubuntu} car l'équipe de \emph{Clonezilla} les utilise pour la
-version \emph{live-CD} de l'outil. Ils développent et distribuent
-eux-mêmes des paquets au format \texttt{deb} pour ces deux
-distributions. Un travail a donc été entrepris pour remplacer
-l'\protect\hyperlink{acronym__OS}{OS} de déploiement basé sur
-\emph{Buildroot} par un \protect\hyperlink{acronym__OS}{OS} basé sur
-\emph{Debian}. Ce choix permettra d'utiliser facilement les nombreux
-paquets disponibles pour cette distribution si il y en a besoin dans les
-versions futures du système de déploiement.
-
-Le problème avec l'utilisation d'une distribution telle que
-\emph{Debian} est que la taille du système de fichiers racine n'est pas
-aussi réduite que ce que l'on peut obtenir avec \emph{Buildroot}. La
-stratégie d'exécution du système d'exploitation a donc été modifiée pour
-tenir compte de ce changement de taille. Le système initial chargeait à
-chaque fois une image entière du système de fichiers racine (environ
-100MB) en mémoire. Sur le nouveau système, seul le noyau linux est
-téléchargé, ainsi que l'image \emph{initrd}. Le sytème de fichier racine
-est monté à partir d'un partage \protect\hyperlink{acronym__NFS}{NFS}.
-Cela permet d'avoir un système de fichiers racine contenant beaucoup
-plus de données, mais de ne télécharger à travers le réseau que ceux qui
-sont utilisés, au moment où ils sont utilisés.
-
-\hypertarget{cruxe9ation-du-systuxe8me-de-fichiers-racine-debian-avec-multistrap}{%
-\subsection{\texorpdfstring{Création du système de fichiers racine
-\emph{Debian} avec
-\emph{multistrap}}{Création du système de fichiers racine Debian avec multistrap}}\label{cruxe9ation-du-systuxe8me-de-fichiers-racine-debian-avec-multistrap}}
-
-Le système de fichiers racine accessible via un partage
-\protect\hyperlink{acronym__NFS}{NFS} est créé en utilisant l'outil
-\emph{multistrap} fourni par Debian. Cet outil permet de générer un
-système de fichiers racine pour une architecture donnée, et d'y
-installer une liste de paquets choisie. Une fois le sytème de fichiers
-racine créé, certains fichiers de configurations doivent sont créés
-manuellement:
-
-\begin{itemize}
-\tightlist
-\item
-  \texttt{/etc/hostname}: le nom d'hôte de la machine. Dans notre cas,
-  la valeur \texttt{bootiful-deployer} a été entrée.
-\item
-  \texttt{/etc/hosts}: la liste des hôtes connus. Dans notre cas, une
-  seule entrée est nécessaire: \texttt{127.0.0.1\ \ localhost}
-\item
-  \texttt{/etc/fstab}: la liste de systèmes de fichiers à monter au
-  démarrage. Pour palier au fait que le système de fichiers racine sera
-  en lecture seule, plusieurs dossiers ont été montés en \texttt{tmpfs}
-  (système de fichier temporaire chargé en mémoire) afin de permettre
-  aux processus du système d'y écrire des fichiers: \texttt{/tmp},
-  \texttt{/dev}, \texttt{/var/run}, \texttt{/var/lock},
-  \texttt{/var/tmp}, \texttt{/var/log}, \texttt{/var/lib/clonezilla},
-  \texttt{/bootiful}
-\item
-  \texttt{/etc/mtab}: ce fichier contient la liste des volumes
-  actuellement montés. Au début, il n'avait pas été créé et cela causait
-  une erreur fatale dans \emph{Partclone}, qui n'arrivait pas à détecter
-  si une partition était montée ou non. Cela a été résolu en créant ce
-  fichier comme un lien symbolique vers le fichier \texttt{/proc/mounts}
-  qui est un faux fichier généré en mémoire par le noyau \emph{Linux} et
-  qui contient la liste des points des volumes actuellement montés.
-\end{itemize}
-
-Quelques autres fichiers sont rajoutés/remplacés dans le système de
-fichiers racine:
-
-\begin{itemize}
-\tightlist
-\item
-  \texttt{/etc/initramfs.conf}: configuration pour générer une image
-  \emph{initramfs} qui va initialiser montage du système de fichiers
-  racine depuis un partage NFS
-\item
-  \texttt{/etc/systemd/system/bootiful-deploy-log.service}:
-  configuration d'unité \emph{Systemd} qui permet de lancer le script
-  d'initialisation du déploiement d'images au démarrage
-\item
-  \texttt{/usr/bin/bootiful-deploy-init}: script d'initialisation du
-  déploiement d'images. Lance le script de déploiement d'images et
-  affiche permet de choisir quelle action effectuer si le déploiement ne
-  se termine pas avec succès.
-\item
-  \texttt{/usr/bin/bootiful-common}: script contenant des fonctions
-  communes aux différents script de déploiement \texttt{bootiful-*}. Il
-  n'est pas conçu pour être exécuté directement, mais à être chargé par
-  les autres scripts avec la commande \texttt{source}.
-\item
-  \texttt{/usr/bin/bootiful-deploy}: script permettant le choix de
-  l'image, des configurations (si applicable), et d'effectuer le
-  déploiement de l'image choisie.
-\item
-  \texttt{/usr/bin/bootiful-save-image}: script utilitaire permettant de
-  construire une image avec \emph{dd}. Il a été utilisé pour construire
-  les images des benchmarks, mais il vaut mieux utiliser le live-cd
-  \emph{Clonezilla} pour la création d'une nouvelle image.
-\item
-  \texttt{/usr/bin/bootiful-reset-cache}: script utilitaire permettant
-  de réinitialiser le cache des images. Il a été utilisé pour pouvoir
-  facilement réinitialiser le cache lors des benchmarks.
-\end{itemize}
-
-Ensuite, la commande \texttt{chroot} est utilisée pour remplacer
-temporairement le système de fichier racine actuel de la machine (celle
-qui a lancé \emph{multistrap}) par celui qui vient d'être créé.
-Plusieurs commandes sont lancées dans cet environnement pour initialiser
-le système:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  \texttt{dpkg\ -\/-configure\ -a}: lance la configuration
-  post-installation de tous les paquets \emph{Debian}.
-\item
-  \texttt{apt-get\ autoremove\ -\/-purge\ \&\&\ apt-get\ clean}:
-  désinstalle les dépendances inutiles et vide le cache des paquets.
-\item
-  \texttt{update-initramfs\ -u}: regénère une image \emph{initramfs} qui
-  va initialiser montage du système de fichiers racine depuis un partage
-  NFS en utilisant la configuration rajoutée précédemment dans
-  \texttt{/etc/initramfs.conf}.
-\item
-  \texttt{systemctl\ enable\ bootiful-deploy-log.service}: active
-  l'unité \emph{Systemd} de lancement automatique du script de
-  déploiement décrite dans le fichier
-  \texttt{/etc/systemd/system/bootiful-deploy-log.service} ajouté
-  précédemment.
-\end{enumerate}
-
-\hypertarget{automatisation-de-la-cruxe9ation-du-systuxe8me-de-duxe9ploiement-avec-docker}{%
-\subsection{\texorpdfstring{Automatisation de la création du système de
-déploiement avec
-\emph{Docker}}{Automatisation de la création du système de déploiement avec Docker}}\label{automatisation-de-la-cruxe9ation-du-systuxe8me-de-duxe9ploiement-avec-docker}}
-
-Pour utiliser l'outil \emph{multistrap} afin de créer un système de
-fichier racine \emph{Debian}, il faut que le programme
-\texttt{multistrap} soit lancé depuis un système d'exploitation
-\emph{Debian}. Pour rendre la création de ce système de fichiers
-possible depuis d'autres distributions Linux, un conteneur \emph{Docker}
-a été créé.
-
-Le processus de création du système décrit dans la section précédente a
-été automatisé et est décrit dans un fichier \texttt{Dockerfile} (le
-code-souce de ce fichier peut être consulté dans la section
-\ref{deployer_dockerfile}). La fonctionnalité de Docker de construction
-en plusieurs ``étages'' (\emph{multi-stage build}) a été utilisée. Trois
-``étages'' sont définis:
-
-\begin{itemize}
-\tightlist
-\item
-  \texttt{build-stage}: depuis une image \texttt{debian:bullseye}
-  construit une image de système de fichier racine \emph{Debian} et le
-  configure comme décrit dans la section précédente. Le dossier
-  \texttt{/boot/} est sorti du dossier du système de fichiers racine
-  nouvellement créé et déplacé dans \texttt{/multistrap/boot}. Le reste
-  du système de fichier racine (tout sauf \texttt{/boot/} est compressé
-  dans une archive \texttt{/multistrap/nfsroot.tar.gz}. Cette étape est
-  un pré-requis des étapes suivantes et n'est normalement pas exécutée
-  directement.
-\item
-  \texttt{nfs-export-stage}: dans une image vide
-  (\texttt{FROM\ scratch}), copie le fichier
-  \texttt{/multistrap/nfsroot.tar.gz} depuis l'étape
-  \texttt{build-stage}. L'image de cette étape contient donc uniquement
-  un fichier à sa racine, \texttt{nfsroot.tar.gz}, qui pourra être
-  exporté et extrait dans le serveur
-  \protect\hyperlink{acronym__NFS}{NFS} pour être partagé.
-\item
-  \texttt{tftp-export-stage}: dans une image vide
-  (\texttt{FROM\ scratch}), copie le contenu du dossier
-  \texttt{/multistrap/boot} depuis l'étape \texttt{build-stage}. L'image
-  de cette étape contient donc uniquement le contenu de la du dossier
-  \texttt{/boot/} de la partition racine, c'est à dire les fichiers
-  \texttt{initrd.img} (image \emph{initrd} initialisant le système de
-  fichier racine depuis \protect\hyperlink{acronym__NFS}{NFS}) et
-  \texttt{vmlinuz} (le noyau \emph{Linux}). Le contenu de cette image
-  pourra être exporté dans le dossier partagé du serveur
-  \protect\hyperlink{acronym__TFTP}{TFTP}, afin d'être téléchargé depuis
-  le logiciel d'amorçage \protect\hyperlink{acronym__GRUB}{GRUB} pour
-  lancer le système de déploiement.
-\end{itemize}
-
-Le fichier \texttt{Makefile} à la racine du projet définit des cibles et
-des recettes pour exécuter \texttt{docker\ build} exporter les données
-des deux derniers étages dans leurs dossiers respectifs:
-
-\begin{itemize}
-\tightlist
-\item
-  le contenu de l'étage \texttt{nfs-export-stage}, c'est à dire
-  l'archive \texttt{nfsroot.tar.gz}, est exportée dans le dossier
-  \texttt{nfs/}. Elle sera extraite dans le serveur
-  \protect\hyperlink{acronym__NFS}{NFS}.
-\item
-  le contenu de l'étage \texttt{tftp-export-stage}, c'est à dire
-  \texttt{initrd.img} et \texttt{vmlinuz} sont exportés dans le dossier
-  \texttt{tftp/tftpboot/boot/deployer} qui contient le système de
-  déploiement d'image servi par le serveur
-  \protect\hyperlink{acronym__TFTP}{TFTP}.
-\end{itemize}
-
-\hypertarget{duxe9ploiement-dimage-windows}{%
-\section{Déploiement d'image
-Windows}\label{duxe9ploiement-dimage-windows}}
-
-Une image \emph{Windows 10} a été créée avec \emph{Clonezilla}, à partir
-du système présent par défaut sur les mini-pc DELL que l'école avait mis
-à disposition. Les PC étant neufs il s'agit du système d'exploitation
-par défaut installé pour le constructeur. L'image qui a été créée a déjà
-été mentionnée dans la section \emph{Réduction de la taille des images}.
-Elle a la particularité d'être très grande car elle prend l'espace
-entier du disque.
-
-Un problème a été rencontré lors du premier déploiement de l'image: le
-script de déploiement ne gérait pas une image qui est tellement grande
-qu'elle écrase la partition de cache et plantait. Une vérification a
-donc été rajoutée sur la taille de l'image. Quand une image va écraser
-la partition de cache, un message d'avertissement est affiché et
-l'utilisateur doit confirmer qu'il souhaite continuer. Si l'utilisateur
-accepte, le déploiment se fait sans mise en cache de l'image et la
-partition cachée de cache est détruite.
-
-Une fois ce système mis en place, le déploiement de l'image s'est
-déroulé sans problème particulier, et a confirmé que le déploiement
-d'une image \emph{Windows} est faisable avec ce système.
-
-\hypertarget{ruxe9duction-du-temps-de-duxe9ploiement-total}{%
-\section{Réduction du temps de déploiement
-total}\label{ruxe9duction-du-temps-de-duxe9ploiement-total}}
-
-Théoriquement, le déploiement d'images avec clonezilla devrait être plus
-court que le déploiement d'images \emph{raw}. Des mesures ont été
-effectuées avec les trois images dont les différences de taille ont déjà
-étudiées précédemment dans la section \emph{Réduction de la taille des
-images}:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  Une petite image (environ 3.2 GB) du système \emph{Debian}, dont les
-  temps de déploiement sont comparés dans le tableau
-  \ref{table_deploy_time_debian} et la figure
-  \ref{chart_deploy_time_debian}
-\item
-  Une image moyenne (environ 200GB) du système \emph{Xubuntu}, dont les
-  temps de déploiement sont comparés dans le tableau
-  \ref{table_deploy_time_xubuntu} et la figure
-  \ref{chart_deploy_time_xubuntu}
-\item
-  Une grande image (environ 512GB) du système \emph{Windows 10}, dont
-  les temps de déploiement sont comparés dans le tableau
-  \ref{table_deploy_time_win10} et la figure
-  \ref{chart_deploy_time_win10}
-\end{enumerate}
-
-\clearpage
-
-\begin{longtable}[]{@{}ll@{}}
-\caption{Table des temps de déploiement d'une petite image \emph{Debian}
-dans plusieurs formats \label{table_deploy_time_debian}}\tabularnewline
-\toprule
-Type & Temps de déploiement (secondes)\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-Type & Temps de déploiement (secondes)\tabularnewline
-\midrule
-\endhead
-Gzip (sans cache) & 14\tabularnewline
-Gzip (avec cache) & 13\tabularnewline
-Clonezilla (sans cache) & 39\tabularnewline
-Clonezilla (avec cache) & 39\tabularnewline
-\bottomrule
-\end{longtable}
-
-\begin{figure}
-\centering
-\includegraphics{charts/chart_deploy_time_debian.svg}
-\caption{Graphique des temps de déploiement d'une petite image
-\emph{Debian} dans plusieurs formats\label{chart_deploy_time_debian}}
-\end{figure}
-
-\clearpage
-
-\begin{longtable}[]{@{}ll@{}}
-\caption{Table des temps de déploiement d'une image \emph{Xubuntu}
-moyenne dans plusieurs formats
-\label{table_deploy_time_xubuntu}}\tabularnewline
-\toprule
-Type & Temps de déploiement (secondes)\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-Type & Temps de déploiement (secondes)\tabularnewline
-\midrule
-\endhead
-Gzip (sans cache) & 623\tabularnewline
-Gzip (avec cache) & 630\tabularnewline
-Clonezilla (sans cache) & 109\tabularnewline
-Clonezilla (avec cache) & 85\tabularnewline
-\bottomrule
-\end{longtable}
-
-\begin{figure}
-\centering
-\includegraphics{charts/chart_deploy_time_xubuntu.svg}
-\caption{Graphique des temps de déploiement d'une image \emph{Xubuntu}
-moyenne dans plusieurs formats\label{chart_deploy_time_xubuntu}}
-\end{figure}
-
-\clearpage
-
-\begin{longtable}[]{@{}ll@{}}
-\caption{Table des temps de déploiement d'une grande image \emph{Windows
-10} dans plusieurs formats
-\label{table_deploy_time_win10}}\tabularnewline
-\toprule
-Type & Temps de déploiement (secondes)\tabularnewline
-\midrule
-\endfirsthead
-\toprule
-Type & Temps de déploiement (secondes)\tabularnewline
-\midrule
-\endhead
-Gzip (sans cache) & 3433\tabularnewline
-Clonezilla (sans cache) & 371\tabularnewline
-\bottomrule
-\end{longtable}
-
-\begin{figure}
-\centering
-\includegraphics{charts/chart_deploy_time_win10.svg}
-\caption{Graphique des temps de déploiement d'une grande image
-\emph{Windows 10} dans plusieurs formats\label{chart_deploy_time_win10}}
-\end{figure}
-
-\clearpage
-
-Ces mesures permettent de se rendre contre de plusieurs faits
-remarquables, qui ne sont pas forcément intuitifs.
-
-Sur des très petites images le déploiement au format \emph{raw}
-compressé avec \emph{gzip} est plus rapide que le déploiement avec
-\emph{Clonezilla}. Ceci peut s'expliquer par le fait que
-\emph{Clonezilla} prend du temps pour créer une table des partitions, un
-système de fichiers pour chacune de ces partitions et copie ensuite les
-blocs un à un sur chaque système de fichiers. Sur une grande image, ce
-mode de fonctionnement est ``rentable'' car il y a beaucoup de blocs qui
-n'auront pas à être copiés, alors qu'une image \emph{raw} devra passer
-du temps à copier les données de chacun de ces blocs. Sur une très
-petite image comme l'image \emph{Debian} mesurée ici, presque tous les
-blocs du système de fichiers sont déjà utilisés, donc la copie brute des
-données des partitions est plus rapide car tout le temps est passé à
-copier les données.
-
-Sur les plus grosses images, cependant, \emph{Clonezilla} a clairement
-l'avantage, car de nombreux blocs vides n'ont pas besoin d'être copiés.
-Ainsi, avec les images plus larges utilisées dans les mesures, le temps
-de déploiement des images plus larges au format \emph{raw} prend environ
-5 à 9 fois plus de temps que le temps de déploiement avec
-\emph{Clonezilla}.
-
-Un autre fait remarquable est que le déploiement d'une image \emph{raw}
-déjà mise en cache prend plus de temps que le déploiement avec une copie
-simultanée dans le cache. Cela s'explique peut être par le fait que dans
-le premier cas, des données doivent être lues depuis le disque et
-écrites sur le même disque, tandis que dans le second cas, seule de
-l'écriture est effectuée.
-
-Par contre, dans le cas des images \emph{Clonezilla}, le déploiement
-d'une image déjà présente en cache s'effectue plus rapidement que le
-déploiement d'une image présente en cache. C'est l'inverse de ce qui se
-passe avec les images \emph{raw}. Cela s'explique par le fait que les
-images \emph{Clonezilla} sont copiées avant d'être déployées, alors que
-les images \emph{raw} sont copiées et déployées simultanément.
-
-Il est important de se rappeller que les mesures montrées ici sont
-effectuées dans des circonstances idéales: il n'y a qu'un seul client
-qui télécharge l'image, seul un switch réseau sépare le client du
-serveur et le client et le serveur sont les appareils connectés à ce
-réseau local. Dans des conditions réelles, plusieurs machines seront
-fréquemment en train de télécharger des images depuis le serveur en même
-temps. Dans ce cas, le temps de déploiement d'une image non présente en
-cache risque de prendre beaucoup plus de temps. Au contraire, le
-déploiement d'une image déjà mise en cache devrait théoriquement prendre
-le même temps que dans ces circonstances idéales.
-
-\hypertarget{amuxe9lioration-des-scripts-de-duxe9ploiement}{%
-\section{Amélioration des scripts de
-déploiement}\label{amuxe9lioration-des-scripts-de-duxe9ploiement}}
-
-De très nombreuses améliorations ont été apportées aux scripts de
-déploiement, au point qu'ils sont presque complètement différents des
-scripts initiaux.
-
-\hypertarget{gestion-des-erreurs}{%
-\subsection{Gestion des erreurs}\label{gestion-des-erreurs}}
-
-Premièrement, la gestion des erreurs, inexistante dans le script initial
-a été rajoutée. Les codes de retour des commandes sont vérifiés et les
-données récupérées depuis la sortie de ces commandes sont validées avant
-utilisation. Si un code de retour ou une donnée récupérée n'est pas au
-format attendu, une fonction spéciale \texttt{fatal\_error} est appelée
-avec comme argument un message d'erreur adapté à la situation. Cette
-fonction va afficher le message d'erreur, ainsi qu'une trace de la pile
-des appels (\emph{stack trace} en anglais). Cette trace permet
-d'identifier précisément à quelle ligne de quel fonction et dans quel
-fichier une erreur a eu lieu.
-
-Finalement, le script de déploiement \texttt{bootiful-deploy} sera
-quitté avec un code d'erreur, ce qui permet au script parent,
-\texttt{bootiful-init}, de détecter qu'une erreur a eu lieu et de
-proposer à l'utilisateur quelle action il souhaite effectuer parmi les
-choix suivants:
-
-\begin{itemize}
-\tightlist
-\item
-  Recommencer le déploiement
-\item
-  Redémarrer la machine
-\item
-  Éteindre la machine
-\item
-  Ouvrir un \emph{shell} interactif (\texttt{/bin/bash}) pour étudier la
-  cause de l'erreur. Une fois le \emph{shell} terminé, l'utilisateur
-  peut à nouveau choisir ce qu'il souhaite faire.
-\end{itemize}
-
-Le mécanisme de gestion d'erreurs a été très utile lors du développement
-et du test des scripts de déploiement pour comprendre pourquoi certaines
-erreurs arrivaient et adapter les scripts pour les éviter. Ce mécanisme
-sera aussi utile pour aider un futur administrateur du système à
-comprendre ce qu'il se passe si un déploiement ne se déroule pas comme
-prévu.
-
-\hypertarget{mesure-du-temps-uxe9couluxe9}{%
-\subsection{Mesure du temps écoulé}\label{mesure-du-temps-uxe9couluxe9}}
-
-Un système permettant de mesurer et d'afficher le temps passé dans
-chaque section du script de déploiement a été créé. Il permet de mesurer
-chacune des parties et d'afficher le temps passé dans chaque partie à la
-fin du script. Les parties mesurées sont classées en deux catégories:
-\emph{batch} et \emph{interactive}. Les parties \emph{batch} sont celles
-qui sont exécutées automatiquement, sans intervention de l'utilisateur,
-tandis que les parties \emph{interactive} sont celles où le système
-attend un choix de l'utilisateur, comme par exemple le choix de l'image
-à déployer. Cette catégorisation des parties permet d'afficher à la fin
-du script combien de temps a été passé dans les parties \emph{batch}
-sans prendre en compte le temps passé à attendre un choix de
-l'utilisateur.
-
-\hypertarget{amuxe9lioration-des-logs}{%
-\subsection{Amélioration des logs}\label{amuxe9lioration-des-logs}}
-
-Plusieurs améliorations ont été apportées au mécanisme de logging. Dans
-le système initial, les flux \texttt{stdin} et \texttt{stdout} du script
-de déploiement étaient redirigés vers un fichier de log sur le serveur.
-Cela permet d'étudier à \emph{posteriori} comment le déploiement s'est
-effectué, et de vérifier la durée d'exécution. Cela permet aussi de
-comprendre ce qui s'est mal passé en cas d'erreur.
-
-Dans le système initial, étant donné que les flux sont redirigés vers un
-fichier, un écran noir est affiché sur l'écran du poste client. Cela a
-l'inconvénient de ne pas permettre à l'utilisateur du poste client de
-savoir ce qu'il est en train de se passer. Il n'est pas possible pour
-l'utilisateur de savoir si le déploiement est en cours ou s'il est
-bloqué sur une étape. La première modification apportée au système de
-logging a été d'utiliser la commande \texttt{tee} pour écrire dans les
-fichiers de log, au lieu d'une simple redirection. Cela permet aux
-sorties d'être simultanément affichées sur l'écran du client et
-sauvegardée dans les logs.
-
-De nombreux textes informatifs ont aussi été rajoutés dans la sortie du
-script pour expliquer ce qu'il est en train de se passer petit à petit.
-Cela permet de mieux contextualiser chaque ligne de log. Une barre de
-progression a aussi été rajoutée lors du déploiement d'une image au
-format \emph{raw} pour que l'utilisateur puisse suivre la progression du
-déploiement et qu'il puisse voir le temps écoulé ainsi qu'une estimation
-du temps restant.
-
-Le mécanisme initial de logging créait un fichier de log par poste
-client, en le nommant avec l'adresse
-\protect\hyperlink{acronym__MAC}{MAC} du poste. Chaque déploiement
-successif était loggué dans ce même fichier. Pour bien différencier le
-début et la fin d'un log, une ligne facilement reconnaissable contenant
-la date et l'heure était affichée. Il y a plusieurs problèmes avec ce
-système:
-
-\begin{itemize}
-\tightlist
-\item
-  Les fichiers de log peuvent devenir très gros après de nombreux
-  déploiements.
-\item
-  Le nettoyage du dossier de logs pour ne garder que les plus récents
-  est compliqué, car chaque fichier contient les logs de plusieurs
-  déploiements.
-\item
-  La manipulation avec des commandes standard telles que \texttt{grep},
-  \texttt{awk}, \texttt{tail} du log d'un déploiement précis est
-  compliqué.
-\item
-  La comparaison de deux logs de déploiement sur la même machine est
-  difficile car il faut trouver où les déploiements commencent et se
-  terminent dans le même fichier.
-\end{itemize}
-
-Le système de log a donc été modifié pour qu'un fichier par déploiement
-soit créé par déploiement. Chaque fichier de log est nommé selon
-l'adresse mac de la machine ainsi que la date et l'heure du début du
-déploiement.
-
-\hypertarget{intuxe9gration-de-clonezilla-comme-type-dimage}{%
-\subsection{\texorpdfstring{Intégration de \emph{Clonezilla} comme type
-d'image}{Intégration de Clonezilla comme type d'image}}\label{intuxe9gration-de-clonezilla-comme-type-dimage}}
-
-Le script de déploiement a été modifié pour pouvoir détecter si une
-image est au format \emph{raw} ou s'il s'agit d'une image
-\emph{Clonezilla}. Selon le type d'image, des stratégies différentes
-sont utilisées pour différentes étapes du déploiement:
-
-\begin{itemize}
-\tightlist
-\item
-  Détermination de la place nécessaire sur le disque pour déployer
-  l'image
-\item
-  Commandes utilisées pour le déploiement
-\item
-  Détermination du point d'entrée EFI.
-\end{itemize}
-
-\hypertarget{duxe9tection-automatique-du-point-dentruxe9e-efi}{%
-\subsection{\texorpdfstring{Détection automatique du point d'entrée
-\protect\hyperlink{acronym__EFI}{EFI}}{Détection automatique du point d'entrée EFI}}\label{duxe9tection-automatique-du-point-dentruxe9e-efi}}
-
-Si l'image est au format \emph{Clonezilla}, le script de déploiement est
-capable de déterminer automatiquement quel sera le programme
-\protect\hyperlink{acronym__EFI}{EFI} qui sera exécuté au prochain
-démarrage pour démarrer l'\protect\hyperlink{acronym__OS}{OS} déployé.
-
-En effet, les images \emph{Clonezilla} de systèmes
-\protect\hyperlink{acronym__EFI}{EFI} contiennent un fichier spécial,
-\texttt{efi-nvram.dat}, qui contient les variables contenues dans la
-\protect\hyperlink{acronym__NVRAM}{NVRAM} du système
-\protect\hyperlink{acronym__EFI}{EFI} au moment de la création de
-l'image. Cette mémoire contient notemment l'ordre des entrées de boot et
-les programmes \protect\hyperlink{acronym__EFI}{EFI} à exécuter pour
-chacune de ces entrées, si applicable.
-
-Par exemple, voici le contenu du fichier \texttt{nvram.dat} de l'image
-\emph{Windows 10} mentionnée dans les sections précédentes:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{BootCurrent: 0001}
-\NormalTok{Timeout: 0 seconds}
-\NormalTok{BootOrder: 0000,0001}
-\NormalTok{Boot0000* Windows Boot Manager  HD(1,GPT,0cccfd69{-}e584{-}4e2d{-}8a5d{-}6afa7130fcab,0x800,0x15e000) /File(\textbackslash{}EFI\textbackslash{}Microsoft\textbackslash{}Boot\textbackslash{}bootmgfw.efi) WINDOWS.........x...B.C.D.O.B.J.E.C.T.=.\{.9.d.e.a.8.6.2.c.{-}.5.c.d.d.{-}.4.e.7.0.{-}.a.c.c.1.{-}.f.3.2.b.3.4.4.d.4.7.9.5.\}....................}
-\NormalTok{Boot0001* UEFI:  USB DISK 3.0 PMAP  PciRoot(0x0)/Pci(0x14,0x0)/USB(16,0)/CDROM(1,0x344,0x5e00)..BO}
-\end{Highlighting}
-\end{Shaded}
-
-Le script de déploiement est capable de lire ce fichier, de trouver la
-première entrée contenant un chemin vers un exécutable
-\protect\hyperlink{acronym__EFI}{EFI}, et transformer ce chemin en un
-chemin \emph{Unix}, c'est à dire avec le caractère \texttt{/} au lieu de
-\texttt{\textbackslash{}} et des noms de dossiers et fichiers sensibles
-à la casse, qui correspondent à des dossiers et fichiers présents sur la
-partition \protect\hyperlink{acronym__ESP}{ESP} qui vient d'être
-déployée. Cette conversion est importante car ce chemin devra être passé
-à \protect\hyperlink{acronym__GRUB}{GRUB}, qui ne sait lire que des
-chemins au format \emph{Unix}.
-
-Une fois le point d'entrée déterminé un fichier \texttt{efi\_entrypoint}
-est écrit à la racine de la partition
-\protect\hyperlink{acronym__ESP}{ESP}. Il sera ensuite lu par
-\protect\hyperlink{acronym__GRUB}{GRUB} au prochain démarrage pour
-trouver le point d'entrée à exécuter. Le contenu de ce fichier
-ressemblera à ceci:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{set} \VariableTok{efi\_entrypoint=}\NormalTok{/efi/Microsoft/Boot/bootmgfw.efi}
-\end{Highlighting}
-\end{Shaded}
-
-Si l'image est au format \emph{raw}, ou alors qu'il est souhaité
-d'outrepasser la lecture automatique du point d'entrée d'une image
-\emph{Clonezilla}, il suffit de rajouter un fichier
-\texttt{efi\_entrypoint} dans le dossier de l'image. Ce fichier sera
-directement copié dans l'\protect\hyperlink{acronym__ESP}{ESP}, sans
-qu'une tentative de détermination automatique du point d'entrée à partir
-du fichier \texttt{nvram.dat} soit effectuée.
-
-\hypertarget{personnalisation-dimages-post-duxe9ploiement}{%
-\section{Personnalisation d'images
-post-déploiement}\label{personnalisation-dimages-post-duxe9ploiement}}
-
-Un système a été conçu pour que l'utilisateur puisse choisir des
-personnalisations post-déploiement pour une image parmi un ensemble
-prédéfini. Ces personnalisations peuvent être implémentées de plusieurs
-manières: il ne s'agit que de fichiers qui seront copiés dans un dossier
-présent dans un répertoire de la machine déployée.
-
-Une image supportant les personnalisation post-déploiement peut par
-exemple être configurée pour exécuter des scripts qui auront été copiés
-dans un répertoire. Par exemple, sur une image dont
-l'\protect\hyperlink{acronym__OS}{OS} est une distribution \emph{Linux}
-utilisant \emph{Systemd}, une unité peut être configurée pour être
-exécutée au démarrage. Cette unité peut lancer au démarrage un script
-servant à exécuter séquentiellement des scripts présents dans un dossier
-prédéfini, ou alors exécuter des \emph{playbooks} \emph{Ansible}.
-
-Des personnalisations peuvent aussi être ``passives'' et ne pas
-nécessiter de configuration particulière du côté du client. Par exemple,
-si elle consiste uniquement à copier/remplacer un fichier de
-configuration à un endroit précis.
-
-Après le choix d'une image, le script de déploiement va chercher si un
-sous dossier \texttt{customizations} existe. Ce dossier contient un
-sous-dossier par personnalisation que l'utilisateur peut choisir. Chaque
-sous dossier personnalisation doit contenir une arborescence de dossiers
-et de fichiers dont le premier niveau contient uniquement des dossier
-correspondant à des noms de partitions existant dans l'image déployée. À
-l'intérieur de ce dossier, une arborescence des fichiers copiés sur la
-machine depuis laS
-
-Étudions une arborescence fictive de personnalisations pour mieux
-comprendre ce système. Voici l'arborescence du dossier
-\texttt{customizations} d'une image:
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\NormalTok{customizations}
-\NormalTok{├── C language development environment}
-\NormalTok{│   └── sda2}
-\NormalTok{│       └── etc}
-\NormalTok{│           └── bootiful}
-\NormalTok{│               └── postdeploy{-}playbooks}
-\NormalTok{│                   └── 002{-}install{-}c{-}dev.yml}
-\NormalTok{├── Custom bashrc}
-\NormalTok{│   └── sda2}
-\NormalTok{│       └── etc}
-\NormalTok{│           └── bash.bashrc}
-\NormalTok{└── Join LDAP domain}
-\NormalTok{    └── sda2}
-\NormalTok{        └── etc}
-\NormalTok{            └── bootiful}
-\NormalTok{                └── postdeploy{-}playbooks}
-\NormalTok{                    └── 001{-}join{-}ldap.yml}
-\end{Highlighting}
-\end{Shaded}
-
-Cette arborescence définit les personnalisations suivantes, qui peuvent
-être choisies par l'utilisateur:
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  \texttt{C\ language\ development\ environment}: copie un
-  \emph{playbook} \emph{Ansible} servant à installer un environnement de
-  développement C dans le dossier
-  \texttt{/etc/bootiful/postdeploy-playbooks} de la partition
-  \texttt{sda2}
-\item
-  \texttt{Custom\ bashrc}: remplace le ficher \texttt{/etc/bash.bashrc}
-  de la partition \texttt{sda2} par un fichier personnalisé.
-\item
-  \texttt{Join\ LDAP\ domain}: copie un \emph{playbook} \emph{Ansible}
-  servant à rejoindre un domaine \protect\hyperlink{acronym__LDAP}{LDAP}
-  dans le dossier \texttt{/etc/bootiful/postdeploy-playbooks} de la
-  partition \texttt{sda2}
-\end{enumerate}
-
-Les personnalisations \textbf{1} et \textbf{3} nécessitent que l'image
-soit équipée d'un mécanisme qui va exécuter les \emph{playbooks Ansible}
-présents dans \texttt{/etc/bootiful/postdeploy-playbooks} au démarrage.
-Des exemples d'un tel script et de l'unité \emph{systemd} servant à le
-lancer au démarrage sont consultables dans les sections
-\ref{source_ansible_run} et \ref{source_ansible_init}.'w'\,'\,'\,'
-
-La personnalisation \textbf{2} est passive: elle remplace juste un
-fichier mais ne nécessite pas de mécanisme spécial sur la machine de
-déploiement pour l'exécuter.
-
-\hypertarget{architecture-finale-du-projet}{%
-\chapter{Architecture finale du
-projet}\label{architecture-finale-du-projet}}
-
-\hypertarget{composants}{%
-\section{Composants}\label{composants}}
-
-\textbf{TODO: diagramme des composants du projet et description}
-
-\hypertarget{processus-de-duxe9ploiement}{%
-\section{Processus de déploiement}\label{processus-de-duxe9ploiement}}
-
-\textbf{TODO: diagramme du processus de déploiement et description
-complète de ce dernier. Explication détaillées de la structure des
-scripts de déploiement, de leurs possibilités et de leurs limitations.}
-
-\hypertarget{architecture-ruxe9seau}{%
-\section{Architecture réseau}\label{architecture-ruxe9seau}}
-
-\textbf{TODO: description de l'architecture réseau finale utilisée pour
-développer et tester le système avec diagramme. Expliquer comment cette
-architecture de test peut être transposée à une architecture de
-production.}
-
-\hypertarget{processus-de-build}{%
-\section{Processus de build}\label{processus-de-build}}
-
-\textbf{TODO: expliquer comment sont construites les différentes parties
-du projet. Expliquer les différentes parties du makefile et les
-différentes images docker utilisées pour construire les différents
-composants.}
-
-\hypertarget{duxe9ploiement-du-serveur}{%
-\section{Déploiement du serveur}\label{duxe9ploiement-du-serveur}}
-
-\textbf{TODO: expliquer comment le serveur peut fonctionner à l'aide
-d'un \texttt{docker-compose} réunissant les serveurs TFTP, NFS et DHCP.
-Expliquer comment ces différentes parties sont utilisés dans un
-environnement de développement, les limitations, et comment adapter
-cette configuration à un environnement de production.}
-
-\hypertarget{structure-des-images}{%
-\section{Structure des images}\label{structure-des-images}}
-
-\textbf{TODO: expliquer exactement comment sont structurées les données
-des images (raw et clonezilla).}
-
-\hypertarget{utilisation-du-systuxe8me-duxe9ployuxe9}{%
-\chapter{Utilisation du système
-déployé}\label{utilisation-du-systuxe8me-duxe9ployuxe9}}
-
-\hypertarget{duxe9ployer-une-image-sur-un-poste}{%
-\section{Déployer une image sur un
-poste}\label{duxe9ployer-une-image-sur-un-poste}}
-
-Cette section contient une marche à suivre qui décrit les étapes pour
-déployer une image sur un poste client quand un serveur est déjà
-installé et configuré, que la machine est configurée pour démarrer sur
-le réseau.
-
-\begin{enumerate}
-\def\labelenumi{\arabic{enumi}.}
-\tightlist
-\item
-  Démarrer la machine et attendre qu'elle
-\end{enumerate}
-
-\textbf{TODO: expliquer pas à pas comment utiliser l'interface pour
-déployer une image sur un client et les différentes inter-actions de
-l'utilisateur, avec des captures d'écran, etc.}
-
-\hypertarget{cruxe9ation-dune-image-clonezilla}{%
-\section{Création d'une image
-clonezilla}\label{cruxe9ation-dune-image-clonezilla}}
-
-\textbf{TODO: expliquer pas à pas comment créer une image avec
-clonezilla et comment l'ajouter au serveur de déploiement.}
-
-\hypertarget{cruxe9ation-dune-image-dd}{%
-\section{Création d'une image dd}\label{cruxe9ation-dune-image-dd}}
-
-\textbf{TODO: expliquer pas à pas comment créer une image avec
-clonezilla et comment l'ajouter au serveur de déploiement.}
-
-\hypertarget{pruxe9paration-dune-image-pour-quelle-supporte-le-systuxe8me-de-personnalisation}{%
-\section{Préparation d'une image pour qu'elle supporte le système de
-personnalisation}\label{pruxe9paration-dune-image-pour-quelle-supporte-le-systuxe8me-de-personnalisation}}
-
-\textbf{TODO: expliquer comment préparer un système pour qu'il supporte
-le système de personnalisation avec ansible, et comment créer les
-scripts de personnalisation, avec un exemple type simple.}
-
-\hypertarget{conclusion}{%
-\chapter{Conclusion}\label{conclusion}}
-
-\hypertarget{synthuxe8se-du-travail-effectuuxe9}{%
-\section{Synthèse du travail
-effectué}\label{synthuxe8se-du-travail-effectuuxe9}}
-
-Le travail initial a été récupéré, analysé, documenté et remis en
-fonctionnement en corrigeant quelques problèmes dans les fichiers de
-configuration et les scripts de déploiement. L'outil \emph{Vagrant} a
-été utilisé pour automatiser la création d'un serveur virtuel qui
-exécute les différents services du système.
-
-Le système a été ensuite modifié pour le rendre compatible avec les
-ordinateurs modernes utilisant le standard
-\protect\hyperlink{acronym__UEFI}{UEFI} au lieu d'un
-\protect\hyperlink{acronym__BIOS}{BIOS}.
-
-Des mesures ont été effectuées pour déterminer si le choix du protocole
-\protect\hyperlink{acronym__NFS}{NFS}, le protocole réseau utilisé pour
-transférer les images, était pertinent. Il été comparé aux protocoles
-\protect\hyperlink{acronym__SCP}{SCP},
-\protect\hyperlink{acronym__HTTP}{HTTP},
-\protect\hyperlink{acronym__FTP}{FTP},
-\protect\hyperlink{acronym__NFS}{NFS},
-\protect\hyperlink{acronym__SMB}{SMB} et
-\protect\hyperlink{acronym__IPFS}{IPFS} en mesurant le temps de
-transfert d'une image. Ces mesures ont montré que les temps de
-déploiement avec ces différents protocoles étaient similaires, à
-l'exception d'\protect\hyperlink{acronym__IPFS}{IPFS} qui prenait
-beaucoup plus de temps. Le protocole
-\protect\hyperlink{acronym__NFS}{NFS} a donc été gardé car les mesures
-ont prouvé que ses performances étaient similaires à ses alternatives.
-
-Un format d'images alternatif aux images brutes compressées a été
-recherché. Une solution produisant des images plus petites et
-déployables plus rapidement a été trouvée: utiliser des images produites
-avec l'outil \emph{Clonezilla}. Cet outil permet aussi de faciliter la
-création d'images en utilisant sa version \emph{live}. Des mesures
-prouvant que ce système de déploiement d'images offre un réel avantage
-en espace utilisé et en temps de déploiement par rapport aux images
-brutes compressées.
-
-Le système d'exploitation utilisé pour effectuer le déploiement a été
-complètement remplacé. Initialement construit avec \emph{Buildroot},
-avec un système de fichiers racine chargé entièrement en mémoire, il a
-été remplacé par un système \emph{Debian} dont le système de fichiers
-racine est monté depuis un partage \protect\hyperlink{acronym__NFS}{NFS}
-en lecture seule. Ce système permet une installation aisée de tous les
-paquets \emph{Debian}, notamment \emph{Clonezilla} qui était compliqué à
-installer sur un système construit avec \emph{Buildroot}. La création de
-ce système d'exploitation a été automatisée et encapsulée dans un
-conteneur \emph{Docker} pour rendre sa modification et reconstruction
-très simple, indépendamment du système d'exploitation utilisé.
-
-Les scripts de déploiement du système initial ont été réécrits. Une
-gestion avancée des erreurs a été implémentée. Un système de mesure et
-d'affichage du temps d'exécution de chaque partie du déploiement a été
-développé. La génération de fichiers de log a été améliorée pour qu'ils
-fournissent plus d'informations utiles et qu'ils soient structurés de
-manière à rendre leur gestion et leur consultation plus aisée. Le
-déploiement d'images avec \emph{Clonezilla} a été implémenté, tout en
-gardant la possibilité d'utiliser des images brutes compressées pour
-offrir plus de flexibilité et permettre de comparer les deux systèmes.
-Le support des images de systèmes d'exploitations compatibles
-\protect\hyperlink{acronym__UEFI}{UEFI} a aussi été implémenté,
-notamment en permettant de déterminer automatiquement l'exécutable
-\protect\hyperlink{acronym__EFI}{EFI} qui devra être lancé pour démarrer
-le système déployé.
-
-Enfin, un système de personnalisation d'un système après son déploiement
-a été conçu, permettant de définir des configurations que l'utilisateur
-peut choisir de copier ou non sur le système déployé. Une image de
-système d'exploitation peut être conçue pour exécuter les fichiers
-copiés par ces personnalisations dans un dossier spécifique, pour
-permettre des configurations complexes exécutées lors du démarrage avec
-un outil choisi, par exemple \emph{Ansible}. Ce système offre beaucoup
-de flexibilité et permet de définir des configurations avancées tout en
-gardant le système de déploiement indépendant de ce qui est utilisé pour
-les exécuter, car le seul mécanisme présent dans le système de
-déploiement est la copie de fichiers sur une partition donnée.
-
-\hypertarget{points-damuxe9lioration}{%
-\section{Points d'amélioration}\label{points-damuxe9lioration}}
-
-Bien que le système à la fin de ce projet soit parfaitement fonctionnel,
-il existe des points qui devraient ou pourraient être étudiés, améliorés
-ou implémentés pour que le système soit prêt à une utilisation dans un
-cadre réel.
-
-\hypertarget{amuxe9lioration-des-performances-de-tuxe9luxe9chargement-des-images-sur-un-ruxe9seau-ruxe9el-avec-de-nombreux-clients-simultanuxe9s}{%
-\subsection{Amélioration des performances de téléchargement des images
-sur un réseau réel avec de nombreux clients
-simultanés}\label{amuxe9lioration-des-performances-de-tuxe9luxe9chargement-des-images-sur-un-ruxe9seau-ruxe9el-avec-de-nombreux-clients-simultanuxe9s}}
-
-Le protocole réseau utilisé pour le téléchargement des images a été
-testé avec un client unique, sur un réseau minimal ne comprenant que le
-client et le serveur. Il est très probable que le temps de
-téléchargement des images soit beaucoup plus long que celui mesuré dans
-le cadre de ce travail si de nombreux clients téléchargent des images en
-même temps, dans un réseau plus complexe tel que celui de l'école.
-
-L'étude et la mitigation de cette problématique a volontairement été
-mise de côté dans le cadre de ce travail car il était difficile de
-simuler les conditions réelles du système déployé dans une école alors
-que tout le travail a été effectué hors de l'école, dans un petit réseau
-local domestique avec une quantité limitée d'ordinateurs à disposition
-pour faire des tests.
-
-Différentes approches pourraient être utilisées pour améliorer ces
-performances, telles que la copie en \emph{multicast} des images, la
-redondance des serveurs mettant à disposition les images ou encore
-l'utilisation d'un protocole \emph{pair à pair} tel que
-\emph{Bittorrent} ou \emph{IPFS} pour permettre de distribuer le
-transfert des images sur tous les clients connectés plutôt que
-d'utiliser uniquement le serveur central comme source du fichiers.
-
-\hypertarget{amuxe9lioration-du-systuxe8me-de-personnalisation-des-images}{%
-\subsection{Amélioration du système de personnalisation des
-images}\label{amuxe9lioration-du-systuxe8me-de-personnalisation-des-images}}
-
-Le système de personnalisation des images a été implémenté tardivement
-dans le travail. Bien qu'il soit fonctionnel, il n'a pas été testé
-extensivement. Il faudrait passer un peu de temps à créer des
-configurations post-déploiement complexes qui sont exécutées au
-démarrage par le système déployé et de valider leur fonctionnement.
-
-Par exemple, il était prévu de tester l'exécution de \emph{playbooks}
-\emph{Ansible} au démarrage du système, copiés selon les choix de
-personnalisation de l'utilisateur. Ces \emph{playbooks} pourraient étre
-utilisés pour effectuer de nombreuses actions, telles que l'installation
-de groupes de paquets choisis, la génération d'un nom d'hôte unique pour
-la machine et la connexion à un domaine \emph{Active Directory} pour
-permettre aux élèves de se connecter avec le même nom d'utilisateur et
-d'avoir accès à leur dossier \emph{home} depuis un partage
-\protect\hyperlink{acronym__NFS}{NFS}, comme sur les postes de travail
-standards présents de l'école.
-
-\hypertarget{amuxe9lioration-de-la-suxe9curituxe9}{%
-\subsection{Amélioration de la
-sécurité}\label{amuxe9lioration-de-la-suxe9curituxe9}}
-
-Sur le système actuel, un utilisateur mal intentionné peut détruire ou
-modifier les images présentes sur le serveur distant, car elles sont
-récupérées sur un partage \protect\hyperlink{acronym__NFS}{NFS} avec des
-droits de lecture-écriture. La raison de ce partage en lecture et
-écriture est que les logs sont écrits sur le même partage. Une manière
-simple de résoudre ce problème serait de séparer ce partage en deux: le
-premier en lecture seule contiendrait les images et le second
-contiendrait les logs uniquement.
-
-Il faudrait ensuite trouver une solution pour empêcher une machine
-d'aller modifier ou supprimer les logs d'une autre machine, ce qui est
-compliqué à mettre en oeuvre avec un partage
-\protect\hyperlink{acronym__NFS}{NFS}. Peut être que les logs pourraient
-être transmis au serveur en utilisant un autre canal de communication et
-de déléguer la création et le nommage du fichier au serveur, pour que
-les clients ne soient plus capables d'accéder directement aux fichiers
-des logs, mais que ce soit le serveur qui ait la responsabilité de les
-créer et de les gérer.
-
-\hypertarget{ruxe9trospection-sur-le-duxe9roulement-du-travail}{%
-\section{Rétrospection sur le déroulement du
-travail}\label{ruxe9trospection-sur-le-duxe9roulement-du-travail}}
-
-J'ai eu beaucoup d'intérêt à travailler sur ce sujet. Cela m'a permis de
-mettre en pratique de nombreuses compétences acquises lors des cours
-suivis les quatre années précédentes, dont en particulier les cours de
-programmation des systèmes (\emph{sIT\_242}), systèmes d'exploitation
-(\emph{sIT\_244}), réseaux et protocoles informatiques (sIT\_362),
-réseaux avancés (\emph{sIT\_384}), programmation avancée des systèmes
-(\emph{sIT\_632}) et virtualisation des
-\protect\hyperlink{acronym__SI}{SI} (\emph{sIT\_632}).
-
-\hypertarget{ruxe9fuxe9rences}{%
-\chapter{Références}\label{ruxe9fuxe9rences}}
-
-\appendix
-
-\hypertarget{appendix_source}{%
-\chapter{Codes sources notables}\label{appendix_source}}
-
-Cette annexe contient les listings des codes sources les plus importants
-du projet.
-
-\hypertarget{makefile-configuration-gnu-make-du-projet}{%
-\section{\texorpdfstring{\texttt{Makefile}: configuration \emph{GNU
-Make} du
-projet}{Makefile: configuration GNU Make du projet}}\label{makefile-configuration-gnu-make-du-projet}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\DataTypeTok{SHELL }\CharTok{:=}\StringTok{ /bin/bash}
-\DataTypeTok{MAKEFLAGS }\CharTok{+=}\StringTok{ "{-}j 4"}
-
-\DataTypeTok{DOCKER\_BUILDKIT\_BUILD }\CharTok{=}\StringTok{ DOCKER\_BUILDKIT=1 docker build {-}{-}progress=plain}
-
-\DataTypeTok{GRUB\_SRC }\CharTok{:=}\StringTok{ }\CharTok{$(}\KeywordTok{shell}\StringTok{ find grub/bootiful{-}grub/ {-}type f {-}regex ".*\textbackslash{}.[c|h|sh|py|cfg|conf]"}\CharTok{)}
-\DataTypeTok{GRUB\_I386\_PC\_BIN }\CharTok{=}\StringTok{ tftp/tftpboot/boot/grub/i386{-}pc/core.0}
-\DataTypeTok{GRUB\_I386\_EFI\_BIN }\CharTok{=}\StringTok{ tftp/tftpboot/boot/grub/i386{-}efi/core.efi}
-\DataTypeTok{GRUB\_X86\_64\_EFI\_BIN }\CharTok{=}\StringTok{ tftp/tftpboot/boot/grub/x86\_64{-}efi/core.efi}
-\DataTypeTok{DEPLOYER\_SRC }\CharTok{:=}\StringTok{ }\CharTok{$(}\KeywordTok{wildcard}\StringTok{ deployer/*}\CharTok{)}
-\DataTypeTok{TFTP\_DEPLOYER\_DIR }\CharTok{=}\StringTok{ tftp/tftpboot/boot/deployer}
-\DataTypeTok{TFTP\_DEPLOYER\_VMLINUZ }\CharTok{:=}\StringTok{ }\CharTok{$(}\DataTypeTok{TFTP\_DEPLOYER\_DIR}\CharTok{)}\StringTok{/vmlinuz}
-\DataTypeTok{TFTP\_DEPLOYER\_INITRD }\CharTok{:=}\StringTok{ }\CharTok{$(}\DataTypeTok{TFTP\_DEPLOYER\_DIR}\CharTok{)}\StringTok{/initrd.img}
-\DataTypeTok{NFS\_DEPLOYER\_ROOT }\CharTok{:=}\StringTok{ nfs/nfsroot.tar.gz}
-\DataTypeTok{LATEST\_LOG }\CharTok{:=}\StringTok{ }\CharTok{$(}\KeywordTok{shell}\StringTok{ ls {-}1 nfs/nfsshared/log/*.log | tail {-}n 1}\CharTok{)}
-
-\OtherTok{.PHONY:}\DataTypeTok{ doc grub deployer start{-}server reprovision{-}server clean print\_last\_log help}
-
-\CommentTok{\# Builds everything}
-\DecValTok{all:}\DataTypeTok{ doc grub deployer}
-
-\CommentTok{\# Builds PDF and markdown documents}
-\DecValTok{doc:}
-    \CharTok{$(}\DataTypeTok{MAKE}\CharTok{)}\NormalTok{ {-}C doc}
-
-\DecValTok{grub/bootiful{-}grub/bootstrap partclone/bootiful{-}partclone/Makefile.am:}\DataTypeTok{ .gitmodules}
-\NormalTok{    git submodule init \&\& git submodule update}
-
-\CommentTok{\# Bootstraps GRUB  dependencies and configuration script}
-\DecValTok{grub/bootiful{-}grub/configure:}\DataTypeTok{ grub/bootiful{-}grub/bootstrap}
-\NormalTok{    (pushd grub/bootiful{-}grub \&\& ./bootstrap; popd)}
-
-\CommentTok{\# Builds GRUB for i386{-}pc}
-\DecValTok{$(GRUB\_I386\_PC\_BIN):}\DataTypeTok{ grub/Dockerfile grub/bootiful{-}grub/configure }\CharTok{$(}\DataTypeTok{GRUB\_SRC}\CharTok{)}
-    \CharTok{$(}\DataTypeTok{DOCKER\_BUILDKIT\_BUILD}\CharTok{)}\NormalTok{ ./grub }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}output ./tftp/tftpboot }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}build{-}arg PLATFORM=pc }\CharTok{\textbackslash{}}
-\NormalTok{          {-}{-}build{-}arg TARGET=i386}
-
-\CommentTok{\# Builds GRUB for i386{-}efi}
-\DecValTok{$(GRUB\_I386\_EFI\_BIN):}\DataTypeTok{ grub/Dockerfile grub/bootiful{-}grub/configure }\CharTok{$(}\DataTypeTok{GRUB\_SRC}\CharTok{)}
-    \CharTok{$(}\DataTypeTok{DOCKER\_BUILDKIT\_BUILD}\CharTok{)}\NormalTok{ ./grub }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}output ./tftp/tftpboot }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}build{-}arg PLATFORM=efi }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}build{-}arg TARGET=i386}
-
-\CommentTok{\# Builds GRUB for x86\_64{-}efi}
-\DecValTok{$(GRUB\_X86\_64\_EFI\_BIN):}\DataTypeTok{ grub/Dockerfile grub/bootiful{-}grub/configure }\CharTok{$(}\DataTypeTok{GRUB\_SRC}\CharTok{)}
-    \CharTok{$(}\DataTypeTok{DOCKER\_BUILDKIT\_BUILD}\CharTok{)}\NormalTok{ ./grub }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}output ./tftp/tftpboot }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}build{-}arg PLATFORM=efi }\CharTok{\textbackslash{}}
-\NormalTok{        {-}{-}build{-}arg TARGET=x86\_64}
-
-\CommentTok{\# Builds GRUB for all platforms}
-\DecValTok{grub:}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{GRUB\_I386\_PC\_BIN}\CharTok{)}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{GRUB\_I386\_EFI\_BIN}\CharTok{)}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{GRUB\_X86\_64\_EFI\_BIN}\CharTok{)}
-
-\CommentTok{\# Builds the deployer OS}
-\DecValTok{deployer:}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{TFTP\_DEPLOYER\_VMLINUZ}\CharTok{)}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{TFTP\_DEPLOYER\_INITRD}\CharTok{)}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{NFS\_DEPLOYER\_ROOT}\CharTok{)}
-
-\DecValTok{$(TFTP\_DEPLOYER\_VMLINUZ) $(TFTP\_DEPLOYER\_INITRD) \&:}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{DEPLOYER\_SRC}\CharTok{)}
-    \CharTok{$(}\DataTypeTok{DOCKER\_BUILDKIT\_BUILD}\CharTok{)}\NormalTok{ ./deployer {-}{-}target tftp{-}export{-}stage {-}{-}output }\CharTok{$(}\DataTypeTok{TFTP\_DEPLOYER\_DIR}\CharTok{)}\NormalTok{ \&\& }\CharTok{\textbackslash{}}
-\NormalTok{    touch {-}c }\CharTok{$(}\DataTypeTok{TFTP\_DEPLOYER\_VMLINUZ}\CharTok{)} \CharTok{$(}\DataTypeTok{TFTP\_DEPLOYER\_INITRD}\CharTok{)}
-
-\DecValTok{$(NFS\_DEPLOYER\_ROOT):}\DataTypeTok{ }\CharTok{$(}\DataTypeTok{DEPLOYER\_SRC}\CharTok{)}
-    \CharTok{$(}\DataTypeTok{DOCKER\_BUILDKIT\_BUILD}\CharTok{)}\NormalTok{ ./deployer {-}{-}target nfs{-}export{-}stage {-}{-}output nfs/ \&\& }\CharTok{\textbackslash{}}
-\NormalTok{    touch {-}c }\CharTok{$(}\DataTypeTok{NFS\_DEPLOYER\_ROOT}\CharTok{)}
-
-\CommentTok{\# Starts bootiful services in docker containers}
-\DecValTok{start{-}server:}\DataTypeTok{ grub deployer}
-\NormalTok{    docker{-}compose up {-}{-}build {-}{-}remove{-}orphans {-}{-}abort{-}on{-}container{-}exit}
-
-\CommentTok{\# Removes all generated files}
-\DecValTok{clean:}
-\NormalTok{    rm {-}rf deployer/rootfs}
-    \CharTok{$(}\DataTypeTok{MAKE}\CharTok{)}\NormalTok{ {-}C doc clean}
-
-\CommentTok{\# Prints the latest deployment log file}
-\DecValTok{print{-}latest{-}log:}
-\NormalTok{    cat }\CharTok{$(}\DataTypeTok{LATEST\_LOG}\CharTok{)}
-
-\CommentTok{\# Show this help.}
-\DecValTok{help:}
-\NormalTok{    printf }\StringTok{"Usage:  make \textless{}target\textgreater{}\textbackslash{}n\textbackslash{}nTargets:\textbackslash{}n"}
-\NormalTok{    awk }\StringTok{\textquotesingle{}/\^{}\#/\{c=substr(}\CharTok{$$}\StringTok{0,3);next\}c\&\&/\^{}[[:alpha:]][[:alnum:]\_{-}]+:/\{print "  " substr(}\CharTok{$$}\StringTok{1,1,index(}\CharTok{$$}\StringTok{1,":")),c\}1\{c=0\}\textquotesingle{}} \CharTok{$(}\DataTypeTok{MAKEFILE\_LIST}\CharTok{)}\NormalTok{ | column {-}s: {-}t}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{docker-compose.yml-configuration-docker-compose-du-serveur-de-duxe9ploiement}{%
-\section{\texorpdfstring{\texttt{docker-compose.yml}: configuration
-\emph{docker-compose} du serveur de
-déploiement}{docker-compose.yml: configuration docker-compose du serveur de déploiement}}\label{docker-compose.yml-configuration-docker-compose-du-serveur-de-duxe9ploiement}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\FunctionTok{version}\KeywordTok{:}\AttributeTok{ }\StringTok{"3.8"}
-
-\FunctionTok{services}\KeywordTok{:}
-\AttributeTok{  }\FunctionTok{bootiful{-}dhcp}\KeywordTok{:}
-\AttributeTok{    }\FunctionTok{build}\KeywordTok{:}\AttributeTok{ ./dhcp}
-\AttributeTok{    }\FunctionTok{network\_mode}\KeywordTok{:}\AttributeTok{ host}
-\AttributeTok{  }\FunctionTok{bootiful{-}tftp}\KeywordTok{:}
-\AttributeTok{    }\FunctionTok{build}\KeywordTok{:}\AttributeTok{ ./tftp}
-\AttributeTok{    }\FunctionTok{network\_mode}\KeywordTok{:}\AttributeTok{ host}
-\AttributeTok{    }\FunctionTok{volumes}\KeywordTok{:}
-\AttributeTok{      }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{type}\KeywordTok{:}\AttributeTok{ bind}
-\AttributeTok{        }\FunctionTok{source}\KeywordTok{:}\AttributeTok{ ./tftp/tftpboot}
-\AttributeTok{        }\FunctionTok{target}\KeywordTok{:}\AttributeTok{ /tftpboot}
-\AttributeTok{        }\FunctionTok{read\_only}\KeywordTok{:}\AttributeTok{ }\CharTok{yes}
-\AttributeTok{  }\FunctionTok{bootiful{-}nfs}\KeywordTok{:}
-\AttributeTok{    }\FunctionTok{build}\KeywordTok{:}\AttributeTok{ ./nfs}
-\AttributeTok{    }\FunctionTok{network\_mode}\KeywordTok{:}\AttributeTok{ host}
-\AttributeTok{    }\FunctionTok{privileged}\KeywordTok{:}\AttributeTok{ }\CharTok{yes}
-\AttributeTok{    }\FunctionTok{volumes}\KeywordTok{:}
-\AttributeTok{      }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{type}\KeywordTok{:}\AttributeTok{ tmpfs}
-\AttributeTok{        }\FunctionTok{target}\KeywordTok{:}\AttributeTok{ /nfsroot}
-\AttributeTok{      }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{type}\KeywordTok{:}\AttributeTok{ bind}
-\AttributeTok{        }\FunctionTok{source}\KeywordTok{:}\AttributeTok{ /run/media/araxor/bigdata/nfsshared}
-\AttributeTok{        }\FunctionTok{target}\KeywordTok{:}\AttributeTok{ /nfsshared}
-\AttributeTok{      }\KeywordTok{{-}}\AttributeTok{ }\FunctionTok{type}\KeywordTok{:}\AttributeTok{ bind}
-\AttributeTok{        }\FunctionTok{source}\KeywordTok{:}\AttributeTok{ /lib/modules}
-\AttributeTok{        }\FunctionTok{target}\KeywordTok{:}\AttributeTok{ /lib/modules}
-\AttributeTok{        }\FunctionTok{read\_only}\KeywordTok{:}\AttributeTok{ }\CharTok{yes}
-\AttributeTok{    }\FunctionTok{environment}\KeywordTok{:}
-\AttributeTok{      }\FunctionTok{NFS\_LOG\_LEVEL}\KeywordTok{:}\AttributeTok{ DEBUG}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployer_dockerfile}{%
-\section{\texorpdfstring{\texttt{deployer/Dockerfile}: configuration
-\emph{Docker} pour la construction de l'OS de
-déploiement}{deployer/Dockerfile: configuration Docker pour la construction de l'OS de déploiement}}\label{deployer_dockerfile}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{FROM}\NormalTok{ debian:bullseye as build{-}stage}
-\KeywordTok{RUN}\NormalTok{ apt{-}get update \&\& apt{-}get install {-}y multistrap}
-
-\KeywordTok{WORKDIR}\NormalTok{ /multistrap}
-
-\KeywordTok{ADD}\NormalTok{ ./multistrap.config ./}
-\KeywordTok{RUN}\NormalTok{ multistrap {-}{-}arch amd64 {-}{-}file ./multistrap.config {-}{-}dir ./rootfs {-}{-}tidy{-}up}
-
-\KeywordTok{ADD}\NormalTok{ ./hostname ./rootfs/etc/hostname}
-\KeywordTok{ADD}\NormalTok{ ./hosts ./rootfs/etc/hosts}
-\KeywordTok{ADD}\NormalTok{ ./fstab ./rootfs/etc/fstab}
-\KeywordTok{ADD}\NormalTok{ ./initramfs.conf ./rootfs/etc/initramfs{-}tools/initramfs.conf}
-\KeywordTok{ADD}\NormalTok{ ./bootiful{-}deploy{-}log.service ./rootfs/etc/systemd/system/bootiful{-}deploy{-}log.service}
-
-\KeywordTok{ADD}\NormalTok{ ./configure.sh ./rootfs/}
-\KeywordTok{RUN}\NormalTok{ chroot /multistrap/rootfs ./configure.sh}
-
-\KeywordTok{RUN}\NormalTok{ mkdir ./boot ./rootfs/bootiful ./rootfs/var/lib/clonezilla ./rootfs/home/partimag}
-\KeywordTok{RUN}\NormalTok{ ln {-}s /proc/mounts rootfs/etc/mtab}
-\KeywordTok{RUN}\NormalTok{ cp ./rootfs/vmlinuz ./rootfs/initrd.img ./boot/ \&\& \textbackslash{}}
-\NormalTok{    rm {-}rf ./rootfs/configure.sh ./rootfs/vmlinuz* ./rootfs/initrd.img* ./rootfs/boot}
-
-\KeywordTok{ADD}\NormalTok{ ./bootiful{-}deploy{-}init ./rootfs/usr/bin/}
-\KeywordTok{ADD}\NormalTok{ ./bootiful{-}common ./rootfs/usr/bin/}
-\KeywordTok{ADD}\NormalTok{ ./bootiful{-}deploy ./rootfs/usr/bin/}
-\KeywordTok{ADD}\NormalTok{ ./bootiful{-}save{-}image ./rootfs/usr/bin/}
-\KeywordTok{ADD}\NormalTok{ ./bootiful{-}reset{-}cache ./rootfs/usr/bin/}
-\KeywordTok{RUN}\NormalTok{ tar {-}czf nfsroot.tar.gz rootfs {-}{-}hard{-}dereference \&\& rm {-}rf ./rootfs}
-
-\KeywordTok{FROM}\NormalTok{ scratch AS nfs{-}export{-}stage}
-\KeywordTok{COPY}\NormalTok{ {-}{-}from=build{-}stage /multistrap/nfsroot.tar.gz /}
-
-\KeywordTok{FROM}\NormalTok{ scratch AS tftp{-}export{-}stage}
-\KeywordTok{COPY}\NormalTok{ {-}{-}from=build{-}stage /multistrap/boot /}
-
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerbootiful-deploy-log.service-configuration-de-lunituxe9-systemd-des-script-de-duxe9ploiement}{%
-\section{\texorpdfstring{\texttt{deployer/bootiful-deploy-log.service}:
-configuration de l'unité \emph{Systemd} des script de
-déploiement}{deployer/bootiful-deploy-log.service: configuration de l'unité Systemd des script de déploiement}}\label{deployerbootiful-deploy-log.service-configuration-de-lunituxe9-systemd-des-script-de-duxe9ploiement}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{[Unit]}
-\DataTypeTok{Description}\OtherTok{=}\StringTok{Bootiful interactive remote image deployment}
-\DataTypeTok{Conflicts}\OtherTok{=}\StringTok{gettytty1.service}
-\DataTypeTok{Before}\OtherTok{=}\StringTok{getty.target}
-
-\KeywordTok{[Service]}
-\DataTypeTok{Type}\OtherTok{=}\StringTok{oneshot}
-\DataTypeTok{RemainAfterExit}\OtherTok{=}\KeywordTok{yes}
-\DataTypeTok{ExecStartPre}\OtherTok{=}\StringTok{/bin/sleep }\DecValTok{2}
-\DataTypeTok{ExecStart}\OtherTok{=}\StringTok{/usr/bin/bootiful{-}deploy{-}init}
-\DataTypeTok{StandardInput}\OtherTok{=}\StringTok{tty}
-\DataTypeTok{StandardOutput}\OtherTok{=}\StringTok{tty}
-\DataTypeTok{StandardError}\OtherTok{=}\StringTok{tty}
-\DataTypeTok{ }
-\KeywordTok{[Install]}
-\DataTypeTok{WantedBy}\OtherTok{=}\StringTok{multi{-}user.target}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerinitramfs.conf-configuration-pour-cruxe9ation-dun-initramfs-pour-duxe9marrer-avec-nfs}{%
-\section{\texorpdfstring{\texttt{deployer/initramfs.conf}: configuration
-pour création d'un \emph{initramfs} pour démarrer avec
-\protect\hyperlink{acronym__NFS}{NFS}}{deployer/initramfs.conf: configuration pour création d'un initramfs pour démarrer avec NFS}}\label{deployerinitramfs.conf-configuration-pour-cruxe9ation-dun-initramfs-pour-duxe9marrer-avec-nfs}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#}
-\CommentTok{\# initramfs.conf}
-\CommentTok{\# Configuration file for mkinitramfs(8). See initramfs.conf(5).}
-\CommentTok{\#}
-\CommentTok{\# Note that configuration options from this file can be overridden}
-\CommentTok{\# by config files in the /etc/initramfs{-}tools/conf.d directory.}
-
-\CommentTok{\#}
-\CommentTok{\# MODULES: [ most | netboot | dep | list ]}
-\CommentTok{\#}
-\CommentTok{\# most {-} Add most filesystem and all harddrive drivers.}
-\CommentTok{\#}
-\CommentTok{\# dep {-} Try and guess which modules to load.}
-\CommentTok{\#}
-\CommentTok{\# netboot {-} Add the base modules, network modules, but skip block devices.}
-\CommentTok{\#}
-\CommentTok{\# list {-} Only include modules from the \textquotesingle{}additional modules\textquotesingle{} list}
-\CommentTok{\#}
-
-\VariableTok{MODULES=}\NormalTok{netboot}
-
-\CommentTok{\#}
-\CommentTok{\# BUSYBOX: [ y | n | auto ]}
-\CommentTok{\#}
-\CommentTok{\# Use busybox shell and utilities.  If set to n, klibc utilities will be used.}
-\CommentTok{\# If set to auto (or unset), busybox will be used if installed and klibc will}
-\CommentTok{\# be used otherwise.}
-\CommentTok{\#}
-
-\VariableTok{BUSYBOX=}\NormalTok{auto}
-
-\CommentTok{\#}
-\CommentTok{\# KEYMAP: [ y | n ]}
-\CommentTok{\#}
-\CommentTok{\# Load a keymap during the initramfs stage.}
-\CommentTok{\#}
-
-\VariableTok{KEYMAP=}\NormalTok{n}
-
-\CommentTok{\#}
-\CommentTok{\# COMPRESS: [ gzip | bzip2 | lz4 | lzma | lzop | xz ]}
-\CommentTok{\#}
-
-\VariableTok{COMPRESS=}\NormalTok{xz}
-
-\CommentTok{\#}
-\CommentTok{\# NFS Section of the config.}
-\CommentTok{\#}
-
-\CommentTok{\#}
-\CommentTok{\# DEVICE: ...}
-\CommentTok{\#}
-\CommentTok{\# Specify a specific network interface, like eth0}
-\CommentTok{\# Overridden by optional ip= or BOOTIF= bootarg}
-\CommentTok{\#}
-
-\VariableTok{DEVICE=}
-
-\CommentTok{\#}
-\CommentTok{\# NFSROOT: [ auto | HOST:MOUNT ]}
-\CommentTok{\#}
-
-\VariableTok{NFSROOT=}\NormalTok{auto}
-
-\CommentTok{\#}
-\CommentTok{\# RUNSIZE: ...}
-\CommentTok{\#}
-\CommentTok{\# The size of the /run tmpfs mount point, like 256M or 10\%}
-\CommentTok{\# Overridden by optional initramfs.runsize= bootarg}
-\CommentTok{\#}
-
-\VariableTok{RUNSIZE=}\NormalTok{10}\ExtensionTok{\%}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployermultistrap.config-configuration-multistrap-pour-la-cruxe9ation-du-systuxe8me-de-fichiers-racine}{%
-\section{\texorpdfstring{\texttt{deployer/multistrap.config}:
-configuration \emph{multistrap} pour la création du système de fichiers
-racine}{deployer/multistrap.config: configuration multistrap pour la création du système de fichiers racine}}\label{deployermultistrap.config-configuration-multistrap-pour-la-cruxe9ation-du-systuxe8me-de-fichiers-racine}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{[General]}
-\DataTypeTok{unpack}\OtherTok{=}\KeywordTok{true}
-\DataTypeTok{bootstrap}\OtherTok{=}\StringTok{DRBL Debian}
-\DataTypeTok{aptsources}\OtherTok{=}\StringTok{Debian}
-\DataTypeTok{addimportant}\OtherTok{=}\KeywordTok{true}
-
-\KeywordTok{[Debian]}
-\DataTypeTok{packages}\OtherTok{=}\StringTok{nfs{-}common linux{-}image{-}amd64 parted systemd udev strace zstd dialog lolcat gdisk gawk pigz pv clonezilla partclone partimage cifs{-}utils}
-\DataTypeTok{source}\OtherTok{=}\StringTok{http://http.debian.net/debian}
-\DataTypeTok{keyring}\OtherTok{=}\StringTok{debian{-}archive{-}keyring}
-\DataTypeTok{suite}\OtherTok{=}\StringTok{bullseye}
-\DataTypeTok{components}\OtherTok{=}\StringTok{main contrib non{-}free}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerconfigure.sh-script-de-configuration-du-systuxe8me-de-fichier-racine-uxe0-exuxe9cuter-en-chroot}{%
-\section{\texorpdfstring{\texttt{deployer/configure.sh}: script de
-configuration du système de fichier racine à exécuter en
-\texttt{chroot}}{deployer/configure.sh: script de configuration du système de fichier racine à exécuter en chroot}}\label{deployerconfigure.sh-script-de-configuration-du-systuxe8me-de-fichier-racine-uxe0-exuxe9cuter-en-chroot}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#!/bin/bash}
-
-\KeywordTok{set} \ExtensionTok{{-}e}
-
-\BuiltInTok{export} \VariableTok{DEBIAN\_FRONTEND=}\NormalTok{noninteractive }\VariableTok{DEBCONF\_NONINTERACTIVE\_SEEN=}\NormalTok{true}
-\BuiltInTok{export} \VariableTok{LC\_ALL=}\NormalTok{C }\VariableTok{LANGUAGE=}\NormalTok{C }\VariableTok{LANG=}\NormalTok{C}
-
-\ExtensionTok{dpkg}\NormalTok{ {-}{-}configure {-}a}
-
-\ExtensionTok{apt{-}get}\NormalTok{ autoremove {-}{-}purge}
-\ExtensionTok{apt{-}get}\NormalTok{ clean}
-
-\ExtensionTok{update{-}initramfs}\NormalTok{ {-}u}
-
-\ExtensionTok{systemctl}\NormalTok{ enable bootiful{-}deploy{-}log.service}
-
-\BuiltInTok{echo} \StringTok{"root:bootiful"} \KeywordTok{|} \ExtensionTok{chpasswd}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerbootiful-deploy-init-script-dinitialisation-du-duxe9ploiement}{%
-\section{\texorpdfstring{\texttt{deployer/bootiful-deploy-init}: script
-d'initialisation du
-déploiement}{deployer/bootiful-deploy-init: script d'initialisation du déploiement}}\label{deployerbootiful-deploy-init-script-dinitialisation-du-duxe9ploiement}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#!/bin/bash}
-
-\BuiltInTok{umask}\NormalTok{ {-}S 0000 }\OperatorTok{\&\textgreater{}}\NormalTok{/dev/null}
-\FunctionTok{clear}
-\ExtensionTok{/usr/games/lolcat}\NormalTok{ {-}a {-}d 6 {-}s 20 {-}F 0.5 }\OperatorTok{\textless{}\textless{}\textquotesingle{}EOF\textquotesingle{}}
-\NormalTok{ .o8                               .    o8o   .o88o.             oooo}
-\NormalTok{"888                             .o8    \textasciigrave{}"\textquotesingle{}   888 \textasciigrave{}"             \textasciigrave{}888}
-\NormalTok{ 888oooo.   .ooooo.   .ooooo.  .o888oo oooo  o888oo  oooo  oooo   888}
-\NormalTok{ d88\textquotesingle{} \textasciigrave{}88b d88\textquotesingle{} \textasciigrave{}88b d88\textquotesingle{} \textasciigrave{}88b   888   \textasciigrave{}888   888    \textasciigrave{}888  \textasciigrave{}888   888}
-\NormalTok{ 888   888 888   888 888   888   888    888   888     888   888   888}
-\NormalTok{ 888   888 888   888 888   888   888 .  888   888     888   888   888}
-\NormalTok{ \textasciigrave{}Y8bod8P\textquotesingle{} \textasciigrave{}Y8bod8P\textquotesingle{} \textasciigrave{}Y8bod8P\textquotesingle{}   "888" o888o o888o    \textasciigrave{}V88V"V8P\textquotesingle{} o888o}
-\OperatorTok{EOF}
-\BuiltInTok{declare} \VariableTok{logo\_pressed\_key}
-\BuiltInTok{read}\NormalTok{ {-}t 0.001 {-}n 1 {-}s {-}r }\VariableTok{logo\_pressed\_key}
-\BuiltInTok{readonly} \VariableTok{logo\_pressed\_key}
-
-\FunctionTok{select\_next\_action()} \KeywordTok{\{}
-    \BuiltInTok{local} \VariableTok{next\_action\_pressed\_key}
-    \KeywordTok{while} \FunctionTok{true}\KeywordTok{;} \KeywordTok{do}
-        \BuiltInTok{echo}
-        \BuiltInTok{echo} \StringTok{"Press \textquotesingle{}d\textquotesingle{} to restart deployment"}
-        \BuiltInTok{echo} \StringTok{"Press \textquotesingle{}s\textquotesingle{} to start an interactive command{-}line shell"}
-        \BuiltInTok{echo} \StringTok{"Press \textquotesingle{}r\textquotesingle{} to reboot"}
-        \BuiltInTok{echo} \StringTok{"Press \textquotesingle{}p\textquotesingle{} to power off"}
-
-        \BuiltInTok{read}\NormalTok{ {-}n 1 {-}s {-}r }\VariableTok{next\_action\_pressed\_key}
-        \KeywordTok{case} \StringTok{"}\VariableTok{$next\_action\_pressed\_key}\StringTok{"}\KeywordTok{ in}
-\NormalTok{            [dD]}\KeywordTok{)}
-                \BuiltInTok{echo} \StringTok{"Restarting deployment..."}
-                \BuiltInTok{break}
-                \KeywordTok{;;}
-\NormalTok{            [sS]}\KeywordTok{)}
-                \BuiltInTok{echo} \StringTok{"Starting an interactive command{-}line shell..."}
-                \ExtensionTok{/bin/bash}\NormalTok{ {-}i}
-                \KeywordTok{;;}
-\NormalTok{            [rR]}\KeywordTok{)}
-                \BuiltInTok{echo} \StringTok{"Rebooting..."}
-                \ExtensionTok{reboot}
-                \KeywordTok{;;}
-\NormalTok{            [pP]}\KeywordTok{)}
-                \BuiltInTok{echo} \StringTok{"Powering off..."}
-                \ExtensionTok{poweroff}
-                \KeywordTok{;;}
-\NormalTok{            *}\KeywordTok{)}
-                \BuiltInTok{echo} \StringTok{"Error: No action defined for key \textquotesingle{}}\VariableTok{$next\_action\_pressed\_key}\StringTok{\textquotesingle{}"}
-                \KeywordTok{;;}
-        \KeywordTok{esac}
-    \KeywordTok{done}
-\KeywordTok{\}}
-
-\KeywordTok{if [[} \StringTok{"}\VariableTok{$logo\_pressed\_key}\StringTok{"}\NormalTok{ =\textasciitilde{} \^{}[sS]$}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \BuiltInTok{echo} \StringTok{"Skipping deployment...."}
-    \ExtensionTok{/bin/bash}\NormalTok{ {-}i}
-    \ExtensionTok{select\_next\_action}
-\KeywordTok{fi}
-
-\KeywordTok{while}\NormalTok{ ! }\ExtensionTok{bootiful{-}deploy}\KeywordTok{;} \KeywordTok{do}
-    \BuiltInTok{echo} \StringTok{"Error in deployment."}
-    \ExtensionTok{select\_next\_action}
-\KeywordTok{done}
-
-\BuiltInTok{echo} \StringTok{"Deployment successful. Rebooting..."}
-\ExtensionTok{reboot}
-
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerbootiful-common-script-de-duxe9finition-des-fonctions-communes-aux-scripts-bootiful-}{%
-\section{\texorpdfstring{\texttt{deployer/bootiful-common}: script de
-définition des fonctions communes aux scripts
-\texttt{bootiful-*}}{deployer/bootiful-common: script de définition des fonctions communes aux scripts bootiful-*}}\label{deployerbootiful-common-script-de-duxe9finition-des-fonctions-communes-aux-scripts-bootiful-}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#!/bin/bash}
-
-\KeywordTok{if [[} \StringTok{"}\VariableTok{$\{BASH\_SOURCE[0]\}}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$0}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \BuiltInTok{echo} \OperatorTok{\textgreater{}\&2} \StringTok{"Error: script \textquotesingle{}}\VariableTok{$0}\StringTok{\textquotesingle{} must be sourced, not executed."}
-    \BuiltInTok{return}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\KeywordTok{if [[} \OtherTok{{-}n} \StringTok{"}\VariableTok{$BOOTIFUL\_COMMON\_SOURCED}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \BuiltInTok{echo} \OperatorTok{\textgreater{}\&2} \StringTok{"Warning: script \textquotesingle{}}\VariableTok{$0}\StringTok{\textquotesingle{} sourced more than once."}
-    \BuiltInTok{return}\NormalTok{ 0}
-\KeywordTok{fi}
-
-\BuiltInTok{readonly} \VariableTok{BOOTIFUL\_COMMON\_SOURCED=}\NormalTok{true}
-
-\FunctionTok{echo\_err()} \KeywordTok{\{}
-    \BuiltInTok{echo} \OperatorTok{\textgreater{}\&2} \StringTok{"$"}
-\KeywordTok{\}}
-
-\CommentTok{\# Writes an error message and a stack trace to stderr, then exits the current}
-\CommentTok{\# shell with the error status code 1.}
-\CommentTok{\#}
-\CommentTok{\# Warning: if called in a sub{-}shell, the error messages are written to stderr}
-\CommentTok{\#          but only the sub{-}shell is exited. The parent shell should always}
-\CommentTok{\#          check the sub{-}shells exit status codes and call \textasciigrave{}fatal\_error\textasciigrave{} if a}
-\CommentTok{\#          non{-}0 exit status is returned.}
-\FunctionTok{fatal\_error()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{message=}\StringTok{"}\VariableTok{$\{1:{-}}\NormalTok{unknown reason}\VariableTok{\}}\StringTok{"}
-
-    \ExtensionTok{echo\_err} \StringTok{"Fatal error: }\VariableTok{$message}\StringTok{"}
-
-    \ExtensionTok{echo\_err} \StringTok{"Stack trace:"}
-    \BuiltInTok{local} \VariableTok{frame=}\NormalTok{0}
-    \KeywordTok{while} \OperatorTok{\textgreater{}\&2} \BuiltInTok{caller} \VariableTok{$frame}\KeywordTok{;} \KeywordTok{do}
-        \KeywordTok{((}\NormalTok{frame++}\KeywordTok{))}
-    \KeywordTok{done}
-
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{\}}
-
-\CommentTok{\# If the INT signal (ctrl+c) is received, a fatal error is thrown}
-\FunctionTok{fatal\_error\_on\_sigint()} \KeywordTok{\{}
-    \ExtensionTok{fatal\_error} \StringTok{"SIGINT received"}
-\KeywordTok{\}}
-\BuiltInTok{trap}\NormalTok{ fatal\_error\_on\_sigint INT}
-
-\BuiltInTok{declare}\NormalTok{ {-}a }\VariableTok{exit\_callbacks=()}
-\FunctionTok{execute\_exit\_callbacks()} \KeywordTok{\{}
-    \KeywordTok{for} \ExtensionTok{exit\_callback}\NormalTok{ in }\StringTok{"}\VariableTok{$\{exit\_callbacks[]\}}\StringTok{"}\KeywordTok{;} \KeywordTok{do}
-        \StringTok{"}\VariableTok{$exit\_callback}\StringTok{"}
-    \KeywordTok{done}
-\KeywordTok{\}}
-\BuiltInTok{trap} \StringTok{\textquotesingle{}execute\_exit\_callbacks\textquotesingle{}}\NormalTok{ EXIT}
-
-\FunctionTok{add\_exit\_callback()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{exit\_callback\_function=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \VariableTok{exit\_callbacks+=(}\StringTok{"}\VariableTok{$exit\_callback\_function}\StringTok{"}\VariableTok{)}
-\KeywordTok{\}}
-
-\BuiltInTok{declare}\NormalTok{ {-}a }\VariableTok{step\_names=()}
-\BuiltInTok{declare}\NormalTok{ {-}a }\VariableTok{step\_timestamps=()}
-\BuiltInTok{declare}\NormalTok{ {-}a }\VariableTok{step\_durations=()}
-\BuiltInTok{declare}\NormalTok{ {-}a }\VariableTok{step\_types=()}
-
-\BuiltInTok{readonly} \VariableTok{STEP\_TYPE\_BATCH=}\StringTok{"batch"}
-\BuiltInTok{readonly} \VariableTok{STEP\_TYPE\_INTERACTIVE=}\StringTok{"interactive"}
-
-\FunctionTok{timestamp\_now()} \KeywordTok{\{}
-    \FunctionTok{date}\NormalTok{ +\%s}
-\KeywordTok{\}}
-
-\FunctionTok{finish\_step()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{step\_name=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{step\_start\_timestamp=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{step\_finish\_timestamp=}\StringTok{"}\VariableTok{$3}\StringTok{"}
-
-    \VariableTok{step\_durations+=($((}\StringTok{"}\VariableTok{$step\_finish\_timestamp}\StringTok{"}\NormalTok{ {-} }\StringTok{"}\VariableTok{$\{step\_start\_timestamp\}}\StringTok{"}\VariableTok{)))}
-    \ExtensionTok{echo\_err} \StringTok{"Finished }\VariableTok{$step\_name}\StringTok{ (duration: }\VariableTok{$\{step\_durations[{-}1]\}}\StringTok{s)"}
-\KeywordTok{\}}
-
-\FunctionTok{print\_step\_durations()} \KeywordTok{\{}
-
-    \KeywordTok{if [[} \StringTok{"$\{\#step\_timestamps[]\}"} \OtherTok{{-}gt}\NormalTok{ 1}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{finish\_step} \StringTok{"}\VariableTok{$\{step\_names[{-}1]\}}\StringTok{"} \KeywordTok{\textbackslash{}}
-            \StringTok{"}\VariableTok{$\{step\_timestamps[{-}1]\}}\StringTok{"} \KeywordTok{\textbackslash{}}
-            \StringTok{"}\VariableTok{$(}\ExtensionTok{timestamp\_now}\VariableTok{)}\StringTok{"}
-    \KeywordTok{fi}
-
-    \BuiltInTok{local} \VariableTok{total\_batch\_duration=}\NormalTok{0}
-    \BuiltInTok{local} \VariableTok{total\_interactive\_duration=}\NormalTok{0}
-    \BuiltInTok{local} \VariableTok{total\_duration=}\NormalTok{0}
-    \BuiltInTok{local} \VariableTok{step\_name}
-    \BuiltInTok{local} \VariableTok{step\_type}
-    \BuiltInTok{local} \VariableTok{step\_duration}
-    \BuiltInTok{local} \VariableTok{step\_number}
-
-    \ExtensionTok{echo\_err}
-    \ExtensionTok{echo\_err} \StringTok{"Steps duration summary:"}
-
-    \KeywordTok{for} \ExtensionTok{i}\NormalTok{ in }\StringTok{"$\{!step\_durations[]\}"}\KeywordTok{;} \KeywordTok{do}
-        \VariableTok{step\_name=}\StringTok{"}\VariableTok{$\{step\_names[$i]\}}\StringTok{"}
-        \VariableTok{step\_duration=}\StringTok{"}\VariableTok{$\{step\_durations[$i]\}}\StringTok{"}
-        \VariableTok{step\_type=}\StringTok{"}\VariableTok{$\{step\_types[$i]\}}\StringTok{"}
-        \VariableTok{step\_number=$((}\NormalTok{i + 1}\VariableTok{))}
-
-        \ExtensionTok{echo\_err} \StringTok{"}\VariableTok{$step\_number}\StringTok{ {-} }\VariableTok{$step\_name}\StringTok{ took }\VariableTok{$\{step\_duration\}}\StringTok{ seconds (}\VariableTok{$step\_type}\StringTok{)"}
-
-        \KeywordTok{case} \StringTok{"}\VariableTok{$step\_type}\StringTok{"}\KeywordTok{ in}
-        \StringTok{"}\VariableTok{$STEP\_TYPE\_BATCH}\StringTok{"}\KeywordTok{)}
-            \KeywordTok{((}\NormalTok{total\_batch\_duration += }\StringTok{"}\VariableTok{$step\_duration}\StringTok{"}\KeywordTok{))}
-            \KeywordTok{;;}
-        \StringTok{"}\VariableTok{$STEP\_TYPE\_INTERACTIVE}\StringTok{"}\KeywordTok{)}
-            \KeywordTok{((}\NormalTok{total\_interactive\_duration += }\StringTok{"}\VariableTok{$step\_duration}\StringTok{"}\KeywordTok{))}
-            \KeywordTok{;;}
-        \KeywordTok{esac}
-
-        \KeywordTok{((}\NormalTok{total\_duration += }\StringTok{"}\VariableTok{$step\_duration}\StringTok{"}\KeywordTok{))}
-    \KeywordTok{done}
-
-    \ExtensionTok{echo\_err}
-    \ExtensionTok{echo\_err} \StringTok{"Total batch duration: }\VariableTok{$\{total\_batch\_duration\}}\StringTok{s"}
-    \ExtensionTok{echo\_err} \StringTok{"Total interactive duration: }\VariableTok{$\{total\_interactive\_duration\}}\StringTok{s"}
-    \ExtensionTok{echo\_err} \StringTok{"Total duration: }\VariableTok{$\{total\_duration\}}\StringTok{s"}
-\KeywordTok{\}}
-
-\FunctionTok{start\_step()} \KeywordTok{\{}
-    \VariableTok{step\_timestamps+=(}\StringTok{"}\VariableTok{$(}\ExtensionTok{timestamp\_now}\VariableTok{)}\StringTok{"}\VariableTok{)}
-    \VariableTok{step\_names+=(}\StringTok{"}\VariableTok{$1}\StringTok{"}\VariableTok{)}
-    \VariableTok{step\_types+=(}\StringTok{"}\VariableTok{$2}\StringTok{"}\VariableTok{)}
-
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{steps\_count=}\StringTok{"$\{\#step\_timestamps[]\}"}
-
-    \KeywordTok{if [[} \VariableTok{$steps\_count} \OtherTok{{-}eq}\NormalTok{ 1}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{add\_exit\_callback} \StringTok{"print\_step\_durations"}
-    \KeywordTok{elif [[} \StringTok{"$\{\#step\_timestamps[]\}"} \OtherTok{{-}gt}\NormalTok{ 1}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{finish\_step} \StringTok{"}\VariableTok{$\{step\_names[{-}2]\}}\StringTok{"} \KeywordTok{\textbackslash{}}
-            \StringTok{"}\VariableTok{$\{step\_timestamps[{-}2]\}}\StringTok{"} \KeywordTok{\textbackslash{}}
-            \StringTok{"}\VariableTok{$\{step\_timestamps[{-}1]\}}\StringTok{"}
-    \KeywordTok{fi}
-
-    \ExtensionTok{echo\_err} \StringTok{"Started }\VariableTok{$\{step\_names[{-}1]\}}\StringTok{"}
-\KeywordTok{\}}
-
-\FunctionTok{start\_step\_batch()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{step\_name=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \ExtensionTok{start\_step} \StringTok{"}\VariableTok{$step\_name}\StringTok{"} \StringTok{"}\VariableTok{$STEP\_TYPE\_BATCH}\StringTok{"}
-\KeywordTok{\}}
-
-\FunctionTok{start\_step\_interactive()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{step\_name=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \ExtensionTok{start\_step} \StringTok{"}\VariableTok{$step\_name}\StringTok{"} \StringTok{"}\VariableTok{$STEP\_TYPE\_INTERACTIVE}\StringTok{"}
-\KeywordTok{\}}
-
-\FunctionTok{warning()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{message=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-
-    \ExtensionTok{echo\_err}
-    \ExtensionTok{echo\_err} \StringTok{"Warning: }\VariableTok{$message}\StringTok{"}
-
-    \BuiltInTok{local} \VariableTok{pressed\_key}
-    \KeywordTok{while} \FunctionTok{true}\KeywordTok{;} \KeywordTok{do}
-        \ExtensionTok{echo\_err}
-        \ExtensionTok{echo\_err} \StringTok{"Continue? (y/n) "}
-
-        \BuiltInTok{read}\NormalTok{ {-}n 1 {-}s {-}r }\VariableTok{pressed\_key}
-        \KeywordTok{case} \StringTok{"}\VariableTok{$pressed\_key}\StringTok{"}\KeywordTok{ in}
-\NormalTok{        [yY]}\KeywordTok{)}
-            \ExtensionTok{echo\_err} \StringTok{"Continuing..."}
-            \BuiltInTok{return}\NormalTok{ 0}
-            \KeywordTok{;;}
-\NormalTok{        [nN]}\KeywordTok{)}
-            \ExtensionTok{echo\_err} \StringTok{"Aborting..."}
-            \BuiltInTok{exit}\NormalTok{ 1}
-            \KeywordTok{;;}
-\NormalTok{        *}\KeywordTok{)}
-            \ExtensionTok{echo\_err} \StringTok{"Invalid key \textquotesingle{}}\VariableTok{$pressed\_key}\StringTok{\textquotesingle{}"}
-            \KeywordTok{;;}
-        \KeywordTok{esac}
-    \KeywordTok{done}
-\KeywordTok{\}}
-
-\FunctionTok{validation\_error()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{validation\_error\_message=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{fatal\_error\_message=}\StringTok{"}\VariableTok{$3}\StringTok{"}
-    \ExtensionTok{echo\_err} \StringTok{"Validation error: value \textquotesingle{}}\VariableTok{$value}\StringTok{\textquotesingle{} }\VariableTok{$validation\_error\_message}\StringTok{."}
-    \ExtensionTok{fatal\_error} \StringTok{"}\VariableTok{$fatal\_error\_message}\StringTok{"}
-\KeywordTok{\}}
-
-\FunctionTok{validate\_not\_empty()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{error\_message=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-
-    \KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$value}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{validation\_error} \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"is empty"} \StringTok{"}\VariableTok{$error\_message}\StringTok{"}
-    \KeywordTok{fi}
-\KeywordTok{\}}
-
-\FunctionTok{validate\_with\_regex()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{regex\_pattern=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{fatal\_error\_message=}\StringTok{"}\VariableTok{$3}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{validation\_error\_message=}\StringTok{"}\VariableTok{$\{4:{-}}\StringTok{"does not match regex pattern \textquotesingle{}}\VariableTok{$regex\_pattern}\StringTok{\textquotesingle{}"}\VariableTok{\}}\StringTok{"}
-
-    \KeywordTok{if [[} \OtherTok{!} \StringTok{"}\VariableTok{$value}\StringTok{"}\NormalTok{ =\textasciitilde{} }\VariableTok{$regex\_pattern}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{validation\_error} \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"}\VariableTok{$validation\_error\_message}\StringTok{"} \StringTok{"}\VariableTok{$fatal\_error\_message}\StringTok{"}
-    \KeywordTok{fi}
-\KeywordTok{\}}
-
-\FunctionTok{validate\_uint()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{error\_message=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{regex\_pattern=}\StringTok{\textquotesingle{}\^{}[0{-}9]+$\textquotesingle{}}
-
-    \ExtensionTok{validate\_with\_regex} \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"}\VariableTok{$regex\_pattern}\StringTok{"} \StringTok{"}\VariableTok{$error\_message}\StringTok{"} \StringTok{"is not a positive integer"}
-\KeywordTok{\}}
-
-\FunctionTok{validate\_nonzero\_uint()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{error\_message=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-
-    \ExtensionTok{validate\_uint} \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"}\VariableTok{$error\_message}\StringTok{"}
-
-    \KeywordTok{if [[} \StringTok{"}\VariableTok{$value}\StringTok{"} \OtherTok{{-}le}\NormalTok{ 0}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{validation\_error} \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"is not bigger than zero"} \StringTok{"}\VariableTok{$error\_message}\StringTok{"}
-    \KeywordTok{fi}
-\KeywordTok{\}}
-
-\FunctionTok{validate\_file\_exists()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{error\_message=}\StringTok{"}\VariableTok{$\{2:{-}}\NormalTok{File does not exist}\VariableTok{\}}\StringTok{"}
-
-    \KeywordTok{if [[} \OtherTok{!} \OtherTok{{-}f} \StringTok{"}\VariableTok{$value}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{validation\_error} \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"is not the path of an existing regular file"} \StringTok{"}\VariableTok{$error\_message}\StringTok{"}
-    \KeywordTok{fi}
-\KeywordTok{\}}
-
-\CommentTok{\# Validates that the given file exists but do not test if it\textquotesingle{}s a regular file}
-\CommentTok{\# like \textasciigrave{}validate\_file\_exists\textasciigrave{}.}
-\FunctionTok{validate\_exists()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{error\_message=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-
-    \KeywordTok{if [[} \OtherTok{!} \OtherTok{{-}e} \StringTok{"}\VariableTok{$value}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{validation\_error} \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"is not an existing path"} \StringTok{"}\VariableTok{$error\_message}\StringTok{"}
-    \KeywordTok{fi}
-\KeywordTok{\}}
-
-\CommentTok{\# Usage:}
-\CommentTok{\#   ensure\_variable VARIABLE\_NAME COMPUTATION\_FUNCTION VALIDATION\_FUNCTION}
-\CommentTok{\#}
-\CommentTok{\# Description:}
-\CommentTok{\#   Ensures that a readonly global variable named VARIABLE\_NAME is declared,}
-\CommentTok{\#   that it\textquotesingle{}s value is initialized using COMPUTATION\_FUNCTION and validated}
-\CommentTok{\#   using VALIDATION\_FUNCTION.}
-\CommentTok{\#}
-\CommentTok{\#   The value is computed, validated and set to a readonly global variable}
-\CommentTok{\#   during the first call to this function. Nothing more is done on}
-\CommentTok{\#   subsequent calls if the variable is already set.}
-\CommentTok{\#}
-\CommentTok{\#   If this function returns, the variable VARIABLE\_NAME should be safe to}
-\CommentTok{\#   use without any further validation. The variable can be accessed from}
-\CommentTok{\#   it\textquotesingle{}s name, or using an expression like \textasciigrave{}$\{!VARIABLE\_NAME\}\textasciigrave{}.}
-\CommentTok{\#}
-\CommentTok{\# Arguments:}
-\CommentTok{\#   VARIABLE\_NAME}
-\CommentTok{\#       The name of the variable to ensure.}
-\CommentTok{\#}
-\CommentTok{\#   COMPUTATION\_FUNCTION}
-\CommentTok{\#       A function that takes 0 arguments, writes the computed value to}
-\CommentTok{\#       standard output and returns 0 if the computation is successful.}
-\CommentTok{\#}
-\CommentTok{\#   VALIDATION\_FUNCTION}
-\CommentTok{\#       A function that takes the computed value and returns 0 if the value}
-\CommentTok{\#       is valid.}
-\CommentTok{\#}
-\CommentTok{\# Exit status code:}
-\CommentTok{\#   0  when no error is encountered. If any error is encountered during}
-\CommentTok{\#      declaration, computation, validation or assignation, the current shell}
-\CommentTok{\#      will be exited by a call to \textasciigrave{}fatal\_error\textasciigrave{} so the function will never}
-\CommentTok{\#      return.}
-\FunctionTok{ensure\_variable()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{variable\_name=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{computation\_function=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{validation\_function=}\StringTok{"}\VariableTok{$3}\StringTok{"}
-
-    \KeywordTok{if [[}\NormalTok{ {-}v }\StringTok{"}\VariableTok{$variable\_name}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{return}\NormalTok{ 0}
-    \KeywordTok{fi}
-
-    \BuiltInTok{local} \VariableTok{computed\_value} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"cannot declare local variable \textquotesingle{}computed\_value\textquotesingle{}"}
-
-    \VariableTok{computed\_value=}\StringTok{"}\VariableTok{$(}\StringTok{"}\VariableTok{$computation\_function}\StringTok{"}\VariableTok{)}\StringTok{"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"cannot compute value of \textquotesingle{}}\VariableTok{$variable\_name}\StringTok{\textquotesingle{} with \textquotesingle{}}\VariableTok{$computation\_function}\StringTok{\textquotesingle{}"}
-
-    \StringTok{"}\VariableTok{$validation\_function}\StringTok{"} \StringTok{"}\VariableTok{$computed\_value}\StringTok{"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"cannot validate value of \textquotesingle{}}\VariableTok{$variable\_name}\StringTok{\textquotesingle{} with \textquotesingle{}}\VariableTok{$validation\_function}\StringTok{\textquotesingle{}"}
-
-    \BuiltInTok{declare}\NormalTok{ {-}g {-}r }\StringTok{"}\VariableTok{$variable\_name}\StringTok{"}\VariableTok{=}\StringTok{"}\VariableTok{$computed\_value}\StringTok{"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"cannot initialize global readonly variable \textquotesingle{}}\VariableTok{$variable\_name}\StringTok{\textquotesingle{} with value \textquotesingle{}}\VariableTok{$computed\_value}\StringTok{\textquotesingle{}"}
-
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{log\_variable\_name=}\StringTok{"}\VariableTok{$(}\BuiltInTok{echo} \StringTok{"}\VariableTok{$\{variable\_name\^{}\}}\StringTok{"} \KeywordTok{|} \FunctionTok{tr} \StringTok{\textquotesingle{}\_\textquotesingle{}} \StringTok{\textquotesingle{} \textquotesingle{}}\VariableTok{)}\StringTok{"}
-    \ExtensionTok{echo\_err} \StringTok{"}\VariableTok{$log\_variable\_name}\StringTok{: }\VariableTok{$\{!variable\_name\}}\StringTok{"}
-
-    \BuiltInTok{return}\NormalTok{ 0}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $remote\_address is declared, initialized and valid.}
-\FunctionTok{ensure\_remote\_address()} \KeywordTok{\{}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{remote\_address}
-
-    \FunctionTok{get\_remote\_address()} \KeywordTok{\{}
-        \FunctionTok{mount}\NormalTok{ {-}t nfs }\KeywordTok{|} \FunctionTok{cut}\NormalTok{ {-}d}\StringTok{\textquotesingle{}:\textquotesingle{}}\NormalTok{ {-}f1 }\KeywordTok{|} \FunctionTok{head}\NormalTok{ {-}1 }\KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot retrieve remote server address."}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_remote\_address()} \KeywordTok{\{}
-        \ExtensionTok{validate\_not\_empty} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"no valid remote server address has not been found."}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"remote\_address"} \StringTok{"get\_remote\_address"} \StringTok{"validate\_remote\_address"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $net\_interface is declared, initialized and valid.}
-\FunctionTok{ensure\_net\_interface()} \KeywordTok{\{}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{net\_interface}
-
-    \ExtensionTok{ensure\_remote\_address}
-
-    \FunctionTok{get\_net\_interface()} \KeywordTok{\{}
-        \ExtensionTok{ip}\NormalTok{ route get }\StringTok{"}\VariableTok{$remote\_address}\StringTok{"} \KeywordTok{|} \FunctionTok{head}\NormalTok{ {-}1 }\KeywordTok{|} \FunctionTok{sed}\NormalTok{ {-}n }\StringTok{\textquotesingle{}s/.* dev \textbackslash{}([\^{} ]*\textbackslash{}).*/\textbackslash{}1/p\textquotesingle{}} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot retrieve network interface with route to \textquotesingle{}}\VariableTok{$remote\_address}\StringTok{\textquotesingle{}."}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_net\_interface()} \KeywordTok{\{}
-        \ExtensionTok{validate\_not\_empty} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"no valid network interface has been found."}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"net\_interface"} \StringTok{"get\_net\_interface"} \StringTok{"validate\_net\_interface"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $mac\_address is declared, initialized and valid.}
-\FunctionTok{ensure\_mac\_address()} \KeywordTok{\{}
-    \CommentTok{\# shellcheck disable=SC2034 \# the variable is declared for parent scripts that source this one}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{mac\_address}
-
-    \ExtensionTok{ensure\_net\_interface}
-
-    \FunctionTok{get\_mac\_address()} \KeywordTok{\{}
-        \FunctionTok{tr} \StringTok{"[:upper:]:"} \StringTok{"[:lower:]{-}"} \OperatorTok{\textless{}} \StringTok{"/sys/class/net/}\VariableTok{$net\_interface}\StringTok{/address"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"failed to retrieve and convert mac address of network interface \textquotesingle{}}\VariableTok{$net\_interface}\StringTok{\textquotesingle{}"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_mac\_address()} \KeywordTok{\{}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{value=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{regex\_pattern=}\StringTok{\textquotesingle{}\^{}([0{-}9a{-}f]\{2\}{-})\{5\}[0{-}9a{-}f]\{2\}$\textquotesingle{}}
-
-        \ExtensionTok{validate\_with\_regex} \KeywordTok{\textbackslash{}}
-            \StringTok{"}\VariableTok{$value}\StringTok{"} \StringTok{"}\VariableTok{$regex\_pattern}\StringTok{"} \KeywordTok{\textbackslash{}}
-            \StringTok{"mac address does not match required format."} \KeywordTok{\textbackslash{}}
-            \StringTok{"is not a mac address formatted as lower{-}case hexadecimal bytes separated by hyphens."}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"mac\_address"} \StringTok{"get\_mac\_address"} \StringTok{"validate\_mac\_address"}
-\KeywordTok{\}}
-
-\BuiltInTok{readonly} \VariableTok{mounting\_point\_remote=}\StringTok{"/bootiful/shared"}
-\BuiltInTok{readonly} \VariableTok{deployment\_disk=}\StringTok{"/dev/sda"}
-
-\CommentTok{\# Ensures the kernel is informed of the latest partition table changes}
-\FunctionTok{refresh\_partition\_table()} \KeywordTok{\{}
-    \ExtensionTok{echo\_err} \StringTok{"Refreshing partition table on disk \textquotesingle{}}\VariableTok{$deployment\_disk}\StringTok{\textquotesingle{}..."}
-    \ExtensionTok{partprobe} \StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}
-\KeywordTok{\}}
-
-\CommentTok{\# Checks if something is currently mounted on the given mount point}
-\FunctionTok{is\_mounted()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{mount\_point=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-
-    \ExtensionTok{refresh\_partition\_table}
-    \ExtensionTok{findmnt}\NormalTok{ {-}{-}mountpoint }\StringTok{"}\VariableTok{$mount\_point}\StringTok{"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures that the given directory exists or create it. If the directory does}
-\CommentTok{\# not exist and cannot be created, \textasciigrave{}fatal\_error\textasciigrave{} is called.}
-\FunctionTok{ensure\_directory()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{directory=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-
-    \ExtensionTok{echo\_err} \StringTok{"Ensuring directory \textquotesingle{}}\VariableTok{$directory}\StringTok{\textquotesingle{} exists..."}
-    \KeywordTok{if [[} \OtherTok{{-}d} \StringTok{"}\VariableTok{$directory}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{echo\_err} \StringTok{"Directory \textquotesingle{}}\VariableTok{$directory}\StringTok{\textquotesingle{} already exists."}
-        \BuiltInTok{return}\NormalTok{ 0}
-    \KeywordTok{fi}
-
-    \ExtensionTok{echo\_err} \StringTok{"Directory \textquotesingle{}}\VariableTok{$directory}\StringTok{\textquotesingle{} does not exist. Attempting to create it..."}
-    \FunctionTok{mkdir}\NormalTok{ {-}p }\StringTok{"}\VariableTok{$directory}\StringTok{"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"Cannot create directory }\VariableTok{$directory}\StringTok{."}
-    \ExtensionTok{echo\_err} \StringTok{"Directory \textquotesingle{}}\VariableTok{$directory}\StringTok{\textquotesingle{} created."}
-\KeywordTok{\}}
-
-\CommentTok{\# Mounts a device to a mount point if it\textquotesingle{}s not already mounted}
-\FunctionTok{ensure\_mounted()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{source\_device=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{mount\_point=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{mount\_fstype=}\StringTok{"}\VariableTok{$3}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{mount\_options=}\StringTok{"}\VariableTok{$4}\StringTok{"}
-
-    \ExtensionTok{echo\_err} \StringTok{"Ensuring device \textquotesingle{}}\VariableTok{$source\_device}\StringTok{\textquotesingle{} is mounted on \textquotesingle{}}\VariableTok{$mount\_point}\StringTok{\textquotesingle{}..."}
-
-    \KeywordTok{if} \ExtensionTok{is\_mounted} \StringTok{"}\VariableTok{$mount\_point}\StringTok{"}\KeywordTok{;} \KeywordTok{then}
-        \ExtensionTok{echo\_err} \StringTok{"Mount point \textquotesingle{}}\VariableTok{$mount\_point}\StringTok{\textquotesingle{} is already mounted."}
-        \BuiltInTok{return}\NormalTok{ 0}
-    \KeywordTok{fi}
-
-    \ExtensionTok{echo\_err} \StringTok{"Nothing is mounted on mount point \textquotesingle{}}\VariableTok{$mount\_point}\StringTok{\textquotesingle{}."}
-
-    \ExtensionTok{ensure\_directory} \StringTok{"}\VariableTok{$mount\_point}\StringTok{"}
-
-    \ExtensionTok{echo\_err} \StringTok{"Attempting to mount \textquotesingle{}}\VariableTok{$source\_device}\StringTok{\textquotesingle{} on \textquotesingle{}}\VariableTok{$mount\_point}\StringTok{\textquotesingle{} as \textquotesingle{}}\VariableTok{$mount\_fstype}\StringTok{\textquotesingle{} with options \textquotesingle{}}\VariableTok{$mount\_options}\StringTok{\textquotesingle{}."}
-
-    \FunctionTok{mount}\NormalTok{ {-}t }\StringTok{"}\VariableTok{$mount\_fstype}\StringTok{"}\NormalTok{ {-}o }\StringTok{"}\VariableTok{$mount\_options}\StringTok{"} \StringTok{"}\VariableTok{$source\_device}\StringTok{"} \StringTok{"}\VariableTok{$mount\_point}\StringTok{"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"Failed to mount device \textquotesingle{}}\VariableTok{$source\_device}\StringTok{\textquotesingle{} on \textquotesingle{}}\VariableTok{$mount\_point}\StringTok{\textquotesingle{}"}\NormalTok{.}
-
-    \ExtensionTok{echo\_err} \StringTok{"Mount successful."}
-\KeywordTok{\}}
-
-\CommentTok{\# Mounts the remote shared data if it\textquotesingle{}s not already mounted}
-\FunctionTok{ensure\_remote\_shared\_mounted()} \KeywordTok{\{}
-    \ExtensionTok{ensure\_remote\_address}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{remote\_nfs\_share=}\StringTok{"}\VariableTok{$remote\_address}\StringTok{:/nfsshared"}
-    \ExtensionTok{ensure\_mounted} \StringTok{"}\VariableTok{$remote\_nfs\_share}\StringTok{"} \StringTok{"}\VariableTok{$mounting\_point\_remote}\StringTok{"} \StringTok{"nfs"} \StringTok{"nolock"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $total\_disk\_size is declared, initialized and valid.}
-\FunctionTok{ensure\_total\_disk\_size()} \KeywordTok{\{}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{total\_disk\_size}
-
-    \FunctionTok{get\_total\_disk\_size()} \KeywordTok{\{}
-        \ExtensionTok{parted}\NormalTok{ {-}{-}script }\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}\NormalTok{ unit B print }\KeywordTok{|}
-            \FunctionTok{sed}\NormalTok{ {-}En }\StringTok{\textquotesingle{}s\#\^{}Disk\textbackslash{}s*\textquotesingle{}"}\VariableTok{$deployment\_disk}\StringTok{"\textquotesingle{}:\textbackslash{}s*([0{-}9]+)B$\#\textbackslash{}1\#p\textquotesingle{}} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot retrieve total disk size"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_total\_disk\_size()} \KeywordTok{\{}
-        \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"retrieved disk size format is invalid."}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"total\_disk\_size"} \StringTok{"get\_total\_disk\_size"} \StringTok{"validate\_total\_disk\_size"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $sector\_sizes is declared, initialized and valid}
-\FunctionTok{ensure\_sector\_sizes()} \KeywordTok{\{}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{sector\_sizes}
-
-    \FunctionTok{get\_sector\_sizes()} \KeywordTok{\{}
-        \ExtensionTok{parted}\NormalTok{ {-}{-}script }\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}\NormalTok{ print }\KeywordTok{|}
-            \FunctionTok{sed}\NormalTok{ {-}En }\StringTok{\textquotesingle{}s\#\^{}Sector size \textbackslash{}(logical/physical\textbackslash{}):\textbackslash{}s*([0{-}9]+)B/([0{-}9]+)B$\#\textbackslash{}1\textbackslash{}t\textbackslash{}2\#p\textquotesingle{}} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot retrieve sector size"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_sector\_sizes()} \KeywordTok{\{}
-        \ExtensionTok{validate\_with\_regex} \KeywordTok{\textbackslash{}}
-            \StringTok{"}\VariableTok{$1}\StringTok{"} \KeywordTok{\textbackslash{}}
-            \StringTok{\textquotesingle{}\^{}[0{-}9]+\textbackslash{}s+[0{-}9]+$\textquotesingle{}} \KeywordTok{\textbackslash{}}
-            \StringTok{\textquotesingle{}retrieved sector sizes are invalid\textquotesingle{}} \KeywordTok{\textbackslash{}}
-            \StringTok{\textquotesingle{}does not contain two unsigned integers separated by spaces\textquotesingle{}}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"sector\_sizes"} \StringTok{"get\_sector\_sizes"} \StringTok{"validate\_sector\_sizes"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $logical\_sector\_size is declared, initialized and valid}
-\FunctionTok{ensure\_logical\_sector\_size()} \KeywordTok{\{}
-    \CommentTok{\# shellcheck disable=SC2034 \# the variable is declared for parent scripts that source this one}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{logical\_sector\_size}
-
-    \ExtensionTok{ensure\_sector\_sizes}
-
-    \FunctionTok{extract\_logical\_sector\_size()} \KeywordTok{\{}
-        \BuiltInTok{echo} \StringTok{"}\VariableTok{$sector\_sizes}\StringTok{"} \KeywordTok{|} \FunctionTok{cut}\NormalTok{ {-}f 1 }\KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot extract logical sector size from sector sizes"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_logical\_sector\_size()} \KeywordTok{\{}
-        \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"retrieved logical sector size is invalid"}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"logical\_sector\_size"} \StringTok{"extract\_logical\_sector\_size"} \StringTok{"validate\_logical\_sector\_size"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $physical\_sector\_size is declared, initialized and valid}
-\FunctionTok{ensure\_physical\_sector\_size()} \KeywordTok{\{}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{physical\_sector\_size}
-
-    \ExtensionTok{ensure\_sector\_sizes}
-
-    \FunctionTok{extract\_physical\_sector\_size()} \KeywordTok{\{}
-        \BuiltInTok{echo} \StringTok{"}\VariableTok{$sector\_sizes}\StringTok{"} \KeywordTok{|} \FunctionTok{cut}\NormalTok{ {-}f 2 }\KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot extract physical sector size from sector sizes"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_physical\_sector\_size()} \KeywordTok{\{}
-        \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"retrieved physical sector size is invalid"}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"physical\_sector\_size"} \StringTok{"extract\_physical\_sector\_size"} \StringTok{"validate\_physical\_sector\_size"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $image\_cache\_partition\_size is declared, initialized and valid}
-\FunctionTok{ensure\_image\_cache\_partition\_size()} \KeywordTok{\{}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{image\_cache\_partition\_size}
-
-    \ExtensionTok{ensure\_total\_disk\_size}
-    \ExtensionTok{ensure\_physical\_sector\_size}
-
-    \FunctionTok{calculate\_image\_cache\_partition\_size()} \KeywordTok{\{}
-        \BuiltInTok{echo} \StringTok{"}\VariableTok{$((}\NormalTok{(20 * total\_disk\_size / 100) / physical\_sector\_size * physical\_sector\_size}\VariableTok{))}\StringTok{"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot calculate image partition size"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_image\_cache\_partition\_size()} \KeywordTok{\{}
-        \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"calculated image cache partition size is invalid"}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"image\_cache\_partition\_size"} \KeywordTok{\textbackslash{}}
-        \StringTok{"calculate\_image\_cache\_partition\_size"} \KeywordTok{\textbackslash{}}
-        \StringTok{"validate\_image\_cache\_partition\_size"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $image\_cache\_partition\_start is declared, initialized and valid}
-\FunctionTok{ensure\_image\_cache\_partition\_start()} \KeywordTok{\{}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{image\_cache\_partition\_start}
-
-    \ExtensionTok{ensure\_total\_disk\_size}
-    \ExtensionTok{ensure\_physical\_sector\_size}
-    \ExtensionTok{ensure\_image\_cache\_partition\_size}
-
-    \FunctionTok{calculate\_image\_cache\_partition\_start()} \KeywordTok{\{}
-        \BuiltInTok{echo} \StringTok{"}\VariableTok{$((}\NormalTok{(total\_disk\_size {-} image\_cache\_partition\_size) / physical\_sector\_size * physical\_sector\_size {-} 4096}\VariableTok{))}\StringTok{"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot calculate image cache partition start"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_image\_cache\_partition\_start()} \KeywordTok{\{}
-        \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"calculated image cache partition start is invalid"}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"image\_cache\_partition\_start"} \KeywordTok{\textbackslash{}}
-        \StringTok{"calculate\_image\_cache\_partition\_start"} \KeywordTok{\textbackslash{}}
-        \StringTok{"validate\_image\_cache\_partition\_start"}
-\KeywordTok{\}}
-
-\CommentTok{\# Ensures $image\_cache\_partition\_end is declared, initialized and valid}
-\FunctionTok{ensure\_image\_cache\_partition\_end()} \KeywordTok{\{}
-    \CommentTok{\# shellcheck disable=SC2034 \# the variable is declared for parent scripts that source this one}
-    \BuiltInTok{declare}\NormalTok{ {-}g }\VariableTok{image\_cache\_partition\_end}
-
-    \ExtensionTok{ensure\_image\_cache\_partition\_size}
-    \ExtensionTok{ensure\_image\_cache\_partition\_start}
-
-    \FunctionTok{calculate\_image\_cache\_partition\_end()} \KeywordTok{\{}
-        \BuiltInTok{echo} \StringTok{"}\VariableTok{$((}\NormalTok{image\_cache\_partition\_start + image\_cache\_partition\_size}\VariableTok{))}\StringTok{"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"cannot calculate image cache partition end"}
-    \KeywordTok{\}}
-
-    \FunctionTok{validate\_image\_cache\_partition\_end()} \KeywordTok{\{}
-        \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"calculated image cache partition start is invalid"}
-    \KeywordTok{\}}
-
-    \ExtensionTok{ensure\_variable} \StringTok{"image\_cache\_partition\_end"} \KeywordTok{\textbackslash{}}
-        \StringTok{"calculate\_image\_cache\_partition\_end"} \KeywordTok{\textbackslash{}}
-        \StringTok{"validate\_image\_cache\_partition\_end"}
-\KeywordTok{\}}
-
-\FunctionTok{parse\_last\_partition\_end()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{gawk\_input\_data=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{input\_size\_unit=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{start\_parse\_token=}\StringTok{"}\VariableTok{$3}\StringTok{"}
-
-    \BuiltInTok{local} \VariableTok{gawk\_program}
-    \BuiltInTok{read}\NormalTok{ {-}r {-}d }\StringTok{\textquotesingle{}\textquotesingle{}} \VariableTok{gawk\_program} \OperatorTok{\textless{}\textless{} \textquotesingle{}EOF\textquotesingle{}}
-\NormalTok{        $0 \textasciitilde{} start\_parse\_regex\_pattern \{}
-\NormalTok{            parsing=1;}
-\NormalTok{            max\_part\_end=0;}
-\NormalTok{            next;}
-\NormalTok{        \}}
-\NormalTok{        parsing \&\& $3 \textasciitilde{} disk\_end\_regex\_pattern \{}
-\NormalTok{            part\_end=substr($3, 1, length($3){-}length(size\_unit)) + 0;}
-\NormalTok{            if(part\_end\textgreater{}max\_part\_end) \{}
-\NormalTok{                max\_part\_end=part\_end;}
-\NormalTok{            \}}
-\NormalTok{        \}}
-\NormalTok{        END \{}
-\NormalTok{            printf "\%d", max\_part\_end;}
-\NormalTok{        \}}
-\OperatorTok{EOF}
-
-    \BuiltInTok{echo} \StringTok{"}\VariableTok{$gawk\_input\_data}\StringTok{"} \KeywordTok{|} \FunctionTok{gawk} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}v}\NormalTok{ start\_parse\_regex\_pattern=}\StringTok{"\^{}}\VariableTok{$start\_parse\_token}\StringTok{"} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}v}\NormalTok{ disk\_end\_regex\_pattern=}\StringTok{"\^{}[0{-}9]+}\VariableTok{$input\_size\_unit}\StringTok{$"} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}v}\NormalTok{ size\_unit=}\StringTok{"}\VariableTok{$input\_size\_unit}\StringTok{"} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}M} \StringTok{"}\VariableTok{$gawk\_program}\StringTok{"} \KeywordTok{\textbackslash{}}
-        \KeywordTok{||} \ExtensionTok{fatal\_error} \StringTok{"cannot extract image size"}
-\KeywordTok{\}}
-
-\CommentTok{\# Print the end offset of the last partition of a parted output}
-\FunctionTok{parse\_parted\_last\_partition\_end()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{parted\_output=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{parted\_unit=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-
-    \ExtensionTok{parse\_last\_partition\_end} \StringTok{"}\VariableTok{$parted\_output}\StringTok{"} \StringTok{"}\VariableTok{$parted\_unit}\StringTok{"} \StringTok{\textquotesingle{}Number\textquotesingle{}}
-\KeywordTok{\}}
-
-\FunctionTok{parse\_parted\_last\_partition\_end\_sector()} \KeywordTok{\{}
-    \ExtensionTok{parse\_parted\_last\_partition\_end} \StringTok{"}\VariableTok{$1}\StringTok{"} \StringTok{"s"}
-\KeywordTok{\}}
-
-\FunctionTok{parse\_fdisk\_last\_partition\_end\_sector()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{fdisk\_output=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-
-    \ExtensionTok{parse\_last\_partition\_end} \StringTok{"}\VariableTok{$fdisk\_output}\StringTok{"} \StringTok{\textquotesingle{}\textquotesingle{}} \StringTok{\textquotesingle{}Device\textquotesingle{}}
-\KeywordTok{\}}
-
-\FunctionTok{create\_hidden\_partition()} \KeywordTok{\{}
-    \BuiltInTok{echo} \StringTok{"Erasing MBR..."}
-    \FunctionTok{dd}\NormalTok{ if=/dev/zero bs=512 count=1 of=}\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}
-    \BuiltInTok{echo} \StringTok{"MBR erased."}
-
-    \BuiltInTok{echo} \StringTok{"Creating new partition table with hidden partition..."}
-    \ExtensionTok{ensure\_image\_cache\_partition\_start}
-    \ExtensionTok{ensure\_image\_cache\_partition\_end}
-    \ExtensionTok{parted}\NormalTok{ {-}s {-}a opt }\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}\NormalTok{ mklabel msdos mkpart primary ext2 }\StringTok{"}\VariableTok{$\{image\_cache\_partition\_start\}}\StringTok{B"} \StringTok{"}\VariableTok{$\{image\_cache\_partition\_end\}}\StringTok{B"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"parted exited with error code }\VariableTok{$?}\StringTok{"}
-    \BuiltInTok{echo} \StringTok{"New partition table with hidden partition created."}
-
-    \ExtensionTok{refresh\_partition\_table}
-
-    \BuiltInTok{echo} \StringTok{"Creating file system in hidden partition..."}
-    \ExtensionTok{mke2fs}\NormalTok{ {-}t ext2 }\StringTok{"}\VariableTok{$\{deployment\_disk\}}\StringTok{1"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"mke2fs exited with error code }\VariableTok{$?}\StringTok{"}
-    \BuiltInTok{echo} \StringTok{"File system in hidden partition created."}
-
-    \ExtensionTok{refresh\_partition\_table}
-\KeywordTok{\}}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerbootiful-deploy-script-de-duxe9ploiement-dimages}{%
-\section{\texorpdfstring{\texttt{deployer/bootiful-deploy}: script de
-déploiement
-d'images}{deployer/bootiful-deploy: script de déploiement d'images}}\label{deployerbootiful-deploy-script-de-duxe9ploiement-dimages}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#!/bin/bash}
-
-\BuiltInTok{shopt}\NormalTok{ {-}s nullglob}
-
-\BuiltInTok{readonly} \VariableTok{SCRIPT\_NAME=}\StringTok{"}\VariableTok{$(}\FunctionTok{basename} \StringTok{"}\VariableTok{$0}\StringTok{"}\VariableTok{)}\StringTok{"}
-\BuiltInTok{readonly} \VariableTok{SCRIPT\_DIR=}\StringTok{"}\VariableTok{$(}\FunctionTok{readlink}\NormalTok{ {-}m }\StringTok{"}\VariableTok{$(}\FunctionTok{dirname} \StringTok{"}\VariableTok{$0}\StringTok{"}\VariableTok{)}\StringTok{"}\VariableTok{)}\StringTok{"}
-
-\FunctionTok{usage()} \KeywordTok{\{}
-    \FunctionTok{cat} \OperatorTok{\textless{}\textless{} EOF}
-\NormalTok{Usage:}
-  \VariableTok{$SCRIPT\_DIR}\NormalTok{ [{-}h | {-}{-}help]}
-
-\NormalTok{Description:}
-\NormalTok{  Deploys an operating system image on the disk.}
-
-\NormalTok{  The image is retrieved from the NFS server that already provides the root file}
-\NormalTok{  system. The NFS shared directory /nfsshared is mounted on /bootiful/shared and}
-\NormalTok{  contains multiple images that can be deployed.}
-
-\NormalTok{  The available images from the server are scanned from /bootiful/shared/images}
-\NormalTok{  and displayed in an interactive menu that allows to choose which particular}
-\NormalTok{  image will be deployed.}
-
-\NormalTok{  All the data written in the standard input and standard error during the}
-\NormalTok{  deployment is also written in a log file in /bootiful/shared/logs.}
-
-\NormalTok{  If there is enough disk space available, the image is cached in a hidden}
-\NormalTok{  partition to avoid downloading it again over the network during a future}
-\NormalTok{  deployment. This hidden partition takes 20\% of the disk.}
-
-\NormalTok{  If the image to deploy overlaps the image cache partition (i.e. the image}
-\NormalTok{  takes more than 80\% of the disk size), a warning message is shown and an}
-\NormalTok{  interactive menu allows to choose whether to abort or continue the deployment}
-\NormalTok{  without using the cache.}
-
-\NormalTok{Options:}
-\NormalTok{  {-}h, {-}{-}help  Shows this help}
-
-\NormalTok{Exit status:}
-\NormalTok{  0  if an image has been deployed successfully}
-\NormalTok{  1  if some error has occured during deployment}
-
-\NormalTok{Example:}
-  \VariableTok{$SCRIPT\_NAME}
-\OperatorTok{EOF}
-\KeywordTok{\}}
-
-\KeywordTok{if [[} \StringTok{"}\VariableTok{$1}\StringTok{"} \OtherTok{==} \StringTok{"{-}h"}\NormalTok{ || }\StringTok{"}\VariableTok{$1}\StringTok{"} \OtherTok{==} \StringTok{"{-}{-}help"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \ExtensionTok{usage}
-    \BuiltInTok{exit}\NormalTok{ 0}
-\KeywordTok{fi}
-
-\CommentTok{\# Loads declarations from the \textquotesingle{}bootiful{-}common\textquotesingle{} script, which is a "library"}
-\CommentTok{\# of functions and constants shared by multiple bootiful{-}* scripts.}
-\BuiltInTok{readonly} \VariableTok{bootiful\_common\_script\_file=}\StringTok{"}\VariableTok{$SCRIPT\_DIR}\StringTok{/bootiful{-}common"}
-\KeywordTok{if [[} \OtherTok{!} \OtherTok{{-}f} \StringTok{"}\VariableTok{$bootiful\_common\_script\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \BuiltInTok{echo} \OperatorTok{\textgreater{}\&2} \StringTok{"Fatal error: cannot find required script file \textquotesingle{}}\VariableTok{$bootiful\_common\_script\_file}\StringTok{\textquotesingle{}."}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-\CommentTok{\# shellcheck source=./bootiful{-}common}
-\BuiltInTok{.} \StringTok{"}\VariableTok{$SCRIPT\_DIR}\StringTok{/bootiful{-}common"}
-
-\ExtensionTok{start\_step\_batch} \StringTok{"remote shared data mount initialization"}
-\VariableTok{start\_timestamp=}\StringTok{"}\VariableTok{$\{step\_timestamps[0]\}}\StringTok{"}
-
-\ExtensionTok{ensure\_remote\_shared\_mounted}
-
-\ExtensionTok{start\_step\_batch} \StringTok{"log file initialization"}
-\BuiltInTok{readonly} \VariableTok{log\_dir=}\StringTok{"}\VariableTok{$mounting\_point\_remote}\StringTok{/log"}
-
-\ExtensionTok{ensure\_mac\_address}
-\ExtensionTok{ensure\_directory} \StringTok{"}\VariableTok{$log\_dir}\StringTok{"}
-\BuiltInTok{readonly} \VariableTok{logfile\_date=$(}\FunctionTok{date}\NormalTok{ {-}{-}date }\StringTok{"}\VariableTok{$start\_timestamp}\StringTok{"}\NormalTok{ {-}{-}universal +\%Y{-}\%m{-}\%d\_\%H{-}\%M{-}\%S}\VariableTok{)}
-\BuiltInTok{readonly} \VariableTok{log\_file\_prefix=}\StringTok{"}\VariableTok{$log\_dir}\StringTok{/}\VariableTok{$\{mac\_address\}}\StringTok{\_}\VariableTok{$logfile\_date}\StringTok{"}
-
-\BuiltInTok{readonly} \VariableTok{log\_file=}\StringTok{"}\VariableTok{$log\_file\_prefix}\StringTok{.log"}
-\BuiltInTok{echo} \StringTok{"Starting logging stdout and stderr to }\VariableTok{$log\_file}\StringTok{..."}
-
-\KeywordTok{\{}
-    \ExtensionTok{start\_step\_batch} \StringTok{"hardware log files creation"}
-
-    \FunctionTok{log\_command\_to\_file()} \KeywordTok{\{}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{prefix=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{extension=}\StringTok{"}\VariableTok{$2}\StringTok{"}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{command=}\StringTok{"}\VariableTok{$3}\StringTok{"}
-
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{hardware\_log\_file=}\StringTok{"}\VariableTok{$prefix}\StringTok{.}\VariableTok{$extension}\StringTok{"}
-
-        \BuiltInTok{echo} \StringTok{"Writing }\VariableTok{$extension}\StringTok{ log file }\VariableTok{$hardware\_log\_file}\StringTok{..."}
-
-        \CommentTok{\# shellcheck disable=SC2086 \# we need to expand args}
-        \FunctionTok{bash}\NormalTok{ {-}c }\StringTok{"}\VariableTok{$command}\StringTok{"} \OperatorTok{\textgreater{}} \StringTok{"}\VariableTok{$hardware\_log\_file}\StringTok{"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"Cannot write }\VariableTok{$extension}\StringTok{ log file }\VariableTok{$hardware\_log\_file}\StringTok{."}
-
-        \BuiltInTok{echo} \StringTok{"Wrote }\VariableTok{$extension}\StringTok{ log file }\VariableTok{$hardware\_log\_file}\StringTok{."}
-    \KeywordTok{\}}
-
-    \ExtensionTok{log\_command\_to\_file} \StringTok{"}\VariableTok{$log\_file\_prefix}\StringTok{"}\NormalTok{ cpuinfo }\StringTok{\textquotesingle{}cat /proc/cpuinfo\textquotesingle{}}
-    \ExtensionTok{log\_command\_to\_file} \StringTok{"}\VariableTok{$log\_file\_prefix}\StringTok{"}\NormalTok{ meminfo }\StringTok{\textquotesingle{}cat /proc/meminfo\textquotesingle{}}
-    \ExtensionTok{log\_command\_to\_file} \StringTok{"}\VariableTok{$log\_file\_prefix}\StringTok{"}\NormalTok{ parted }\StringTok{\textquotesingle{}parted {-}{-}script {-}{-}list\textquotesingle{}}
-
-    \ExtensionTok{start\_step\_batch} \StringTok{"remote images search"}
-
-    \VariableTok{remote\_images\_dir=}\StringTok{"}\VariableTok{$mounting\_point\_remote}\StringTok{/images"}
-
-    \BuiltInTok{echo} \StringTok{"Finding remote images..."}
-    \BuiltInTok{declare} \VariableTok{count=}\NormalTok{0}
-    \BuiltInTok{declare}\NormalTok{ {-}A }\VariableTok{images}
-    \BuiltInTok{declare} \VariableTok{found\_image\_name}
-    \KeywordTok{for} \ExtensionTok{image\_folder}\NormalTok{ in }\StringTok{"}\VariableTok{$remote\_images\_dir}\StringTok{"}\NormalTok{/*}\KeywordTok{;} \KeywordTok{do}
-        \VariableTok{found\_image\_name=$(}\FunctionTok{basename} \StringTok{"}\VariableTok{$image\_folder}\StringTok{"}\VariableTok{)}
-        \BuiltInTok{echo} \StringTok{"Image \textquotesingle{}}\VariableTok{$found\_image\_name}\StringTok{\textquotesingle{} found"}
-        \VariableTok{options=(}\StringTok{"}\VariableTok{$\{options[]\}}\StringTok{"} \StringTok{"}\VariableTok{$((}\NormalTok{++count}\VariableTok{))}\StringTok{"} \StringTok{"}\VariableTok{$found\_image\_name}\StringTok{"}\VariableTok{)}
-        \VariableTok{images[$count]=}\StringTok{"}\VariableTok{$found\_image\_name}\StringTok{"}
-    \KeywordTok{done}
-    \BuiltInTok{echo} \StringTok{"}\VariableTok{$count}\StringTok{ remote images found."}
-
-    \KeywordTok{if [[} \VariableTok{$count} \OtherTok{{-}eq}\NormalTok{ 0}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{fatal\_error} \StringTok{"No image found in remote images directory }\VariableTok{$remote\_images\_dir}\StringTok{"}
-    \KeywordTok{fi}
-
-    \ExtensionTok{start\_step\_interactive} \StringTok{"image selection"}
-
-    \BuiltInTok{declare} \VariableTok{tty}
-    \VariableTok{tty=$(}\ExtensionTok{tty}\VariableTok{)}
-    \BuiltInTok{readonly} \VariableTok{tty}
-
-    \BuiltInTok{declare} \VariableTok{choice}
-    \VariableTok{choice=$(}\ExtensionTok{dialog} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}{-}clear} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}{-}title} \StringTok{"Image selection"} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}{-}menu} \StringTok{"Select an image to deploy"} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{0}\NormalTok{ 0 0 }\KeywordTok{\textbackslash{}}
-        \StringTok{"}\VariableTok{$\{options[]\}}\StringTok{"} \KeywordTok{\textbackslash{}}
-        \OperatorTok{2\textgreater{}\&1} \OperatorTok{\textgreater{}} \StringTok{"}\VariableTok{$tty}\StringTok{"}\VariableTok{)}
-    \BuiltInTok{readonly} \VariableTok{choice}
-
-    \ExtensionTok{validate\_not\_empty} \StringTok{"}\VariableTok{$choice}\StringTok{"} \StringTok{"No image has been chosen"}
-
-    \BuiltInTok{readonly} \VariableTok{image\_name=$\{images[$choice]\}}
-
-    \BuiltInTok{echo} \StringTok{"Chosen image is }\VariableTok{$image\_name}\StringTok{"}
-
-    \BuiltInTok{readonly} \VariableTok{remote\_image\_dir=}\StringTok{"}\VariableTok{$remote\_images\_dir}\StringTok{/}\VariableTok{$image\_name}\StringTok{"}
-    \BuiltInTok{readonly} \VariableTok{remote\_image\_gzip\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/}\VariableTok{$image\_name}\StringTok{.img.gz"}
-    \BuiltInTok{readonly} \VariableTok{remote\_image\_clonezilla\_id\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/Info{-}img{-}id.txt"}
-
-    \BuiltInTok{readonly} \VariableTok{IMAGE\_TYPE\_RAW=}\StringTok{"raw"}
-    \BuiltInTok{readonly} \VariableTok{IMAGE\_TYPE\_CLONEZILLA=}\StringTok{"clonezilla"}
-
-    \KeywordTok{if [[} \OtherTok{{-}f} \StringTok{"}\VariableTok{$remote\_image\_gzip\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{readonly} \VariableTok{image\_type=}\StringTok{"}\VariableTok{$IMAGE\_TYPE\_RAW}\StringTok{"}
-        \BuiltInTok{readonly} \VariableTok{remote\_image\_md5\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/}\VariableTok{$image\_name}\StringTok{.md5"}
-        \BuiltInTok{readonly} \VariableTok{remote\_image\_size\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/}\VariableTok{$image\_name}\StringTok{.partition"}
-        \BuiltInTok{readonly} \VariableTok{parse\_end\_sector\_function=}\NormalTok{parse\_fdisk\_last\_partition\_end\_sector}
-    \KeywordTok{elif [[} \OtherTok{{-}f} \StringTok{"}\VariableTok{$remote\_image\_clonezilla\_id\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{readonly} \VariableTok{image\_type=}\StringTok{"}\VariableTok{$IMAGE\_TYPE\_CLONEZILLA}\StringTok{"}
-        \BuiltInTok{readonly} \VariableTok{remote\_image\_size\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/sda{-}pt.parted"}
-        \BuiltInTok{readonly} \VariableTok{parse\_end\_sector\_function=}\NormalTok{parse\_parted\_last\_partition\_end\_sector}
-    \KeywordTok{else}
-        \ExtensionTok{fatal\_error} \StringTok{"Cannot find type of image \textquotesingle{}}\VariableTok{$image\_name}\StringTok{\textquotesingle{} in \textquotesingle{}}\VariableTok{$remote\_image\_dir}\StringTok{\textquotesingle{}"}
-    \KeywordTok{fi}
-
-    \ExtensionTok{start\_step\_batch} \StringTok{"image size verification"}
-
-    \ExtensionTok{validate\_file\_exists} \KeywordTok{\textbackslash{}}
-        \StringTok{"}\VariableTok{$remote\_image\_size\_file}\StringTok{"} \KeywordTok{\textbackslash{}}
-        \StringTok{"cannot retrieve size of image because parted/fdisk dump file does not exist."}
-
-    \BuiltInTok{readonly} \VariableTok{remote\_image\_size\_file\_content=}\StringTok{"}\OperatorTok{$(\textless{}} \StringTok{"}\VariableTok{$remote\_image\_size\_file}\StringTok{"}\OperatorTok{)}\StringTok{"} \KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"Cannot read parted/fdisk dump file \textquotesingle{}}\VariableTok{$remote\_image\_size\_file}\StringTok{\textquotesingle{}"}
-
-    \BuiltInTok{declare} \VariableTok{image\_end\_sector}
-    \VariableTok{image\_end\_sector=$(}\StringTok{"}\VariableTok{$parse\_end\_sector\_function}\StringTok{"} \StringTok{"}\VariableTok{$remote\_image\_size\_file\_content}\StringTok{"}\VariableTok{)}
-    \BuiltInTok{readonly} \VariableTok{image\_end\_sector}
-    \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$image\_end\_sector}\StringTok{"} \StringTok{"Invalid image end sector"}
-
-    \ExtensionTok{ensure\_logical\_sector\_size}
-    \KeywordTok{((}\NormalTok{image\_size = image\_end\_sector * logical\_sector\_size}\KeywordTok{))}
-    \ExtensionTok{validate\_nonzero\_uint} \StringTok{"}\VariableTok{$image\_size}\StringTok{"} \StringTok{"Retrieved image size is invalid"}
-
-    \BuiltInTok{echo} \StringTok{"Image type: }\VariableTok{$image\_type}\StringTok{"}
-    \BuiltInTok{echo} \StringTok{"Image size: }\VariableTok{$image\_size}\StringTok{ B"}
-
-    \ExtensionTok{ensure\_total\_disk\_size}
-    \BuiltInTok{echo} \StringTok{"Available space in disk without image cache partition: }\VariableTok{$total\_disk\_size}\StringTok{ B"}
-    \ExtensionTok{ensure\_image\_cache\_partition\_size}
-    \BuiltInTok{echo} \StringTok{"Available space before image cache partition partition: }\VariableTok{$image\_cache\_partition\_size}\StringTok{ B"}
-
-    \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_size}\StringTok{"} \OtherTok{{-}gt} \StringTok{"}\VariableTok{$total\_disk\_size}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{fatal\_error} \StringTok{"Insufficient disk space for imaging. Image size: }\VariableTok{$image\_size}\StringTok{ B Disk size: }\VariableTok{$total\_disk\_size}\StringTok{ B"}
-    \KeywordTok{fi}
-
-    \VariableTok{mounting\_point\_hidden=}\StringTok{"/mnt"}
-    \VariableTok{DEPLOY\_MODE\_ALREADY\_CACHED=}\StringTok{\textquotesingle{}cached\textquotesingle{}}
-    \VariableTok{DEPLOY\_MODE\_CACHED\_NOW=}\StringTok{\textquotesingle{}cached\_now\textquotesingle{}}
-    \VariableTok{DEPLOY\_MODE\_NOT\_CACHED=}\StringTok{\textquotesingle{}not\_cached\textquotesingle{}}
-
-    \ExtensionTok{ensure\_image\_cache\_partition\_start}
-    \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_size}\StringTok{"} \OtherTok{{-}gt} \StringTok{"}\VariableTok{$image\_cache\_partition\_start}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \ExtensionTok{start\_step\_interactive} \StringTok{"hidden partition destruction confirmation"}
-
-        \ExtensionTok{warning} \StringTok{"Image overlaps with local image cache."} \KeywordTok{\textbackslash{}}
-            \StringTok{"It can be deployed from network but the image cache will be destroyed."} \KeywordTok{\textbackslash{}}
-            \StringTok{"Continue?"}
-
-        \BuiltInTok{echo} \StringTok{"Sufficient disk space for imaging, but image cache partition will be destroyed if it exists."}
-        \VariableTok{deploy\_mode=}\StringTok{"}\VariableTok{$DEPLOY\_MODE\_NOT\_CACHED}\StringTok{"}
-    \KeywordTok{else}
-        \BuiltInTok{echo} \StringTok{"Sufficient disk space for imaging with cache. Image cache partition will be restored or created."}
-
-        \BuiltInTok{readonly} \VariableTok{hidden\_partition\_dev=}\StringTok{"/dev/loop0"}
-
-        \BuiltInTok{readonly} \VariableTok{HIDDEN\_PARTITION\_STATUS\_UNKNOWN=}\StringTok{\textquotesingle{}unknown\textquotesingle{}}
-        \BuiltInTok{readonly} \VariableTok{HIDDEN\_PARTITION\_STATUS\_CREATED=}\StringTok{\textquotesingle{}created\textquotesingle{}}
-        \BuiltInTok{readonly} \VariableTok{HIDDEN\_PARTITION\_STATUS\_RESTORED=}\StringTok{\textquotesingle{}restored\textquotesingle{}}
-        \BuiltInTok{declare} \VariableTok{hidden\_partition\_status=}\StringTok{"}\VariableTok{$HIDDEN\_PARTITION\_STATUS\_UNKNOWN}\StringTok{"}
-
-        \CommentTok{\# Mounts the hidden partition.}
-        \CommentTok{\# If there is a mount error and the partition was restored, the partition will be}
-        \CommentTok{\# recreated and there will be another tentative to mount it.}
-        \FunctionTok{mount\_hidden\_partition()} \KeywordTok{\{}
-            \ExtensionTok{start\_step\_batch} \StringTok{"image cache partition mount tentative"}
-
-            \BuiltInTok{echo} \StringTok{"Creating loopback node for }\VariableTok{$deployment\_disk}\StringTok{ (offset=}\VariableTok{$image\_cache\_partition\_start}\StringTok{) on }\VariableTok{$hidden\_partition\_dev}\StringTok{"}
-
-            \ExtensionTok{losetup}\NormalTok{ {-}o }\StringTok{"}\VariableTok{$image\_cache\_partition\_start}\StringTok{"} \StringTok{"}\VariableTok{$hidden\_partition\_dev}\StringTok{"} \StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"} \KeywordTok{||}
-                \ExtensionTok{fatal\_error} \StringTok{"Failed to create loopback node for }\VariableTok{$deployment\_disk}\StringTok{ on }\VariableTok{$hidden\_partition\_dev}\StringTok{"}
-            \BuiltInTok{echo} \StringTok{"Created loopback node for }\VariableTok{$deployment\_disk}\StringTok{ on }\VariableTok{$hidden\_partition\_dev}\StringTok{"}
-
-            \BuiltInTok{echo} \StringTok{"Mounting hidden partition from }\VariableTok{$hidden\_partition\_dev}\StringTok{ on }\VariableTok{$mounting\_point\_hidden}\StringTok{..."}
-            \KeywordTok{if}\NormalTok{ ! }\FunctionTok{mount}\NormalTok{ {-}t ext2 }\StringTok{"}\VariableTok{$hidden\_partition\_dev}\StringTok{"} \StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{"}\KeywordTok{;} \KeywordTok{then}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{error\_message=}\StringTok{"Cannot mount }\VariableTok{$hidden\_partition\_status}\StringTok{ hidden partition from }\VariableTok{$hidden\_partition\_dev}\StringTok{ on }\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-
-                \KeywordTok{if [[} \StringTok{"}\VariableTok{$hidden\_partition\_status}\StringTok{"} \OtherTok{!=} \StringTok{"}\VariableTok{$HIDDEN\_PARTITION\_STATUS\_CREATED}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                    \BuiltInTok{echo} \StringTok{"}\VariableTok{$error\_message}\StringTok{"}
-
-                    \ExtensionTok{losetup}\NormalTok{ {-}d }\StringTok{"}\VariableTok{$hidden\_partition\_dev}\StringTok{"} \KeywordTok{||}
-                        \ExtensionTok{fatal\_error} \StringTok{"Cannot detach loopback device }\VariableTok{$hidden\_partition\_dev}\StringTok{"}
-
-                    \ExtensionTok{start\_step\_batch} \StringTok{"image cache partition creation"}
-                    \ExtensionTok{create\_hidden\_partition}
-                    \ExtensionTok{mount\_hidden\_partition}
-                    \VariableTok{hidden\_partition\_status=}\StringTok{"}\VariableTok{$HIDDEN\_PARTITION\_STATUS\_CREATED}\StringTok{"}
-                \KeywordTok{else}
-                    \ExtensionTok{fatal\_error} \StringTok{"}\VariableTok{$error\_message}\StringTok{"}
-                \KeywordTok{fi}
-            \KeywordTok{fi}
-
-            \KeywordTok{if [[} \StringTok{"}\VariableTok{$hidden\_partition\_status}\StringTok{"} \OtherTok{!=} \StringTok{"}\VariableTok{$HIDDEN\_PARTITION\_STATUS\_CREATED}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \VariableTok{hidden\_partition\_status=}\StringTok{"}\VariableTok{$HIDDEN\_PARTITION\_STATUS\_RESTORED}\StringTok{"}
-            \KeywordTok{fi}
-
-            \BuiltInTok{echo} \StringTok{"Hidden partition mounted on }\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-        \KeywordTok{\}}
-
-        \ExtensionTok{mount\_hidden\_partition}
-
-        \FunctionTok{read\_raw\_image\_id\_file()} \KeywordTok{\{}
-            \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{image\_id\_file=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-            \FunctionTok{head}\NormalTok{ {-}n 1 }\StringTok{"}\VariableTok{$image\_id\_file}\StringTok{"} \KeywordTok{|} \FunctionTok{cut}\NormalTok{ {-}d }\StringTok{" "}\NormalTok{ {-}f 1}
-        \KeywordTok{\}}
-
-        \FunctionTok{read\_clonezilla\_image\_id\_file()} \KeywordTok{\{}
-            \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{image\_id\_file=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-            \FunctionTok{awk}\NormalTok{ {-}F }\StringTok{\textquotesingle{}=\textquotesingle{}} \StringTok{\textquotesingle{}/IMG\_ID/ \{print $2\}\textquotesingle{}} \StringTok{"}\VariableTok{$image\_id\_file}\StringTok{"}
-        \KeywordTok{\}}
-
-        \CommentTok{\# Check if the selected image exists in cache by comparing its id file to the one stored in cache.}
-        \CommentTok{\# Return value: 0 if the image is cached, 1 if it\textquotesingle{}s not}
-        \FunctionTok{is\_image\_cached()} \KeywordTok{\{}
-            \KeywordTok{if [[}\NormalTok{ hidden\_partition\_status }\OtherTok{==} \StringTok{"}\VariableTok{$HIDDEN\_PARTITION\_STATUS\_CREATED}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \BuiltInTok{return}\NormalTok{ 1}
-            \KeywordTok{fi}
-
-            \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_RAW}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{remote\_image\_id\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/}\VariableTok{$image\_name}\StringTok{.md5"}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{cached\_image\_id\_file=}\StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{/}\VariableTok{$image\_name}\StringTok{.md5"}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{read\_image\_id\_file=}\NormalTok{read\_raw\_image\_id\_file}
-            \KeywordTok{elif [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_CLONEZILLA}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{remote\_image\_id\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/Info{-}img{-}id.txt"}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{cached\_image\_id\_file=}\StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{/}\VariableTok{$image\_name}\StringTok{/Info{-}img{-}id.txt"}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{read\_image\_id\_file=}\NormalTok{read\_clonezilla\_image\_id\_file}
-            \KeywordTok{else}
-                \ExtensionTok{fatal\_error} \StringTok{"Unhandled image type: }\VariableTok{$image\_type}\StringTok{"}
-            \KeywordTok{fi}
-
-            \KeywordTok{if [[} \OtherTok{{-}f} \StringTok{"}\VariableTok{$cached\_image\_id\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{cached\_image\_id=$($read\_image\_id\_file} \StringTok{"}\VariableTok{$cached\_image\_id\_file}\StringTok{"}\VariableTok{)}
-                \KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$cached\_image\_id}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                    \BuiltInTok{return}\NormalTok{ 1}
-                \KeywordTok{fi}
-
-                \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{remote\_image\_id=$($read\_image\_id\_file} \StringTok{"}\VariableTok{$remote\_image\_id\_file}\StringTok{"}\VariableTok{)}
-                \KeywordTok{if [[} \StringTok{"}\VariableTok{$cached\_image\_id}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$remote\_image\_id}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                    \BuiltInTok{return}\NormalTok{ 0}
-                \KeywordTok{fi}
-            \KeywordTok{fi}
-            \BuiltInTok{return}\NormalTok{ 1}
-        \KeywordTok{\}}
-
-        \ExtensionTok{start\_step\_batch} \StringTok{"cached image search"}
-        \BuiltInTok{echo} \StringTok{"Checking if image is cached..."}
-        \KeywordTok{if} \ExtensionTok{is\_image\_cached}\KeywordTok{;} \KeywordTok{then}
-            \BuiltInTok{echo} \StringTok{"Image found in cache."}
-            \VariableTok{deploy\_mode=}\StringTok{"}\VariableTok{$DEPLOY\_MODE\_ALREADY\_CACHED}\StringTok{"}
-        \KeywordTok{else}
-            \BuiltInTok{echo} \StringTok{"Image not found in cache."}
-
-            \ExtensionTok{start\_step\_batch} \StringTok{"image cache space availability check"}
-
-            \VariableTok{cache\_available\_size\_bytes=$(}\FunctionTok{df}\NormalTok{ {-}{-}block{-}size=1 {-}{-}output=avail }\StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{"} \KeywordTok{|} \FunctionTok{tail}\NormalTok{ {-}n 1}\VariableTok{)}
-
-            \KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$cache\_available\_size\_bytes}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \ExtensionTok{fatal\_error} \StringTok{"Cannot retrieve available size in cache."}
-            \KeywordTok{fi}
-
-            \KeywordTok{((}\NormalTok{cache\_available\_size\_bytes = cache\_available\_size\_bytes {-} 4096}\KeywordTok{))}
-
-            \BuiltInTok{echo} \StringTok{"Available size in cache: }\VariableTok{$cache\_available\_size\_bytes}\StringTok{ B"}
-
-            \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_RAW}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \VariableTok{image\_size\_bytes=$(}\FunctionTok{stat}\NormalTok{ {-}c \%s }\StringTok{"}\VariableTok{$remote\_image\_gzip\_file}\StringTok{"}\VariableTok{)}
-            \KeywordTok{elif [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_CLONEZILLA}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \VariableTok{image\_size\_bytes=$(}\FunctionTok{du}\NormalTok{ {-}b {-}c }\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{"} \KeywordTok{|} \FunctionTok{tail}\NormalTok{ {-}n1 }\KeywordTok{|} \FunctionTok{cut}\NormalTok{ {-}f1}\VariableTok{)}
-            \KeywordTok{else}
-                \ExtensionTok{fatal\_error} \StringTok{"Unhandled image type: }\VariableTok{$image\_type}\StringTok{"}
-            \KeywordTok{fi}
-
-            \BuiltInTok{echo} \StringTok{"Size of image to download: }\VariableTok{$image\_size\_bytes}\StringTok{ B"}
-
-            \CommentTok{\# Check enough space available in hidden partition for caching}
-            \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_size\_bytes}\StringTok{"} \OtherTok{{-}lt} \StringTok{"}\VariableTok{$cache\_available\_size\_bytes}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \BuiltInTok{echo} \StringTok{"Enough space for caching. Image will be cached and deployed simultaneously."}
-                \VariableTok{deploy\_mode=}\StringTok{"}\VariableTok{$DEPLOY\_MODE\_CACHED\_NOW}\StringTok{"}
-            \KeywordTok{else}
-                \BuiltInTok{echo} \StringTok{"Not enough space for caching. Image will be deployed without caching."}
-                \VariableTok{deploy\_mode=}\StringTok{"}\VariableTok{$DEPLOY\_MODE\_NOT\_CACHED}\StringTok{"}
-            \KeywordTok{fi}
-        \KeywordTok{fi}
-    \KeywordTok{fi}
-
-    \FunctionTok{deploy\_image\_with\_clonezilla()} \KeywordTok{\{}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{clonezilla\_images\_dir=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-        \BuiltInTok{echo} \StringTok{"Starting deployment of image }\VariableTok{$image\_name}\StringTok{ from }\VariableTok{$clonezilla\_images\_dir}\StringTok{ with clonezilla..."}
-        \CommentTok{\# yes \textquotesingle{}\textquotesingle{} 2\textgreater{}/dev/null |}
-        \ExtensionTok{ocs{-}sr} \KeywordTok{\textbackslash{}}
-            \ExtensionTok{{-}{-}ignore{-}update{-}efi{-}nvram} \KeywordTok{\textbackslash{}}
-            \ExtensionTok{{-}{-}ocsroot} \StringTok{"}\VariableTok{$clonezilla\_images\_dir}\StringTok{"} \KeywordTok{\textbackslash{}}
-            \ExtensionTok{{-}{-}skip{-}check{-}restorable{-}r} \KeywordTok{\textbackslash{}}
-            \ExtensionTok{{-}{-}nogui} \KeywordTok{\textbackslash{}}
-            \ExtensionTok{{-}{-}batch} \KeywordTok{\textbackslash{}}
-            \ExtensionTok{restoredisk} \StringTok{"}\VariableTok{$image\_name}\StringTok{"}\NormalTok{ sda}
-
-        \BuiltInTok{echo} \StringTok{"Checking for error during clonezilla deployment..."}
-
-        \KeywordTok{if} \FunctionTok{grep} \StringTok{"Failed to restore partition image file"}\NormalTok{ /var/log/clonezilla.log}\KeywordTok{;} \KeywordTok{then}
-            \ExtensionTok{fatal\_error} \StringTok{"Error while deploying image with clonezilla."}
-        \KeywordTok{fi}
-
-        \BuiltInTok{echo} \StringTok{"Image deployed with clonezilla."}
-    \KeywordTok{\}}
-
-    \FunctionTok{print\_progress()} \KeywordTok{\{}
-        \ExtensionTok{pv}\NormalTok{ {-}ptebar {-}{-}size }\StringTok{"}\VariableTok{$image\_size}\StringTok{"} \OperatorTok{2\textgreater{}}\StringTok{"}\VariableTok{$tty}\StringTok{"}
-    \KeywordTok{\}}
-
-    \ExtensionTok{start\_step\_batch} \StringTok{"image deployment"}
-    \KeywordTok{if [[} \StringTok{"}\VariableTok{$deploy\_mode}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$DEPLOY\_MODE\_CACHED\_NOW}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{echo} \StringTok{"Saving image to cache and deploying it..."}
-        \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_RAW}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-            \FunctionTok{cp} \StringTok{"}\VariableTok{$remote\_image\_md5\_file}\StringTok{"} \StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{/"} \KeywordTok{||}
-                \ExtensionTok{fatal\_error} \StringTok{"Cannot copy hash of image to }\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-
-            \FunctionTok{tee} \StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{/}\VariableTok{$image\_name}\StringTok{.img.gz"} \OperatorTok{\textless{}} \StringTok{"}\VariableTok{$remote\_image\_gzip\_file}\StringTok{"} \KeywordTok{|}
-                \FunctionTok{gunzip}\NormalTok{ {-}c }\KeywordTok{|}
-                \ExtensionTok{print\_progress} \KeywordTok{|}
-                \FunctionTok{dd}\NormalTok{ bs=128k of=}\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"} \KeywordTok{||}
-                \ExtensionTok{fatal\_error} \StringTok{"Cannot copy image to cache and disk."}
-        \KeywordTok{elif [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_CLONEZILLA}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-            \BuiltInTok{echo} \StringTok{"Starting copy of clonezilla image to cache..."}
-            \FunctionTok{rm}\NormalTok{ {-}rf }\StringTok{"}\VariableTok{$\{mounting\_point\_hidden:?\}}\StringTok{/}\VariableTok{$image\_name}\StringTok{"}
-            \FunctionTok{cp}\NormalTok{ {-}r }\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{"} \StringTok{"}\VariableTok{$\{mounting\_point\_hidden:?\}}\StringTok{/"} \KeywordTok{||}
-                \ExtensionTok{fatal\_error} \StringTok{"Error while copying remote image to cache."}
-            \BuiltInTok{echo} \StringTok{"Clonezilla image copied to cache."}
-            \BuiltInTok{echo} \StringTok{"Content of cache:"}
-            \FunctionTok{ls}\NormalTok{ {-}als }\StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-
-            \ExtensionTok{deploy\_image\_with\_clonezilla} \StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-        \KeywordTok{else}
-            \ExtensionTok{fatal\_error} \StringTok{"Unhandled image type: }\VariableTok{$image\_type}\StringTok{"}
-        \KeywordTok{fi}
-
-        \BuiltInTok{echo} \StringTok{"Image deployed and cached."}
-    \KeywordTok{elif [[} \StringTok{"}\VariableTok{$deploy\_mode}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$DEPLOY\_MODE\_ALREADY\_CACHED}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{echo} \StringTok{"Deploying image from cache..."}
-
-        \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_RAW}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-            \FunctionTok{gunzip}\NormalTok{ {-}c }\StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{/}\VariableTok{$image\_name}\StringTok{.img.gz"} \KeywordTok{|}
-                \ExtensionTok{print\_progress} \KeywordTok{|}
-                \FunctionTok{dd}\NormalTok{ bs=1M of=}\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"} \KeywordTok{||}
-                \ExtensionTok{fatal\_error} \StringTok{"Cannot copy image from cache to disk."}
-        \KeywordTok{elif [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_CLONEZILLA}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-            \ExtensionTok{deploy\_image\_with\_clonezilla} \StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-        \KeywordTok{else}
-            \ExtensionTok{fatal\_error} \StringTok{"Unhandled image type: }\VariableTok{$image\_type}\StringTok{"}
-        \KeywordTok{fi}
-
-        \BuiltInTok{echo} \StringTok{"Image deployed from cache."}
-    \KeywordTok{elif [[} \StringTok{"}\VariableTok{$deploy\_mode}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$DEPLOY\_MODE\_NOT\_CACHED}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{echo} \StringTok{"Deploying image without caching..."}
-
-        \KeywordTok{if [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_RAW}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-            \FunctionTok{gunzip}\NormalTok{ {-}c }\StringTok{"}\VariableTok{$remote\_image\_gzip\_file}\StringTok{"} \KeywordTok{|}
-                \ExtensionTok{print\_progress} \KeywordTok{|}
-                \FunctionTok{dd}\NormalTok{ of=}\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}\NormalTok{ bs=128k }\KeywordTok{||}
-                \ExtensionTok{fatal\_error} \StringTok{"Cannot copy image without caching."}
-        \KeywordTok{elif [[} \StringTok{"}\VariableTok{$image\_type}\StringTok{"} \OtherTok{==} \StringTok{"}\VariableTok{$IMAGE\_TYPE\_CLONEZILLA}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-            \ExtensionTok{deploy\_image\_with\_clonezilla} \StringTok{"}\VariableTok{$remote\_images\_dir}\StringTok{"}
-        \KeywordTok{else}
-            \ExtensionTok{fatal\_error} \StringTok{"Unhandled image type: }\VariableTok{$image\_type}\StringTok{"}
-        \KeywordTok{fi}
-
-        \BuiltInTok{echo} \StringTok{"Image deployed without caching."}
-    \KeywordTok{else}
-        \ExtensionTok{fatal\_error} \StringTok{"Unhandled deploy mode: }\VariableTok{$deploy\_mode}\StringTok{"}
-    \KeywordTok{fi}
-
-    \BuiltInTok{echo} \StringTok{"Deployment of image }\VariableTok{$image\_name}\StringTok{ (}\VariableTok{$image\_size}\StringTok{ B) done."}
-
-    \KeywordTok{if} \ExtensionTok{findmnt}\NormalTok{ {-}{-}mountpoint }\StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{"}\KeywordTok{;} \KeywordTok{then}
-        \ExtensionTok{start\_step\_batch} \StringTok{"image cache partition unmount"}
-        \BuiltInTok{echo} \StringTok{"Unmounting hidden partition from }\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-        \FunctionTok{umount} \StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"Cannot unmount hidden partition from }\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-        \BuiltInTok{echo} \StringTok{"Unmounted hidden partition from }\VariableTok{$mounting\_point\_hidden}\StringTok{"}
-
-        \ExtensionTok{start\_step\_batch} \StringTok{"image cache partition check"}
-        \ExtensionTok{fsck}\NormalTok{ {-}y }\StringTok{"}\VariableTok{$hidden\_partition\_dev}\StringTok{"}
-    \KeywordTok{fi}
-
-    \ExtensionTok{start\_step\_batch} \StringTok{"EFI entrypoint file creation"}
-
-    \BuiltInTok{readonly} \VariableTok{remote\_image\_efi\_entrypoint\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/efi\_entrypoint"}
-    \BuiltInTok{readonly} \VariableTok{remote\_image\_efi\_nvram\_file=}\StringTok{"}\VariableTok{$remote\_image\_dir}\StringTok{/efi{-}nvram.dat"}
-    \BuiltInTok{readonly} \VariableTok{mounting\_point\_esp=}\StringTok{"/bootiful/esp"}
-    \BuiltInTok{readonly} \VariableTok{esp\_partition=}\StringTok{"}\VariableTok{$\{deployment\_disk\}}\StringTok{1"}
-
-    \FunctionTok{mount\_esp()} \KeywordTok{\{}
-        \BuiltInTok{echo} \StringTok{"Mounting ESP partition..."}
-        \ExtensionTok{ensure\_directory} \StringTok{"}\VariableTok{$mounting\_point\_esp}\StringTok{"}
-        \ExtensionTok{refresh\_partition\_table}
-        \FunctionTok{mount} \StringTok{"}\VariableTok{$esp\_partition}\StringTok{"} \StringTok{"}\VariableTok{$mounting\_point\_esp}\StringTok{"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"Cannot mount }\VariableTok{$esp\_partition}\StringTok{ on }\VariableTok{$mounting\_point\_esp}\StringTok{"}
-        \BuiltInTok{echo} \StringTok{"ESP partition mounted."}
-    \KeywordTok{\}}
-
-    \FunctionTok{write\_efi\_entrypoint\_file()} \KeywordTok{\{}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{efi\_entrypoint\_file\_content=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-        \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{target\_efi\_entrypoint\_file=}\StringTok{"}\VariableTok{$mounting\_point\_esp}\StringTok{/efi\_entrypoint"}
-
-        \BuiltInTok{echo} \StringTok{"Writing efi entrypoint file \textquotesingle{}}\VariableTok{$target\_efi\_entrypoint\_file}\StringTok{\textquotesingle{}"}
-
-        \BuiltInTok{echo} \StringTok{"}\VariableTok{$efi\_entrypoint\_file\_content}\StringTok{"} \OperatorTok{\textgreater{}} \StringTok{"}\VariableTok{$target\_efi\_entrypoint\_file}\StringTok{"} \KeywordTok{||}
-            \ExtensionTok{fatal\_error} \StringTok{"Cannot write EFI entrypoint file \textquotesingle{}}\VariableTok{$target\_efi\_entrypoint\_file}\StringTok{\textquotesingle{}."}
-
-        \BuiltInTok{echo} \StringTok{"EFI entrypoint file \textquotesingle{}}\VariableTok{$target\_efi\_entrypoint\_file}\StringTok{\textquotesingle{} written."}
-
-        \FunctionTok{umount} \StringTok{"}\VariableTok{$mounting\_point\_esp}\StringTok{"}
-    \KeywordTok{\}}
-
-    \KeywordTok{if [[} \OtherTok{{-}e} \StringTok{"}\VariableTok{$remote\_image\_efi\_entrypoint\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{echo} \StringTok{"EFI entrypoint file detected. Copying it to ESP root..."}
-        \ExtensionTok{mount\_esp}
-        \ExtensionTok{write\_efi\_entrypoint\_file} \StringTok{"}\VariableTok{$(}\FunctionTok{cat} \StringTok{"}\VariableTok{$remote\_image\_efi\_entrypoint\_file}\StringTok{"}\VariableTok{)}\StringTok{"}
-    \KeywordTok{elif [[} \OtherTok{{-}e} \StringTok{"}\VariableTok{$remote\_image\_efi\_nvram\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-        \BuiltInTok{echo} \StringTok{"Trying to find boot entry from efi nvram file }\VariableTok{$remote\_image\_efi\_nvram\_file}\StringTok{..."}
-
-        \VariableTok{boot\_order\_entries=}\StringTok{"}\VariableTok{$(}\FunctionTok{sed}\NormalTok{ {-}nr }\StringTok{\textquotesingle{}s/\^{}BootOrder: ([0{-}9]+(,[0{-}9]+)*)$/\textbackslash{}1/p\textquotesingle{}} \StringTok{"}\VariableTok{$remote\_image\_efi\_nvram\_file}\StringTok{"} \KeywordTok{|}
-            \FunctionTok{head}\NormalTok{ {-}n 1 }\KeywordTok{|}
-            \FunctionTok{tr} \StringTok{\textquotesingle{},\textquotesingle{}} \StringTok{\textquotesingle{} \textquotesingle{}}\VariableTok{)}\StringTok{"}
-
-        \KeywordTok{if [[} \OtherTok{{-}n} \StringTok{"}\VariableTok{$boot\_order\_entries}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-            \BuiltInTok{echo} \StringTok{"Boot order entries found: }\VariableTok{$boot\_order\_entries}\StringTok{"}
-            \VariableTok{written\_boot\_order\_entry=}\StringTok{""}
-            \KeywordTok{for} \ExtensionTok{boot\_order\_entry}\NormalTok{ in }\VariableTok{$boot\_order\_entries}\KeywordTok{;} \KeywordTok{do}
-                \BuiltInTok{echo} \StringTok{"Trying to find boot file path for boot order entry }\VariableTok{$boot\_order\_entry}\StringTok{..."}
-                \VariableTok{boot\_file\_path=}\StringTok{"}\VariableTok{$(}\FunctionTok{sed}\NormalTok{ {-}nr }\StringTok{"s|\^{}Boot}\VariableTok{$boot\_order\_entry}\StringTok{.*\textbackslash{}tHD\textbackslash{}(1.*\textbackslash{})/File\textbackslash{}((.*)\textbackslash{}).*$|\textbackslash{}1|p"} \StringTok{"}\VariableTok{$remote\_image\_efi\_nvram\_file}\StringTok{"}\VariableTok{)}\StringTok{"}
-
-                \KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$boot\_file\_path}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                    \BuiltInTok{echo} \StringTok{"Boot file path not found for boot entry }\VariableTok{$boot\_order\_entry}\StringTok{"}
-                    \BuiltInTok{continue}
-                \KeywordTok{fi}
-
-                \BuiltInTok{echo} \StringTok{"Boot file path found for boot entry }\VariableTok{$boot\_order\_entry}\StringTok{: }\VariableTok{$boot\_file\_path}\StringTok{"}
-
-                \ExtensionTok{mount\_esp}
-
-                \KeywordTok{if [[} \StringTok{"}\VariableTok{$boot\_file\_path}\StringTok{"}\NormalTok{ =\textasciitilde{} \^{}}\DataTypeTok{\textbackslash{}\textbackslash{}}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                    \BuiltInTok{echo} \StringTok{"Boot file path looks like a windows{-}like path. Converting it to a unix{-}like path..."}
-                    \VariableTok{unix\_boot\_file\_path=}\StringTok{"}\VariableTok{$(}\BuiltInTok{echo} \StringTok{"}\VariableTok{$boot\_file\_path}\StringTok{"} \KeywordTok{|} \FunctionTok{tr} \DataTypeTok{\textbackslash{}\textbackslash{}\textbackslash{}\textbackslash{}}\NormalTok{ /}\VariableTok{)}\StringTok{"}
-                    \BuiltInTok{echo} \StringTok{"Windows{-}like path \textquotesingle{}}\VariableTok{$boot\_file\_path}\StringTok{\textquotesingle{} converted to unix{-}like path \textquotesingle{}}\VariableTok{$unix\_boot\_file\_path}\StringTok{\textquotesingle{}"}
-
-                    \BuiltInTok{echo} \StringTok{"Trying to find the case sensitive path for \textquotesingle{}}\VariableTok{$unix\_boot\_file\_path}\StringTok{\textquotesingle{} in EFI..."}
-                    \VariableTok{boot\_file\_path=}\StringTok{"}\VariableTok{$(}
-                        \FunctionTok{find} \StringTok{"}\VariableTok{$mounting\_point\_esp}\StringTok{"} \KeywordTok{\textbackslash{}}
-                            \ExtensionTok{{-}type}\NormalTok{ f }\KeywordTok{\textbackslash{}}
-                            \ExtensionTok{{-}ipath} \StringTok{"}\VariableTok{$mounting\_point\_esp$unix\_boot\_file\_path}\StringTok{"} \KeywordTok{\textbackslash{}}
-                            \ExtensionTok{{-}printf} \StringTok{\textquotesingle{}/\%P\textbackslash{}n\textquotesingle{}} \KeywordTok{|}
-                            \FunctionTok{head}\NormalTok{ {-}n 1}
-                    \VariableTok{)}\StringTok{"}
-
-                    \KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$boot\_file\_path}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                        \ExtensionTok{fatal\_error} \StringTok{"Cannot find a case insensitive match for efi boot file \textquotesingle{}}\VariableTok{$unix\_boot\_file\_path}\StringTok{\textquotesingle{}"}
-                    \KeywordTok{fi}
-
-                    \BuiltInTok{echo} \StringTok{"Case insensitive EFI boot file path found: \textquotesingle{}}\VariableTok{$boot\_file\_path}\StringTok{\textquotesingle{}."}
-                \KeywordTok{fi}
-
-                \ExtensionTok{write\_efi\_entrypoint\_file} \StringTok{"set efi\_entrypoint=}\VariableTok{$boot\_file\_path}\StringTok{"}
-                \VariableTok{written\_boot\_order\_entry=}\StringTok{"}\VariableTok{$boot\_order\_entry}\StringTok{"}
-                \BuiltInTok{break}
-            \KeywordTok{done}
-
-            \KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$written\_boot\_order\_entry}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-                \ExtensionTok{fatal\_error} \StringTok{"No bootfile found in \textquotesingle{}}\VariableTok{$remote\_image\_efi\_nvram\_file}\StringTok{\textquotesingle{}."}
-            \KeywordTok{fi}
-        \KeywordTok{else}
-            \ExtensionTok{fatal\_error} \StringTok{"Boot order entries not found in \textquotesingle{}}\VariableTok{$remote\_image\_efi\_nvram\_file}\StringTok{\textquotesingle{}."}
-        \KeywordTok{fi}
-    \KeywordTok{else}
-        \BuiltInTok{echo} \StringTok{"No EFI entrypoint file or EFI nvram file found."}
-    \KeywordTok{fi}
-
-    \ExtensionTok{start\_step\_batch} \StringTok{"signature creation"}
-
-    \KeywordTok{((}\NormalTok{signature\_offset = total\_disk\_size {-} 200}\KeywordTok{))}
-    \VariableTok{signature=}\StringTok{"hepia2015"}
-
-    \BuiltInTok{echo} \StringTok{"Writing signature \textquotesingle{}}\VariableTok{$signature}\StringTok{\textquotesingle{} on offset }\VariableTok{$signature\_offset}\StringTok{ B..."}
-    \BuiltInTok{echo}\NormalTok{ {-}ne }\StringTok{"}\VariableTok{$signature}\StringTok{"} \KeywordTok{|} \FunctionTok{dd}\NormalTok{ of=}\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}\NormalTok{ seek=}\StringTok{"}\VariableTok{$signature\_offset}\StringTok{"}\NormalTok{ bs=1 iflag=skip\_bytes }\KeywordTok{||}
-        \ExtensionTok{fatal\_error} \StringTok{"Cannot write signature at the end of the disk"}
-    \BuiltInTok{echo} \StringTok{"Signature written."}
-
-    \BuiltInTok{echo} \StringTok{"Image deployment process successful."}
-
-    \ExtensionTok{print\_step\_durations}
-
-\KeywordTok{\}} \OperatorTok{2\textgreater{}\&1} \KeywordTok{|} \FunctionTok{tee} \StringTok{"}\VariableTok{$log\_file}\StringTok{"}
-
-\BuiltInTok{exit} \StringTok{"}\VariableTok{$\{PIPESTATUS[0]\}}\StringTok{"}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerbootiful-save-image-script-utilitaire-de-cruxe9ation-dimage-raw}{%
-\section{\texorpdfstring{\texttt{deployer/bootiful-save-image}: script
-utilitaire de création d'image
-raw}{deployer/bootiful-save-image: script utilitaire de création d'image raw}}\label{deployerbootiful-save-image-script-utilitaire-de-cruxe9ation-dimage-raw}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#!/bin/bash}
-\BuiltInTok{readonly} \VariableTok{SCRIPT\_NAME=}\StringTok{"}\VariableTok{$(}\FunctionTok{basename} \StringTok{"}\VariableTok{$0}\StringTok{"}\VariableTok{)}\StringTok{"}
-\BuiltInTok{readonly} \VariableTok{SCRIPT\_DIR=}\StringTok{"}\VariableTok{$(}\FunctionTok{readlink}\NormalTok{ {-}m }\StringTok{"}\VariableTok{$(}\FunctionTok{dirname} \StringTok{"}\VariableTok{$0}\StringTok{"}\VariableTok{)}\StringTok{"}\VariableTok{)}\StringTok{"}
-
-\FunctionTok{usage()} \KeywordTok{\{}
-    \FunctionTok{cat} \OperatorTok{\textless{}\textless{} EOF}
-\NormalTok{Usage:}
-  \VariableTok{$SCRIPT\_DIR}\NormalTok{ IMAGE\_NAME}
-  \VariableTok{$SCRIPT\_DIR}\NormalTok{ [{-}h | {-}{-}help]}
-
-\NormalTok{Description:}
-\NormalTok{  Saves a raw dd image of the /dev/sda device to the remote server shared images}
-\NormalTok{  folder.}
-
-\NormalTok{Parameters:}
-\NormalTok{  IMAGE\_NAME  Name of the image to create}
-
-\NormalTok{Options:}
-\NormalTok{  {-}h {-}{-}help  Shows this help}
-
-\NormalTok{Example:}
-\NormalTok{  ./}\VariableTok{$SCRIPT\_NAME}\NormalTok{ debian{-}buster{-}x86\_64{-}efi}
-\OperatorTok{EOF}
-\KeywordTok{\}}
-
-\KeywordTok{if [[} \StringTok{"}\VariableTok{$1}\StringTok{"} \OtherTok{==} \StringTok{"{-}h"}\NormalTok{ || }\StringTok{"}\VariableTok{$1}\StringTok{"} \OtherTok{==} \StringTok{"{-}{-}help"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \ExtensionTok{usage}
-    \BuiltInTok{exit}\NormalTok{ 0}
-\KeywordTok{fi}
-
-\BuiltInTok{readonly} \VariableTok{image\_name=}\StringTok{"}\VariableTok{$1}\StringTok{"}
-\KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$image\_name}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \ExtensionTok{usage}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\CommentTok{\# Loads declarations from the \textquotesingle{}bootiful{-}common\textquotesingle{} script, which is a "library"}
-\CommentTok{\# of functions and constants shared by multiple bootiful{-}* scripts.}
-\BuiltInTok{readonly} \VariableTok{bootiful\_common\_script\_file=}\StringTok{"}\VariableTok{$SCRIPT\_DIR}\StringTok{/bootiful{-}common"}
-\KeywordTok{if [[} \OtherTok{!} \OtherTok{{-}f} \StringTok{"}\VariableTok{$bootiful\_common\_script\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \OperatorTok{\textgreater{}\&2} \BuiltInTok{echo} \StringTok{"Fatal error: cannot find required script file \textquotesingle{}}\VariableTok{$bootiful\_common\_script\_file}\StringTok{\textquotesingle{}."}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-\CommentTok{\# shellcheck source=./bootiful{-}common}
-\BuiltInTok{.} \StringTok{"}\VariableTok{$bootiful\_common\_script\_file}\StringTok{"}
-
-\ExtensionTok{ensure\_remote\_shared\_mounted}
-
-\BuiltInTok{echo} \StringTok{"Finding size of the image to create..."}
-\BuiltInTok{readonly} \VariableTok{parted\_unit=}\StringTok{"B"}
-
-\BuiltInTok{declare} \VariableTok{parted\_output}
-\VariableTok{parted\_output=$(}\ExtensionTok{parted}\NormalTok{ {-}{-}script }\StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}\NormalTok{ unit }\StringTok{"}\VariableTok{$parted\_unit}\StringTok{"}\NormalTok{ print}\VariableTok{)} \KeywordTok{||}
-    \ExtensionTok{fatal\_error} \StringTok{"failed to save parted output"}
-\BuiltInTok{readonly} \VariableTok{parted\_output}
-
-\BuiltInTok{declare} \VariableTok{image\_size}
-\VariableTok{image\_size=$(}\ExtensionTok{parse\_parted\_last\_partition\_end} \StringTok{"}\VariableTok{$parted\_output}\StringTok{"} \StringTok{"}\VariableTok{$parted\_unit}\StringTok{"}\VariableTok{)}
-\BuiltInTok{readonly} \VariableTok{image\_size}
-
-\BuiltInTok{echo} \StringTok{"Image size: }\VariableTok{$image\_size}\StringTok{"}
-
-\BuiltInTok{readonly} \VariableTok{image\_folder=}\StringTok{"}\VariableTok{$mounting\_point\_hidden}\StringTok{/images/}\VariableTok{$image\_name}\StringTok{"}
-
-\KeywordTok{if [[} \OtherTok{{-}d} \StringTok{"}\VariableTok{$image\_folder}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \BuiltInTok{echo} \StringTok{"Image folder \textquotesingle{}}\VariableTok{$image\_folder}\StringTok{\textquotesingle{} already exists."}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\KeywordTok{if}\NormalTok{ ! }\FunctionTok{mkdir} \StringTok{"}\VariableTok{$image\_folder}\StringTok{"}\KeywordTok{;} \KeywordTok{then}
-    \BuiltInTok{echo} \StringTok{"Cannot create image folder \textquotesingle{}}\VariableTok{$image\_folder}\StringTok{\textquotesingle{}"}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\BuiltInTok{readonly} \VariableTok{image\_file=}\StringTok{"}\VariableTok{$image\_folder}\StringTok{/}\VariableTok{$image\_name}\StringTok{.img.gz"}
-\KeywordTok{if}\NormalTok{ ! }\ExtensionTok{pv}\NormalTok{ {-}{-}size }\StringTok{"}\VariableTok{$image\_size}\StringTok{"}\NormalTok{ {-}{-}stop{-}at{-}size /dev/sda }\KeywordTok{|}
-        \ExtensionTok{pigz}\NormalTok{ {-}c }\OperatorTok{\textgreater{}} \StringTok{"}\VariableTok{$image\_file}\StringTok{"}
-\KeywordTok{then}
-    \BuiltInTok{echo} \StringTok{"Cannot create image file \textquotesingle{}}\VariableTok{$image\_file}\StringTok{\textquotesingle{}"}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\CommentTok{\# }\AlertTok{TODO}\CommentTok{: Rename md5 files to uuid because creating md5 hashes takes too much time}
-\BuiltInTok{readonly} \VariableTok{md5\_file=}\StringTok{"}\VariableTok{$image\_folder}\StringTok{/}\VariableTok{$image\_name}\StringTok{.md5"}
-\KeywordTok{if}\NormalTok{ ! }\FunctionTok{cat}\NormalTok{ /proc/sys/kernel/random/uuid }\OperatorTok{\textgreater{}} \StringTok{"}\VariableTok{$md5\_file}\StringTok{"}\KeywordTok{;} \KeywordTok{then}
-    \BuiltInTok{echo} \StringTok{"Cannot create md5 file \textquotesingle{}}\VariableTok{$md5\_file}\StringTok{\textquotesingle{}"}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\BuiltInTok{readonly} \VariableTok{partition\_file=}\StringTok{"}\VariableTok{$image\_folder}\StringTok{/}\VariableTok{$image\_name}\StringTok{.partition"}
-\KeywordTok{if}\NormalTok{ ! }\ExtensionTok{fdisk}\NormalTok{ {-}l /dev/sda }\OperatorTok{\textgreater{}} \StringTok{"}\VariableTok{$partition\_file}\StringTok{"}\KeywordTok{;} \KeywordTok{then}
-    \BuiltInTok{echo} \StringTok{"Cannot create partition file }\VariableTok{$partition\_file}\StringTok{"}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\BuiltInTok{readonly} \VariableTok{size\_file=}\StringTok{"}\VariableTok{$image\_folder}\StringTok{/}\VariableTok{$image\_name}\StringTok{.size"}
-\KeywordTok{if}\NormalTok{ ! }\FunctionTok{du} \StringTok{"}\VariableTok{$image\_file}\StringTok{"} \OperatorTok{\textgreater{}} \StringTok{"}\VariableTok{$size\_file}\StringTok{"}\KeywordTok{;} \KeywordTok{then}
-    \BuiltInTok{echo} \StringTok{"Cannot create size file }\VariableTok{$size\_file}\StringTok{"}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-
-\BuiltInTok{echo} \StringTok{"Image creation successful."}
-\BuiltInTok{exit}\NormalTok{ 0}
-
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{deployerbootiful-reset-cache-script-utilitaire-de-ruxe9initialisation-du-cache}{%
-\section{\texorpdfstring{\texttt{deployer/bootiful-reset-cache}: script
-utilitaire de réinitialisation du
-cache}{deployer/bootiful-reset-cache: script utilitaire de réinitialisation du cache}}\label{deployerbootiful-reset-cache-script-utilitaire-de-ruxe9initialisation-du-cache}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#!/bin/bash}
-
-\BuiltInTok{readonly} \VariableTok{SCRIPT\_NAME=}\StringTok{"}\VariableTok{$(}\FunctionTok{basename} \StringTok{"}\VariableTok{$0}\StringTok{"}\VariableTok{)}\StringTok{"}
-\BuiltInTok{readonly} \VariableTok{SCRIPT\_DIR=}\StringTok{"}\VariableTok{$(}\FunctionTok{readlink}\NormalTok{ {-}m }\StringTok{"}\VariableTok{$(}\FunctionTok{dirname} \StringTok{"}\VariableTok{$0}\StringTok{"}\VariableTok{)}\StringTok{"}\VariableTok{)}\StringTok{"}
-
-\FunctionTok{usage()} \KeywordTok{\{}
-    \FunctionTok{cat} \OperatorTok{\textless{}\textless{} EOF}
-\NormalTok{Usage:}
-  \VariableTok{$SCRIPT\_DIR}\NormalTok{ [{-}h | {-}{-}help]}
-
-\NormalTok{Description:}
-\NormalTok{  Clears the bootiful image cache by re{-}creating the hidden partition}
-
-\NormalTok{Options:}
-\NormalTok{  {-}h {-}{-}help  Shows this help}
-
-\NormalTok{Example:}
-\NormalTok{  ./}\VariableTok{$SCRIPT\_NAME}
-\OperatorTok{EOF}
-\KeywordTok{\}}
-
-\KeywordTok{if [[} \StringTok{"}\VariableTok{$1}\StringTok{"} \OtherTok{==} \StringTok{"{-}h"}\NormalTok{ || }\StringTok{"}\VariableTok{$1}\StringTok{"} \OtherTok{==} \StringTok{"{-}{-}help"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \ExtensionTok{usage}
-    \BuiltInTok{exit}\NormalTok{ 0}
-\KeywordTok{fi}
-
-\CommentTok{\# Loads declarations from the \textquotesingle{}bootiful{-}common\textquotesingle{} script, which is a "library"}
-\CommentTok{\# of functions and constants shared by multiple bootiful{-}* scripts.}
-\BuiltInTok{readonly} \VariableTok{bootiful\_common\_script\_file=}\StringTok{"}\VariableTok{$SCRIPT\_DIR}\StringTok{/bootiful{-}common"}
-\KeywordTok{if [[} \OtherTok{!} \OtherTok{{-}f} \StringTok{"}\VariableTok{$bootiful\_common\_script\_file}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \OperatorTok{\textgreater{}\&2} \BuiltInTok{echo} \StringTok{"Fatal error: cannot find required script file \textquotesingle{}}\VariableTok{$bootiful\_common\_script\_file}\StringTok{\textquotesingle{}."}
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{fi}
-\CommentTok{\# shellcheck source=./bootiful{-}common}
-\BuiltInTok{.} \StringTok{"}\VariableTok{$bootiful\_common\_script\_file}\StringTok{"}
-
-\ExtensionTok{validate\_exists} \StringTok{"}\VariableTok{$deployment\_disk}\StringTok{"}
-\ExtensionTok{create\_hidden\_partition}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{dhcpdockerfile-configuration-docker-du-serveur-dhcp}{%
-\section{\texorpdfstring{\texttt{dhcp/Dockerfile}: configuration
-\emph{Docker} du serveur
-\protect\hyperlink{acronym__DHCP}{DHCP}}{dhcp/Dockerfile: configuration Docker du serveur DHCP}}\label{dhcpdockerfile-configuration-docker-du-serveur-dhcp}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{FROM}\NormalTok{ alpine:3.12}
-\KeywordTok{RUN}\NormalTok{ apk add dhcp{-}server{-}vanilla \&\& touch /var/lib/dhcp/dhcpd.leases}
-\KeywordTok{COPY}\NormalTok{ dhcpd.conf /etc/dhcp/dhcpd.conf}
-\KeywordTok{EXPOSE}\NormalTok{ 67}
-\KeywordTok{ENTRYPOINT}\NormalTok{ [}\StringTok{"dhcpd"}\NormalTok{, }\StringTok{"{-}f"}\NormalTok{]}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{dhcpdhcpd.conf-configuration-du-serveur-dhcp}{%
-\section{\texorpdfstring{\texttt{dhcp/dhcpd.conf}: configuration du
-serveur
-\protect\hyperlink{acronym__DHCP}{DHCP}}{dhcp/dhcpd.conf: configuration du serveur DHCP}}\label{dhcpdhcpd.conf-configuration-du-serveur-dhcp}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\ExtensionTok{allow}\NormalTok{ bootp}\KeywordTok{;}
-
-\ExtensionTok{subnet}\NormalTok{ 192.168.56.0 netmask 255.255.255.0 \{}
-    \ExtensionTok{range}\NormalTok{ 192.168.56.10 192.168.56.80}\KeywordTok{;}
-    \ExtensionTok{default{-}lease{-}time}\NormalTok{ 600}\KeywordTok{;}
-    \ExtensionTok{max{-}lease{-}time}\NormalTok{ 7200}\KeywordTok{;}
-
-\CommentTok{\#   option domain{-}name{-}servers 10.136.132.100;}
-\CommentTok{\#   option routers  192.168.56.100;}
-
-    \ExtensionTok{class} \StringTok{"pxeclient"}\NormalTok{ \{}
-        \ExtensionTok{match}\NormalTok{ if substring (option vendor{-}class{-}identifier, 0, 9) = }\StringTok{"PXEClient"}\NormalTok{;}
-        \ExtensionTok{next{-}server}\NormalTok{ 192.168.56.100}\KeywordTok{;}
-        \ExtensionTok{option}\NormalTok{ tftp{-}server{-}name }\StringTok{"192.168.56.100"}\KeywordTok{;}
-
-        \KeywordTok{if} \ExtensionTok{substring}\NormalTok{ (option vendor{-}class{-}identifier, 15, 5) = }\StringTok{"00000"} \KeywordTok{\{}
-            \ExtensionTok{option}\NormalTok{ bootfile{-}name   }\StringTok{"/boot/grub/i386{-}pc/core.0"}\KeywordTok{;}
-        \KeywordTok{\}}
-        \ExtensionTok{elsif}\NormalTok{ substring (option vendor{-}class{-}identifier, 15, 5) = }\StringTok{"00006"} \KeywordTok{\{}
-            \ExtensionTok{option}\NormalTok{ bootfile{-}name }\StringTok{"/boot/grub/i386{-}efi/core.efi"}\KeywordTok{;}
-        \KeywordTok{\}}
-        \KeywordTok{else} \KeywordTok{\{}
-         \ExtensionTok{option}\NormalTok{ bootfile{-}name }\StringTok{"/boot/grub/x86\_64{-}efi/core.efi"}\KeywordTok{;} 
-        \KeywordTok{\}}
-\NormalTok{    \}}
-
-    \ExtensionTok{class} \StringTok{"normalclient"}\NormalTok{ \{}
-        \ExtensionTok{match}\NormalTok{ if substring (option vendor{-}class{-}identifier, 0, 9) != }\StringTok{"PXEClient"}\NormalTok{;}
-\NormalTok{    \}}
-\NormalTok{\}}
-
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{grubdockerfile-configuration-docker-pour-la-compilation-de-grub}{%
-\section{\texorpdfstring{\texttt{grub/Dockerfile}: configuration
-\emph{Docker} pour la compilation de
-\protect\hyperlink{acronym__GRUB}{GRUB}}{grub/Dockerfile: configuration Docker pour la compilation de GRUB}}\label{grubdockerfile-configuration-docker-pour-la-compilation-de-grub}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{FROM}\NormalTok{ debian:buster AS build{-}stage}
-\KeywordTok{RUN}\NormalTok{ apt{-}get update \&\& apt{-}get install {-}y {-}{-}no{-}install{-}recommends \textbackslash{}}
-\NormalTok{        gcc \textbackslash{}}
-\NormalTok{        make \textbackslash{}}
-\NormalTok{        bison \textbackslash{}}
-\NormalTok{        gettext \textbackslash{}}
-\NormalTok{        binutils \textbackslash{}}
-\NormalTok{        flex \textbackslash{}}
-\NormalTok{        pkg{-}config \textbackslash{}}
-\NormalTok{        libdevmapper{-}dev \textbackslash{}}
-\NormalTok{        libfreetype6{-}dev \textbackslash{}}
-\NormalTok{        unifont \textbackslash{}}
-\NormalTok{        python \textbackslash{}}
-\NormalTok{        automake \textbackslash{}}
-\NormalTok{        autoconf}
-
-\KeywordTok{WORKDIR}\NormalTok{ /bootiful{-}grub}
-\KeywordTok{ADD}\NormalTok{ ./bootiful{-}grub ./}
-
-\KeywordTok{ARG}\NormalTok{ PLATFORM}
-\KeywordTok{ARG}\NormalTok{ TARGET}
-\KeywordTok{RUN}\NormalTok{ ./configure {-}{-}with{-}platform=$\{PLATFORM\} {-}{-}target=$\{TARGET\}}
-\KeywordTok{RUN}\NormalTok{ make}
-\KeywordTok{RUN}\NormalTok{ make install}
-
-\KeywordTok{RUN}\NormalTok{ grub{-}mknetdir {-}{-}net{-}directory=./netdir {-}{-}subdir=./boot/grub}
-
-\KeywordTok{FROM}\NormalTok{ scratch AS export{-}stage}
-\KeywordTok{COPY}\NormalTok{ {-}{-}from=build{-}stage ./bootiful{-}grub/netdir /}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{nfsdockerfile-configuration-docker-du-serveur-nfs}{%
-\section{\texorpdfstring{\texttt{nfs/Dockerfile}: configuration
-\emph{Docker} du serveur
-\protect\hyperlink{acronym__NFS}{NFS}}{nfs/Dockerfile: configuration Docker du serveur NFS}}\label{nfsdockerfile-configuration-docker-du-serveur-nfs}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{FROM}\NormalTok{ erichough/nfs{-}server}
-\KeywordTok{ADD}\NormalTok{ nfsroot.tar.gz /nfsrootsrc/}
-\KeywordTok{COPY}\NormalTok{ exports /etc/exports}
-\KeywordTok{VOLUME}\NormalTok{ /nfsroot}
-\KeywordTok{VOLUME}\NormalTok{ /nfsshared}
-\KeywordTok{ENTRYPOINT}\NormalTok{ cp {-}a nfsrootsrc/rootfs/. /nfsroot/ \&\& entrypoint.sh}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{nfsexports-configuration-des-partages-du-serveur-nfs}{%
-\section{\texorpdfstring{\texttt{nfs/exports}: configuration des
-partages du serveur
-\protect\hyperlink{acronym__NFS}{NFS}}{nfs/exports: configuration des partages du serveur NFS}}\label{nfsexports-configuration-des-partages-du-serveur-nfs}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\# /etc/exports: the access control list for filesystems which may be exported}
-\CommentTok{\#       to NFS clients.  See exports(5).}
-\CommentTok{\#}
-\CommentTok{\# Example for NFSv2 and NFSv3:}
-\CommentTok{\# /srv/homes       hostname1(rw,sync,no\_subtree\_check) hostname2(ro,sync,no\_subtree\_check)}
-\CommentTok{\#}
-\CommentTok{\# Example for NFSv4:}
-\CommentTok{\# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no\_subtree\_check)}
-\CommentTok{\# /srv/nfs4/homes  gss/krb5i(rw,sync,no\_subtree\_check)}
-\CommentTok{\#}
-\ExtensionTok{/nfsroot}\NormalTok{         *(ro,fsid=0,no\_root\_squash,no\_subtree\_check,async,insecure)}
-\ExtensionTok{/nfsshared}\NormalTok{       *(rw,fsid=1,no\_root\_squash,no\_subtree\_check,async,insecure)}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tftpdockerfile-configuration-docker-du-serveur-tftp}{%
-\section{\texorpdfstring{\texttt{tftp/Dockerfile}: configuration
-\emph{Docker} du serveur
-\protect\hyperlink{acronym__TFTP}{TFTP}}{tftp/Dockerfile: configuration Docker du serveur TFTP}}\label{tftpdockerfile-configuration-docker-du-serveur-tftp}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{FROM}\NormalTok{ alpine:3.12}
-\KeywordTok{RUN}\NormalTok{ apk add tftp{-}hpa}
-\KeywordTok{VOLUME}\NormalTok{ /tftpboot}
-\KeywordTok{EXPOSE}\NormalTok{ 69/udp}
-\KeywordTok{ENTRYPOINT}\NormalTok{ [}\StringTok{"in.tftpd"}\NormalTok{, }\StringTok{"{-}{-}foreground"}\NormalTok{, }\StringTok{"{-}{-}address"}\NormalTok{, }\StringTok{":69"}\NormalTok{, }\StringTok{"{-}{-}secure"}\NormalTok{, }\StringTok{"{-}{-}verbose"}\NormalTok{, }\StringTok{"/tftpboot"}\NormalTok{]}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tftptftpd-hpa-configuration-du-serveur-tftp}{%
-\section{\texorpdfstring{\texttt{tftp/tftpd-hpa}: configuration du
-serveur
-\protect\hyperlink{acronym__TFTP}{TFTP}}{tftp/tftpd-hpa: configuration du serveur TFTP}}\label{tftptftpd-hpa-configuration-du-serveur-tftp}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\VariableTok{TFTP\_USERNAME=}\StringTok{"tftp"}
-\VariableTok{TFTP\_DIRECTORY=}\StringTok{"/tftpboot"}
-\VariableTok{TFTP\_ADDRESS=}\StringTok{":69"}
-\VariableTok{TFTP\_OPTIONS=}\StringTok{"{-}s {-}c"}
-\VariableTok{RUN\_DAEMON=}\StringTok{"yes"}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{tftptftpbootbootgrubgrub.cfg-configuration-de-grub-servie-par-tftp}{%
-\section{\texorpdfstring{\texttt{tftp/tftpboot/boot/grub/grub.cfg}:
-configuration de \protect\hyperlink{acronym__GRUB}{GRUB} servie par
-\protect\hyperlink{acronym__TFTP}{TFTP}}{tftp/tftpboot/boot/grub/grub.cfg: configuration de GRUB servie par TFTP}}\label{tftptftpbootbootgrubgrub.cfg-configuration-de-grub-servie-par-tftp}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{set} \VariableTok{timeout=}\NormalTok{3}
-
-\ExtensionTok{insmod}\NormalTok{ part\_msdos}
-\ExtensionTok{insmod}\NormalTok{ part\_gpt}
-\ExtensionTok{insmod}\NormalTok{ isign}
-\ExtensionTok{insmod}\NormalTok{ all\_video}
-
-\ExtensionTok{isign}\NormalTok{ {-}c hepia2015 (hd0)}
-\KeywordTok{set} \VariableTok{check1=$?}
-\KeywordTok{if}\BuiltInTok{ [} \VariableTok{$check1} \OtherTok{==}\NormalTok{ 101}\BuiltInTok{ ]}\NormalTok{; }\KeywordTok{then}
-    \ExtensionTok{isign}\NormalTok{ {-}w 000000000 (hd0)}
-
-    \ExtensionTok{menuentry} \StringTok{"Local HDD"}\NormalTok{ \{}
-        \KeywordTok{set} \VariableTok{root=(}\NormalTok{hd0,1}\VariableTok{)}
-
-        \KeywordTok{if}\BuiltInTok{ [} \OtherTok{{-}e}\NormalTok{ /efi\_entrypoint}\BuiltInTok{ ]}\NormalTok{; }\KeywordTok{then}
-            \BuiltInTok{echo} \StringTok{"Reading EFI entry point from (hd0,1)/efi\_entrypoint file..."}
-            \BuiltInTok{source}\NormalTok{ /efi\_entrypoint}
-
-            \BuiltInTok{echo} \StringTok{"Chainloading to }\VariableTok{$efi\_entrypoint}\StringTok{"}
-            \ExtensionTok{chainloader} \VariableTok{$efi\_entrypoint}
-        \KeywordTok{else}
-            \BuiltInTok{echo} \StringTok{"Legacy chainloading to (hd0,1)+1..."}
-            \ExtensionTok{chainloader}\NormalTok{ +1}
-        \KeywordTok{fi}
-\NormalTok{    \}}
-\KeywordTok{fi}
-
-\ExtensionTok{menuentry} \StringTok{"Bootiful deployer"}\NormalTok{ \{}
-    \BuiltInTok{echo} \StringTok{"Loading vmlinuz..."}
-    \ExtensionTok{linux}\NormalTok{ boot/deployer/vmlinuz root=/dev/nfs nfsroot=}\VariableTok{$net\_default\_server}\NormalTok{:/nfsroot ro}
-    \ExtensionTok{initrd}\NormalTok{ boot/deployer/initrd.img}
-\NormalTok{\}}
-
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{source_ansible_run}{%
-\section{\texorpdfstring{\texttt{postdeploy/bootiful-postdeploy}: script
-de post-déploiement qui exécute les playbooks \emph{Ansible} présents
-dans un
-dossier}{postdeploy/bootiful-postdeploy: script de post-déploiement qui exécute les playbooks Ansible présents dans un dossier}}\label{source_ansible_run}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\CommentTok{\#!/bin/bash}
-
-\KeywordTok{function}\FunctionTok{ log()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{log\_message=}\StringTok{"}\VariableTok{$0}\StringTok{"}
-    \OperatorTok{\textgreater{}\&2} \BuiltInTok{echo} \StringTok{"}\VariableTok{$log\_message}\StringTok{"}
-\KeywordTok{\}}
-
-\KeywordTok{function}\FunctionTok{ fatal\_error()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{error\_message=}\StringTok{"}\VariableTok{$0}\StringTok{"}
-    \ExtensionTok{log} \StringTok{"Fatal error: }\VariableTok{$error\_message}\StringTok{"}
-
-    \ExtensionTok{log} \StringTok{"Stack trace:"}
-    \BuiltInTok{local} \VariableTok{frame=}\NormalTok{0}
-    \KeywordTok{while} \OperatorTok{\textgreater{}\&2} \BuiltInTok{caller} \VariableTok{$frame}\KeywordTok{;} \KeywordTok{do}
-        \KeywordTok{((}\NormalTok{frame++}\KeywordTok{))}
-    \KeywordTok{done}
-
-    \BuiltInTok{exit}\NormalTok{ 1}
-\KeywordTok{\}}
-
-\ExtensionTok{log} \StringTok{"Starting bootiful post{-}deployment script..."}
-\BuiltInTok{readonly} \VariableTok{playbooks\_dir=}\StringTok{"/etc/bootiful/postdeploy{-}playbooks"}
-\KeywordTok{[[} \OtherTok{{-}d} \StringTok{"}\VariableTok{$playbooks\_dir}\StringTok{"}\KeywordTok{ ]]} \KeywordTok{||} \ExtensionTok{fatal\_error} \StringTok{"playbooks directory \textquotesingle{}}\VariableTok{$playbooks\_dir}\StringTok{\textquotesingle{} not found."}
-
-\BuiltInTok{readonly} \VariableTok{playbook\_files=}\StringTok{"}\VariableTok{$()}\StringTok{"}
-
-\KeywordTok{if [[} \OtherTok{{-}z} \StringTok{"}\VariableTok{$playbook\_files}\StringTok{"}\KeywordTok{ ]]}\NormalTok{; }\KeywordTok{then}
-    \ExtensionTok{log} \StringTok{"no story found in directory \textquotesingle{}}\VariableTok{$playbooks\_dir}\StringTok{\textquotesingle{}. Exiting."}
-    \BuiltInTok{exit}\NormalTok{ 0}
-\KeywordTok{fi}
-
-\FunctionTok{run\_playbook()} \KeywordTok{\{}
-    \BuiltInTok{local}\NormalTok{ {-}r }\VariableTok{playbook\_file=}\StringTok{"}\VariableTok{$0}\StringTok{"}
-    \ExtensionTok{log} \StringTok{"Executing playbook file \textquotesingle{}}\VariableTok{$playbook\_file}\StringTok{\textquotesingle{}..."}
-\NormalTok{    [[ }\ExtensionTok{{-}f} \StringTok{"}\VariableTok{$playbook\_file}\StringTok{"}\NormalTok{ ]] }\KeywordTok{||} \ExtensionTok{fatal\_error} \StringTok{"playbook file }\VariableTok{$playbook\_file}\StringTok{ not found."}
-
-    \ExtensionTok{ansible{-}playbook} \KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}{-}connection}\NormalTok{=local }\KeywordTok{\textbackslash{}}
-        \ExtensionTok{{-}{-}inventory}\NormalTok{=127.0.0.1, }\KeywordTok{\textbackslash{}}
-        \StringTok{"}\VariableTok{$playbook\_file}\StringTok{"} \KeywordTok{\textbackslash{}}
-        \KeywordTok{||} \ExtensionTok{fatal\_error} \StringTok{"error while executing playbook file "}
-
-    \ExtensionTok{log} \StringTok{"Execution of playbook file \textquotesingle{}}\VariableTok{$playbook\_file}\StringTok{\textquotesingle{} successful."}
-\KeywordTok{\}}
-\BuiltInTok{export}\NormalTok{ {-}f }\VariableTok{run\_playbook}
-
-\CommentTok{\# shellcheck disable=SC2016 \# we do not want to expand $1 in bash command}
-\FunctionTok{find} \StringTok{"}\VariableTok{$playbooks\_dir}\StringTok{"}\NormalTok{ {-}maxdepth 1 {-}type f {-}name }\StringTok{\textquotesingle{}*.yml\textquotesingle{}}\NormalTok{ {-}print0 }\KeywordTok{|}
-    \FunctionTok{sort}\NormalTok{ {-}z }\KeywordTok{|}
-    \FunctionTok{xargs}\NormalTok{ {-}n1 {-}0 bash {-}c }\StringTok{$\textquotesingle{}trap }\DataTypeTok{\textbackslash{}\textquotesingle{}}\StringTok{[[ $? == 0 ]] || exit 255}\DataTypeTok{\textbackslash{}\textquotesingle{}}\StringTok{ EXIT; run\_playbook "$1"\textquotesingle{}}\NormalTok{ {-}{-}}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{source_ansible_init}{%
-\section{\texorpdfstring{\texttt{postdeploy/bootiful-postdeploy.service}:
-configuration de l'unité \emph{Systemd} pour exécuter des scripts de
-post-déploiement sur un
-client}{postdeploy/bootiful-postdeploy.service: configuration de l'unité Systemd pour exécuter des scripts de post-déploiement sur un client}}\label{source_ansible_init}}
-
-\begin{Shaded}
-\begin{Highlighting}[]
-\KeywordTok{[Unit]}
-\DataTypeTok{Description}\OtherTok{=}\StringTok{Runs bootiful post{-}deployment script }\KeywordTok{on}\StringTok{ boot}
-\DataTypeTok{After}\OtherTok{=}\StringTok{network.target}
-
-\KeywordTok{[Service]}
-\DataTypeTok{ExecStart}\OtherTok{=}\StringTok{/usr/local/bin/bootiful{-}postdeploy}
-\DataTypeTok{Type}\OtherTok{=}\StringTok{oneshot}
-
-\KeywordTok{[Install]}
-\DataTypeTok{WantedBy}\OtherTok{=}\StringTok{multi{-}user.target}
-\end{Highlighting}
-\end{Shaded}
-
-\hypertarget{refs}{}
-\begin{cslreferences}
-\leavevmode\hypertarget{ref-venkatesh_remote_imaging}{}%
-\textbf{1}. VENKATESH, Abhilash. Remote imaging. GitLab. {[}en~ligne{]}.
-{[}Consulté~le~16~août~2020{]}. Disponible à l'adresse~:
-\url{https://githepia.hesge.ch/abhilash.venkates/remote-imaging}
-\end{cslreferences}
-
-\backmatter
-\end{document}