#!/bin/bash

#set -x

base_chemin_mv="/tmp/ramdisk/qemu-adm"
bin_qemu="/usr/bin/qemu-system-x86_64"
bin_qemu_img="/usr/bin/qemu-img"
chemin_services_demons="/usr/local/etc/systemd/system"
chemin_services_production="/etc/systemd/system"
nom_script=$(basename $0)
nom_complet_script="$(dirname $0)/${nom_script}"

die()
{
	echo -e "\033[0;31m${1}\033[0m" 1>&2; exit ${2};
}

verifMVExiste()
{
	if [ -e "${base_chemin_mv}/${nom_fichier_mv}" ]; then
		die "Le répertoire de la machine virtuelle ${base_chemin_mv}/${nom_fichier_mv} existe déjà." 4
	fi
}

initEnv()
{
	echo "initEnv" # Debogage
	local l_option=${1}
	echo "l_option=${l_option}" # Debogage
	shift
	case "${l_option}" in
		"sousvolume")
			echo "initEnv - sousvolume" # Debogage
			case "${1}" in
				"btrfs"|"BTRFS")
					echo "initEnv - sousvolume - BTRFS" # Debogage
					btrfs subvolume create ${base_chemin_mv}
					if [[ $? -gt 0 ]]; then
						die "La création du sous-volume dans le système de fichier cible n'est pas possible." 7
					fi
			esac
			;;
		"repMV")
			mkdir -p ${base_chemin_mv}
			;;
	esac
}

nouvMV()
{
	local l_option=${1}
	echo "l_option=${l_option}" # Debogage
	shift
	case "${l_option}" in
		"nom")
			echo "-name ${1} \\" > ${chemin_mv}
			;;
		"cpu")
			echo "-cpu ${1} -smp cores=${2},threads=${3},sockets=1 \\" >> ${chemin_mv}
			;;
		"memoire")
			echo "-m ${1} \\" >> ${chemin_mv}
			;;
		"bios")
			case "${1}" in
				"OVMF")
					cp /usr/share/ovmf/OVMF.fd ${base_chemin_mv}/OVMF.fd
					echo "-drive if=pflash,format=raw,file=${base_chemin_mv}/OVMF.fd \\" >> ${chemin_mv}
					;;
			esac
			;;
		"disque")
			echo "${2}"
			if [[ ! -z ${2} ]]; then
				if [[ ! -f ${bin_qemu_img} ]]; then
					die "Le paquet qemu-utils n'est pas installé." 6
				fi
				echo "Création du disque..." # Debogage
				qemu-img create -f ${2} ${1} ${3}
			fi
			echo "-drive file=${1},if=virtio \\" >> ${chemin_mv}
			;;
		"iso")
			echo "-cdrom ${1} \\" >> ${chemin_mv}
			;;
		"reseau")
			if [[ "${4}" != "faux" ]]; then
				echo "#PONT=${4}" >> ${chemin_mv}
				if [[ "${5}" == "n" ]]; then
					echo "#VLAN=0" >> ${chemin_mv}
				fi
			fi
			case "${6}" in
				"a")
					echo "#VLAN=${7}" >> ${chemin_mv}
					;;
				"t")
					echo "#8021Q=${7}" >> ${chemin_mv}
					;;
			esac
			if [[ "${4}" != "faux" ]]; then
				echo "#INTERFACE=${1}" >> ${chemin_mv}
			fi

			echo "-device ${2},netdev=${1} -netdev tap,id=${1},ifname=${1},script=no,downscript=no \\" >> ${chemin_mv}
			;;
		"kvm")
			echo "-enable-kvm \\" >> ${chemin_mv}
			;;
		"series")
			echo "-serial mon:stdio \\" >> ${chemin_mv}
			;;
		"spice")
			if [[ "${3}" != "faux" ]]; then
				echo "-object secret,id=spice-mdp,data=${4} -spice addr=${1},port=${2},password-secret=spice-mdp \\" >> ${chemin_mv}
			else
				echo "-spice addr=${1},port=${2},disable-ticketing=on \\" >> ${chemin_mv}
			fi
			;;
		"gtk")
			echo "-vga virtio -display sdl,gl=on \\" >> ${chemin_mv}
			;;
		"ecran")
			if [[ ${1} == "faux" ]]; then
				echo "-display none \\" >> ${chemin_mv}
			fi
			;;
		"parametres")
			echo "$@ \\" >> ${chemin_mv}
			;;
	esac
}

execCmd()
{
	#verifEnv
	liste_executions=("$@")
	for ((id_commande=0 ; "${#liste_executions[*]}" - "${id_commande}"; id_commande++)); do
		${liste_executions["${id_commande}"]}
	done
}

confInteractive()
{
	echo "confInteractive" # Debogage
}

presenceParametre()
{
	echo "presenceParametre" # Debogage
	local l_nombre_arguments="${1}"
	local l_nom_option="${2}"
	local l_nombre_parametres=${l_nombre_arguments}-1 # On soustrait l'option du nombre d'arguments resultant le nombre de parametres
	if [[ "${l_nombre_parametres}" -eq 0 ]]; then
		die "L'option ${l_nom_option} n'a pas de paramètre." 5
	fi
}

creeMV()
{
	localiserMV ${1}
	commandes_a_executer+=("nouvMV nom ${nom_mv}")
	shift # On retire le nom de la machine virtuelle passé en argument
	echo 1 "$#" # Debogage
	while [[ $# -gt 0 ]]; do
		case "${1}" in
			"-c") # Cpu (requis)
				echo "cpu" # Debogage
				parametre="${2}"
				echo "cpu parametre=${parametre}" # Debogage
				presenceParametre "$#" "$1"
				shift
				if [[ ${temoin_c} -ne 1 ]]; then
					# <type CPU>:<nombres cœurs CPU>:<nombre files d'execution>

					cpu_type=$( echo ${1} | awk -F: '{print $1}' )
					echo "${cpu_type}" # Debogage
					if [[ -z "${cpu_type}" ]]; then
						die "Le type de CPU n'est pas renseigné.\nSyntaxe attendue : <type CPU>:<nombres cœurs CPU>:<nombre files d'execution>." 5
					fi

					cpu_nombre_de_coeurs=$( echo ${1} | awk -F: '{print $2}' )
					echo "${cpu_nombre_de_coeurs}" # Debogage
					if [[ -z "${cpu_nombre_de_coeurs}" ]]; then
						die "Le nombre de cœurs n'est pas renseigné.\nSyntaxe attendue : <type CPU>:<nombres cœurs CPU>:<nombre files d'execution>." 5
					fi

					cpu_nombre_de_files_d_execution=$( echo ${1} | awk -F: '{print $3}' )
					echo "${cpu_nombre_de_files_d_execution}" # Debogage
					if [[ -z "${cpu_nombre_de_files_d_execution}" ]]; then
						die "Le nombre de files d'execution n'est pas renseigné.\nSyntaxe attendue : <type CPU>:<nombres cœurs CPU>:<nombre files d'execution>." 5
					fi

					commandes_a_executer+=("nouvMV cpu ${cpu_type} ${cpu_nombre_de_coeurs} ${cpu_nombre_de_files_d_execution}")
					temoin_c=1
				else
					die "L'option ${1} a déjà été renseignée." 3
				fi
				;;
			"-m") # Memoire (requis)
				echo "memoire" # Debogage
				parametre="${2}"
				echo "memoire parametre=${parametre}" # Debogage
				presenceParametre "$#" "$1"
				shift
				if [[ ${temoin_m} -ne 1 ]]; then
					commandes_a_executer+=( "nouvMV memoire ${1}")
					temoin_m=1
				else
					die "L'option ${1} a déjà été renseignée." 3
				fi
				;;
			"-b") # Bios
				echo "bios" # Debogage
				parametre="${2}"
				echo "bios parametre=${parametre}" # Debogage
				presenceParametre "$#" "$1"
				shift
				if [[ ${temoin_b} -ne 1 ]]; then
					case ${1} in
						"ovmf"|"OVMF")
							if [[ ! -f "/usr/share/ovmf/OVMF.fd" ]]; then
								die "Le paquet ovmf n'est pas installé." 6
							fi
							commandes_a_executer+=( "nouvMV bios $(echo ${1} | tr '[:lower:]' '[:upper:]')")
							;;
					esac
					temoin_b=1
				else
					die "L'option ${1} a déjà été renseignée." 3
				fi
				;;
			"-d") # Disque
				echo "disque" # Debogage
				parametre="${2}"
				presenceParametre "$#" "$1"
				echo "disque parametre=${parametre}" # Debogage
				shift

				# <chemin disque>|(<chemin disque>|<nom disque>):(raw|qcow2):<capacité>)

				disque_nom=$( echo ${1} | awk -F: '{print $1}' )
				echo "disque_nom=${disque_nom}" # Debogage
				if [[ -z "${disque_nom}" ]]; then
					die "Le disque n'est pas renseigné.\nSyntaxe attendue : <chemin disque>|(<chemin disque>|<nom disque>):(raw|qcow2):<capacité>)." 5
				fi
				if [[ "$(dirname ${1})" == "." ]];then
					disque_nom="${base_chemin_mv}/${disque_nom}"
				fi
				

				disque_format=$( echo ${1} | awk -F: '{print $2}' )
				echo "disque_format=${disque_format}" # Debogage
				if [[ -z "${disque_format}" && "$(dirname ${1})" == "." ]]; then
					die "Le format du disque n'est pas renseigné.\nSyntaxe attendue : <chemin disque>|(<chemin disque>|<nom disque>):(raw|qcow2):<capacité>)." 5
				fi

				disque_capacite=$( echo ${1} | awk -F: '{print $3}' )
				echo "disque_capacite=${disque_capacite}" # Debogage
				if [[ -z "${disque_capacite}" && "$(dirname ${1})" == "." ]]; then
					die "La capacité du disque n'est pas renseigné.\nSyntaxe attendue : <chemin disque>|(<chemin disque>|<nom disque>):(raw|qcow2):<capacité>)." 5
				fi

				commandes_a_executer+=( "nouvMV disque ${disque_nom} ${disque_format} ${disque_capacite}")
				;;
			"-i") # Iso
				echo "iso" # Debogage
				parametre="${2}"
				presenceParametre "$#" "$1"
				echo "iso parametre=${parametre}" # Debogage
				shift
				commandes_a_executer+=( "nouvMV iso ${1}")
				;;
			'-r') # Reseau
				echo "reseau" # Debogage
				parametre="${2}"
				presenceParametre "$#" "$1"
				echo "reseau parametre=${parametre}" # Debogage
				shift
				
				# Interface réseau simple :
				##	<nom interface>:(virtio|e1000):<activation pont>
				# 	<nom interface>:(virtio|e1000):n
				#
				# Interface réseau dans un pont
				##	<nom interface>:(virtio|e1000):o:<nom pont>:<activation 8021q>
				# 	<nom interface>:(virtio|e1000):o:<nom pont>:n
				#
				# Interface réseau dans un pont avec gestion des VLAN
				# 	<nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>)

				# <nom interface>:(virtio|e1000):(n|o:<nom pont>:(n|o:(t:<VIDs>|a:<VID>)))
				
				# Initialisation des variables
				reseau_nom_interface="faux"
				reseau_type="faux"
				reseau_activ_pont="faux"
				reseau_nom_pont="faux"
				reseau_activ_8021q="faux"
				reseau_mode_8021q="faux"
				reseau_vid="faux"

				reseau_nom_interface=$( echo ${1} | awk -F: '{print $1}' )
				if [[ -z "${reseau_nom_interface}" ]]; then
					die "L'interface réseau n'est pas renseigné.\nSyntaxe minimum attendue : <nom interface>:(virtio|e1000):n." 5
				fi

				reseau_type=$( echo ${1} | awk -F: '{print $2}' )
				if [[ -z "${reseau_type}" ]]; then
					die "Le type d'interface réseau n'est pas renseigné.\nSyntaxe minimum attendue : <nom interface>:(virtio|e1000):n." 5
				fi
				case ${reseau_type} in
					"virtio")
						reseau_type="virtio-net-pci"
						;;
					"e1000")
						;;
					*)
						die "Le type d'interface réseau n'a pas une valeur connue.\nSyntaxe minimum attendue : <nom interface>:(virtio|e1000):n." 5
						;;
				esac
				
				reseau_activ_pont=$( echo ${1} | awk -F: '{print $3}' )
				echo "reseau_activ_pont=${reseau_activ_pont}" # Debogage
				if [[ -z "${reseau_activ_pont}" ]]; then
					die "L'activation du pont n'est pas renseigné.\nVoici les deux syntaxes minimum posisbles : \n\tSans pont :\n\t\t<nom interface>:(virtio|e1000):n\n\tAvec pont :\n\t\t<nom interface>:(virtio|e1000):o:<nom pont>:n" 5
				fi
				case ${reseau_activ_pont} in
					"n"|"N")
						;;
					"o"|"O")
						reseau_nom_pont=$( echo ${1} | awk -F: '{print $4}' )
						if [[ -z "${reseau_nom_pont}" ]]; then
							die "Le nom du pont réseau n'est pas renseigné.\nSyntaxe minimum attendue : <nom interface>:(virtio|e1000):o:<nom pont>:n." 5
						fi

						reseau_activ_8021q=$( echo ${1} | awk -F: '{print $5}' )
						if [[ -z "${reseau_activ_8021q}" ]]; then
							die "L'activation du VLAN n'est pas renseigné.\nVoici les deux syntaxes minimum posisbles :\n\tSans VLAN :\n\t\t<nom interface>:(virtio|e1000):o:<nom pont>:n\n\tAvec VLAN :\n\t\t<nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>)" 5
						fi
						case ${reseau_activ_8021q} in
							"n"|"N")
								;;
							"o"|"O")
								reseau_mode_8021q=$( echo ${1} | awk -F: '{print $6}' )
								if [[ -z "${reseau_mode_8021q}" ]]; then
									die "Le mode du 802.1Q n'est pas renseigné.\nSyntaxe attendue : <nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>)" 5
								fi
								case ${reseau_mode_8021q} in
									"t"|"T")
										reseau_vid=$( echo ${1} | awk -F: '{print $7}' )
										echo "reseau_vid=${reseau_vid}" # Debogage
										if [[ -z "${reseau_vid}" ]]; then
											die "Les identifiants de VLAN ne sont pas renseignés.\nSyntaxe attendue : <nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>).\nExemple pour un accès via trunk aux VLAN 10 et 20 :\n\t qemu-adm [...] -r tap0:virtio:o:br0:o:t:10,20" 5
										fi
										for vid in $(echo $reseau_vid | sed 's/,/ /g'); do
											echo "vid=${vid}" # Debogage
											if [[ !(${vid} -ge 1 && ${vid} -le 4096) ]]; then
												die "${vid} n'est pas une valeur correcte. L'attendu est un ou plusieurs chiffres comprise entre 1 et 4096 séparé par une virgule.\nExemple pour un accès via trunk aux VLAN 10 et 20 :\n\t qemu-adm [...] -r tap0:virtio:o:br0:o:t:10,20"
											fi
										done
										;;
									"a"|"A")
										reseau_vid=$( echo ${1} | awk -F: '{print $7}' )
										if [[ -z "${reseau_vid}" ]]; then
											die "L'identifiant de VLAN n'est pas renseignés.\nSyntaxe attendue : <nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>).\nExemple pour un accès au VLAN 10 :\n\t qemu-adm [...] -r tap0:virtio:o:br0:o:a:10" 5
										fi
										if [[ ! "${reseau_vid}" =~ ^[0-9]+$ ]]; then
											die "${reseau_vid} n'est pas une valeur correcte. L'attendu est un chiffre compris entre 1 et 4096.\nExemple pour un accès au VLAN 10 :\n\t qemu-adm [...] -r tap0:virtio:o:br0:o:a:10"
										fi
										if [[ !(${reseau_vid} -ge 1 && ${reseau_vid} -le 4096) ]]; then
											die "${reseau_vid} n'est pas une valeur correcte. L'attendu est un chiffre compris entre 1 et 4096.\nExemple pour un accès au VLAN 10 :\n\t qemu-adm [...] -r tap0:virtio:o:br0:o:a:10"
										fi
										;;
									*)
										die "${reseau_mode_8021q} n'est pas une valeur connue.\nSyntaxe attendue : <nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>)\n"
										;;
								esac
								;;
							*)
								die "${reseau_activ_8021q} n'est pas une valeur connue.\nVoici les deux syntaxes minimum posisbles : \n\tSans VLAN :\n\t\t<nom interface>:(virtio|e1000):o:<nom pont>:n\n\tAvec VLAN :\n\t\t<nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>)" 5
								;;
						esac
						;;

					*)
						die "${reseau_activ_pont} n'est pas une valeur connue.\nVoici les deux syntaxes minimum posisbles : \n\tSans pont :\n\t\t<nom interface>:(virtio|e1000):n\n\tAvec pont :\n\t\t<nom interface>:(virtio|e1000):o:<nom pont>:n" 5
						;;
				esac

				commandes_a_executer+=( "nouvMV reseau ${reseau_nom_interface} ${reseau_type} ${reseau_activ_pont} ${reseau_nom_pont} ${reseau_activ_8021q} ${reseau_mode_8021q} ${reseau_vid}")
				echo "nouvMV reseau ${reseau_nom_interface} ${reseau_type} ${reseau_activ_pont} ${reseau_nom_pont} ${reseau_activ_8021q} ${reseau_mode_8021q} ${reseau_vid}" # Debogage
				;;
			# "-p") # VFIO PCI
			# 	echo "pci" # Debogage
			# 	# -device vfio-pci,host=0b:10.0,id=hostdev0,bus=pci.0,addr=0xa
			# 	shift
			# 	;;	
			"-S") # Sous-volume
				echo "sous-volume" # Debogage
				parametre="${2}"
				echo "sous-volume parametre=${parametre}" # Debogage
				presenceParametre "$#" "$1"
				shift
				if [[ ${temoin_S} -ne 1 ]]; then
					case ${1} in
						"btrfs"|"BTRFS")
							if [[ ! $(command -v btrfs) ]]; then
								die "Le paquet btrfs-progs n'est pas installé." 6
							fi
							commandes_init_a_executer+=( "initEnv sousvolume ${1}" )
							;;
					esac
					temoin_S=1
				else
					die "L'option ${1} a déjà été renseignée." 3
				fi
				;;
			"-k") # KVM
				echo "KVM" # Debogage
				if [[ ${temoin_k} -ne 1 ]]; then
					commandes_a_executer+=( "nouvMV kvm")
					temoin_k=1
				else
					die "L'option ${1} a déjà été renseignée." 3
				fi
				;;
			"-s") # Séries
				echo "Séries" # Debogage
				if [[ ${temoin_s} -ne 1 ]]; then
					commandes_a_executer+=( "nouvMV series")
					temoin_s=1
				else
					die "L'option ${1} a déjà été renseignée." 3
				fi
				;;
			"-a") # Affichage
				echo "Affichage" # Debogage
				presenceParametre "$#" "$1"
				shift

				# (gtk|(spice:(<adresse ecoute>|<chemin socket>):(<tcp port ecoute>|unix)[:<mot de passe>]))

				affichage_protocole=$( echo ${1} | awk -F: '{print $1}' )
				if [[ -z "${affichage_protocole}" ]]; then
					die "Le protocole de gestion de l'affichage n'est pas renseigné.\nSyntaxe attendue : (gtk|(spice:(<adresse ecoute>|<chemin socket>):(<tcp port ecoute>|unix)[:<mot de passe>]))." 5
				fi
				case ${affichage_protocole} in
					"spice"|"SPICE")
						affichage_spice_adresse_unix=$( echo ${1} | awk -F: '{print $2}' )
						if [[ -z "${affichage_spice_adresse_unix}" ]]; then
							die "L'adresse IPv4 ou le chemin unix n'est pas renseigné.\nSyntaxe attendue : (gtk|(spice:(<adresse ecoute>|<chemin socket>):(<tcp port ecoute>|unix)[:<mot de passe>]))." 5
						fi

						affichage_spice_port_unix=$( echo ${1} | awk -F: '{print $3}' )
						if [[ -z "${affichage_spice_port_unix}" ]]; then
							die "Le port ou le mot clé unix n'est pas renseigné.\nSyntaxe attendue : (gtk|(spice:(<adresse ecoute>|<chemin socket>):(<tcp port ecoute>|unix)[:<mot de passe>]))." 5
						fi

						affichage_spice_activ_mot_de_passe="vrai"
						affichage_spice_mot_de_passe=$( echo ${1} | awk -F: '{print $4}' )
						if [[ -z "${affichage_spice_mot_de_passe}" ]]; then
							affichage_spice_activ_mot_de_passe="faux"
						fi

						commandes_a_executer+=( "nouvMV spice ${affichage_spice_adresse_unix} ${affichage_spice_port_unix} ${affichage_spice_activ_mot_de_passe} ${affichage_spice_mot_de_passe}")
						;;
					"gtk"|"GTK")
						commandes_a_executer+=( "nouvMV gtk")
						;;
					"aucun"|"AUCUN")
						commandes_a_executer+=( "nouvMV ecran faux")
						;;
					*)
						die "${affichage_protocole} n'est pas une valeur connue.\nSyntaxe attendue : (gtk|((vnc|spice):<adresse ecoute>:<port ecoute>))." 5
						;;
				esac

				;;
			# "-f") # Force
			# 	# Permet d'eviter la demande de confirmation de création
			# 	echo "force" # Debogage
			# 	if [[ ${temoin_f} -ne 1 ]]; then
			# 		#commandes_a_executer+=( "nouvMV ${nom_mv}")
			# 		temoin_s=f
			# 	else
			# 		die "L'option ${1} a déjà été renseignée." 3
			# 	fi
			# 	;;
			'-h') # Aide
					usage "cree"
					exit 0
				;;
			'--') # Autre parametres (champ libre)
				echo "parametres" # Debogage
				presenceParametre "$#" "$1"
				shift
				parametres="$@"
				echo "parametres=${parametres}" # Debogage
				commandes_a_executer+=( "nouvMV parametres $parametres")
				shift $#
				;;
			*) # Autre
				usage "cree"
				;;
		esac
		shift
	done
	if [[ ${temoin_c} -ne 1 || ${temoin_m} -ne 1 ]]; then
		die "Les parametres -c et -m sont obligatoires." 2
	fi
	#verifMVExiste ${nom_mv}
	commandes_init_a_executer+=( "initEnv repMV" )
	execCmd "${commandes_init_a_executer[@]}"
	execCmd "${commandes_a_executer[@]}"
	echo "########## FICHIER ##########" # Debogage
	cat ${chemin_mv} # Debogage
}

genCmdIntRzo(){
	# Création d'une interface simple
	if [[ "${pont_init}" -eq 1 && "${vlan_init}" -eq 2 && "${interface_init}" -eq 1 ]]; then
		# Commandes à executer au demarrage
		commandes_a_executer_on+=( "ip tuntap add ${interface} mode tap" )
		commandes_a_executer_on+=( "ip link set ${interface} up" )
		commandes_a_executer_on+=( "ip link set ${interface} master ${pont}" )
		# Commandes à exectuer à l'arrêt
		commandes_a_executer_off+=( "ip link del ${interface}" )

		# Réinitialisation des variables témoins
		pont_init=0
		vlan_init=0
		interface_init=0

	# Création d'une interface non étiqueté (access)
	elif [[ "${pont_init}" -eq 1 && "${vlan_init}" -eq 1 && "${interface_init}" -eq 1 ]]; then
		# Commandes à executer au demarrage
		commandes_a_executer_on+=( "ip tuntap add ${interface} mode tap" )
		commandes_a_executer_on+=( "ip link set ${interface} up" )
		commandes_a_executer_on+=( "ip link set ${interface} master ${pont}" )
		commandes_a_executer_on+=( "bridge vlan del dev ${interface} vid 1 PVID untagged master" )
		commandes_a_executer_on+=( "bridge vlan add dev ${interface} vid ${vlan} pvid untagged master" )
		# Commandes à exectuer à l'arrêt
		commandes_a_executer_off+=( "ip link del ${interface}" )

		# Réinitialisation des variables témoins
		pont_init=0
		vlan_init=0
		interface_init=0

	# Création d'une interface étiqueté (trunk)
	elif [[ "${pont_init}" -eq 1 && "${ieee8021q_init}" -eq 1 && "${interface_init}" -eq 1 ]]; then
		commandes_a_executer_on+=( "ip tuntap add ${interface} mode tap" )
		commandes_a_executer_on+=( "ip link set ${interface} up" )
		commandes_a_executer_on+=( "ip link set ${interface} master ${pont}" )
		commandes_a_executer_on+=( "bridge vlan del dev ${interface} vid 1 PVID untagged master" )
		for ((id_label_vlan=0 ; "${nb_params_label}" - "${id_label_vlan}" ; id_label_vlan++)); do
			commandes_a_executer_on+=( "bridge vlan add dev ${interface} vid ${label_vlan[${id_label_vlan}]} tagged master" )
		done
		# Commandes à exectuer à l'arrêt
		commandes_a_executer_off+=( "ip link del ${interface}" )

		# Réinitialisation des variables témoins
		pont_init=0
		ieee8021q_init=0
		interface_init=0
		
	fi
}

# Fonction exécuté en premier. Récupère les paramètres du fichier de configuration du conteneur
recupParams(){
	verif_params=${1}
	declare -a params_int=( $(grep -B 3 "^-device" ${chemin_mv}) )
	nb_params="${#params_int[*]}"

	for ((id_param_fichier=0 ; "${nb_params}" - "${id_param_fichier}" ; id_param_fichier++)); do
		nom_param=$(echo "${params_int[${id_param_fichier}]}" | grep -v '#.*-device' | sed "s/=.*//" | sed "s/#//")
		val_param=$(echo "${params_int[${id_param_fichier}]}" | sed "s/.*=//")

		# Récupération des données d'après le fichier de configuration
		if [ "${nom_param}" == "PONT" ]; then
			if [[ ${verif_params} == "vrai" ]]; then
				if [[ $(ip link show "${val_param}" 2> /dev/null) ]]; then
					pont="${val_param}"
					pont_init=1
				else
					die "Le pont ${val_param} n'existe pas." 8
				fi
			else
				pont="${val_param}"
				pont_init=1
			fi
		elif [ "${nom_param}" == "VLAN" ]; then
			if [[ "${val_param}" =~ ^-?[0-9]+$ && "${val_param}" -ge 1 && "${val_param}" -le 4094 && $(echo -n "${val_param}" | cut -c 1) -ne 0 ]]; then
				if [[ "${pont_init}" -eq 1 ]]; then
					vlan="${val_param}"
					vlan_init=1
				else
					die "Le paramètre \"#PONT=votrePont\" est manquant dans le fichier ${chemin_mv}." 9
				fi
			elif [[ "${val_param}" -eq 0 ]]; then
				vlan_init=2
			else
				die "Le VLAN \"${val_param}\" n'est pas un entier compris entre 1 et 4094. Veuillez verifier le fichier ${chemin_mv}." 9
			fi
		elif [ "${nom_param}" == "8021Q" ]; then
			declare -a label_vlan=( $(echo ${val_param} | sed 's/,/\n/g') )
			nb_params_label="${#label_vlan[*]}"

			for ((id_label_vlan=0 ; "${nb_params_label}" - "${id_label_vlan}" ; id_label_vlan++)); do
				if [[ "${label_vlan[${id_label_vlan}]}" =~ ^-?[0-9]+$ && "${label_vlan[${id_label_vlan}]}" -ge 1 && "${label_vlan[${id_label_vlan}]}" -le 4094 && $(echo -n "${label_vlan[${id_label_vlan}]}" | cut -c 1) -ne 0 ]]; then
					if [[ "${pont_init}" -eq 1 ]]; then
						ieee8021q_init=1
					else
						die "Le paramètre \"#PONT=votrePont\" est manquant dans le fichier ${chemin_mv}." 9
					fi
				else
					die "Le tronc 802.1Q comporte un identifiant de VLAN (\"${val_param}\") qui n'est pas un entier compris entre 1 et 4094. Veuillez verifier le fichier ${chemin_mv}." 9
				fi
			done
		elif [ "${nom_param}" == "INTERFACE" ]; then
			if [[ ${verif_params} == "vrai" ]]; then
				if [[ ! $(ip link show "${val_param}" 2> /dev/null) ]]; then
					if [[ "${vlan_init}" -eq 1 || "${vlan_init}" -eq 2 || "${ieee8021q_init}" -eq 1 ]]; then
						interface="${val_param}"
						interface_init=1
					else
						die "Le paramètre \"#VLAN=votreVLAN\" est manquant dans le fichier ${chemin_mv}." 9
					fi
				elif [[ $(ls /run/network/ | sed -e "s/ifstate//g" -e "s/^.//" -e "/^$/d" -e "/^lo$/d" | grep "${val_param}" 2> /dev/null) ]]; then
					pont_init=0
					vlan_init=0
					ieee8021q_init=0
					interface_init=0
				else
					die "L'interface ${val_param} est déjà existante." 8
				fi
			else
				interface="${val_param}"
				interface_init=1
			fi
		fi

		# Génération des commandes de création des interfaces réseau du conteneur
		genCmdIntRzo
	done
}

genService(){
	echo "genService" # Debogage
	mkdir -p ${chemin_services_demons}
	echo "chemin_mv=${chemin_mv}" # Debogage
	nom_du_service="qemu-${nom_mv}-$(echo -n ${chemin_mv} | sha512sum | cut -c 1-10).service"
	cat << _EOF_ > ${chemin_services_demons}/${nom_du_service}
[Unit]
Description=Service pour la machine vituelle ${chemin_mv}
After=syslog.target
After=network.target

[Service]
RestartSec=2s
Type=simple
ExecStart=${nom_complet_script} demarre ${chemin_mv}

[Install]
WantedBy=multi-user.target
_EOF_
	echo "Le service ${chemin_services_demons}/${nom_du_service} a été crée"
	ln -sf ${chemin_services_demons}/${nom_du_service} ${chemin_services_production}/${nom_du_service}
	echo "Un lien synbolique vers ${chemin_services_production}/${nom_du_service} a été crée"
	echo -e "Si vous voulez exécuter votre machine au démarrage du système, veuillez utiliser la commande suivante :\n\t\033[01;30msystemctl enable ${nom_du_service}\033[00m"
}

usage()
{
	case ${1} in
		cree)
			echo "usage_cree" # Debogage
			# qemu-img: Invalid image size specified. You may use k, M, G, T, P or E suffixes for
			# qemu-img: kilobytes, megabytes, gigabytes, terabytes, petabytes and exabytes.
			die "" 0
			;;
		demarre)
			echo "usage_demarre" # Debogage
			die "" 0
			;;
		arret)
			echo "usage_arret" # Debogage
			die "" 0
			;;
		active)
			echo "usage_active" # Debogage
			die "" 0
			;;
		desactive)
			echo "usage_desactive" # Debogage
			die "" 0
			;;
		*)
			echo "$(tput bold)Utilisation : $(basename ${0}) {-i|-s N} [OPTION]...$(tput sgr0)" 2>&1
			echo -e "Permet de sauvegarder les sous-volumes BTRFS d'un serveur monté selon la procédure décrite par ycharbi.fr. Permet également d'effectuer un roulement des archives.\n"
			echo -e "L'option -i ou -s sont requises pour l'exécution du script. Les deux peuvent êtres utilisées simultanément.\n"
			echo -e "\n$(tput bold)Options :$(tput sgr0)"
			echo -e "L'ordre des paramètres n'a pas d'importance.\n"
			echo -e "   -i\t\tExécute un instantané des sous-volumes BTRFS répertoriés dans le fichier texte passé en paramètre (via -f ou la variable \$fichierListeSousVolumes du présent script). Les entrées de cette liste doivent êtres conformes au retour de la commande \"btrfs subvolume list /\" pour être interprétés. Toute entrée invalide est ignorée"
			echo -e "   -s N\t\tSupprime l'instantané le plus ancien de chaque entrée de la liste. Un nombre désignant le seuil maximal d'instantané à conserver doit obligatoirement être passé en paramètre. L'instantané le plus ancien au delà de cette limite sera supprimé. Par sécurité, cette option ne supprime que le plus ancien. Si vous avez beaucoup d'instantanés au dessus de votre seuil, vous devrez répeter l'opération autant de fois que nécessaire"
			echo -e "   -f\t\tPermet de spécifier le fichier listant les sous-volumes à traiter pour gérer les instantanés. Ce fichier doit contenir des entrées correspondants parfaitement avec celles retournées par la commande \"btrfs subvolume list /\" pour être traités. Cette option est facultative. Si elle n'est pas renseignée, le script utilisera le fichier spécifié dans la variable \$fichierListeSousVolumes"
			echo -e "   -h\t\tAffiche cette aide. Si passée avec d'autres options, celles-ci seront ignorées pour n'afficher que l'aide"
			echo -e "\n$(tput bold)Exemples :$(tput sgr0)"
			echo -e "Réalisation d'un instantané avec un seuil de 13 archives (l'ancienne numéro 13 sera supprimée) :\n\t${0} -i -s 13 -f /root/cpt_instents/listeSousVolumes.txt\n"
			echo -e "Peut être raccourci en :\n\t${0} -is 13 -f /root/cpt_instents/listeSousVolumes.txt"
			echo -e "\nContenu du fichier listeSousVolumes.txt :"
			echo -e "\tsystèmes/bullseye/@\n\tsystèmes/bullseye/@boot\n\ttmp/toto\n\tvar/lib/machines/web\n\tvar/lib/machines/courriel\n\tvar/lib/machines/routeur\n\tvar/lib/machines/wireguard"
			echo -e "\nLe sous-volume tmp/toto n'existant pas, cette entrée sera ignorée sans entraver l'exécution du script. Il est également possible de commenter des lignes (en les rendant invalides)."
			die ""
			;;
	esac
}

localiserMV() {
	nom_mv="$(basename ${1})"
	if [[ "$(dirname ${1})" != "." ]];then
		base_chemin_mv="$(dirname ${1})"
		nom_fichier_mv="${nom_mv}"
	else
		base_chemin_mv+="/${nom_mv}"
		nom_fichier_mv="qemu-${nom_mv}.mv"
	fi
	chemin_mv="${base_chemin_mv}/${nom_fichier_mv}"
	echo "chemin_mv=${chemin_mv}" # Debogage
	echo "nom_mv=${nom_mv}" # Debogage
	echo "base_chemin_mv=${base_chemin_mv}" # Debogage
	echo "nom_fichier_mv=${nom_fichier_mv}" # Debogage
}

demarreService() {
	systemctl daemon-reload
	systemctl start ${nom_du_service}
	echo "Verification en cours..."
	sleep 2
	systemctl is-active --quiet ${nom_du_service}
	if [[ $? -eq 0 ]]; then
		echo -e "\033[01;32mLa machine virtuelle ${nom_mv} est bien démarrée.\033[00m"
	else
		echo -e "\033[01;31mLa machine virtuelle ${nom_mv} n'a pas démarrée.\033[00m"
		journalctl --no-pager --lines=10 --output=cat -eu ${nom_du_service}
	fi
}

case ${1} in
	cree)
		echo "Créer" # Debogage
		shift # On retire l'argument "cree"
		if [[ "$#" -eq 0 ]]; then
			confInteractive
			creeMV #Ajouter les parametre sous forme de tableau
		else
			if [[ "${1}" == "-h" ]]; then
				usage "cree"
			fi
			creeMV $*
		fi
		;;

	demarre)
		echo "Démarre" # Debogage
		shift # On retire l'argument "demarre"
		if [[ "$#" -eq 0 ]]; then
			usage "demarre"
		else
			if [[ "${1}" == "-h" ]]; then
				usage "demarre"
			fi
			localiserMV ${1}
			shift
			echo 1 "$#" # Debogage
			if [[ $# -eq 0 ]]; then
				echo "Demarrage de la MV..." # Debogage
				recupParams vrai
				execCmd "${commandes_a_executer_on[@]}"
				commande_qemu=$(grep -Ev '^#|^$' ${chemin_mv} | tr -d '\n' | tr -d '\\')
				echo "${bin_qemu} ${commande_qemu}" # Debogage
				${bin_qemu} ${commande_qemu}
				execCmd "${commandes_a_executer_off[@]}"
			else
				while [[ $# -gt 0 ]]; do
					case "${1}" in
						'-d') #demon
							echo "demon" # Debogage
							if [[ ${temoin_d} -ne 1 ]]; then
								commandes_a_executer_demon+=( "genService" )
								commandes_a_executer_demon+=( "demarreService")
								temoin_d=1
							else
								die "L'option ${1} a déjà été renseignée." 3
							fi
							;;
						'-h') #aide
								usage "demarre"
								exit 0
							;;
						*) #autre
							usage "demarre"
							;;
					esac
					shift
				done
				execCmd "${commandes_a_executer_demon[@]}"
			fi
		fi
		;;

	arret)
		echo "Arrêt" # Debogage
		shift # On retire l'argument "arret"
		if [[ "${1}" == "-h" ]]; then
			usage "arret"
		fi
		localiserMV ${1}
		shift
		nom_du_service="qemu-${nom_mv}-$(echo -n ${chemin_mv} | sha512sum | cut -c 1-10).service"
		systemctl stop ${nom_du_service}
		recupParams faux
		execCmd "${commandes_a_executer_off[@]}"
		;;

	active)
		echo "Active" # Debogage
		shift # On retire l'argument "active"
		if [[ "${1}" == "-h" ]]; then
			usage "active"
		fi
		nom_mv="${1}"
		echo "nom_mv=${nom_mv}"
		;;

	desactive)
		echo "Désactive" # Debogage
		shift  # On retire l'argument "desactive"
		if [[ "${1}" == "-h" ]]; then
			usage "desactive"
		fi
		nom_mv="${1}"
		echo "nom_mv=${nom_mv}"
		;;
	
	liste)
		echo "Liste" # Debogage
		shift  # On retire l'argument "liste"
		;;

	*)
		usage
		;;
esac