diff --git a/README.md b/README.md index e6bb7586a4d58518bc340b587317971c9aab5099..68e4cfa76ba1b0ab7d5bc142b965204787b94688 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,34 @@ # Bootiful - \ No newline at end of file + + +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}