#!/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 || "${3:0:1}" == "-" ]]; 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}" "${parametre}" shift if [[ ${temoin_c} -ne 1 ]]; then # :: 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 : ::." 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 : ::." 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 : ::." 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}" "${parametre}" 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}" "${parametre}" 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}" "${parametre}" echo "disque parametre=${parametre}" # Debogage shift # |(|):(raw|qcow2):) 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 : |(|):(raw|qcow2):)." 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 : |(|):(raw|qcow2):)." 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 : |(|):(raw|qcow2):)." 5 fi commandes_a_executer+=( "nouvMV disque ${disque_nom} ${disque_format} ${disque_capacite}") ;; "-i") # Iso echo "iso" # Debogage parametre="${2}" presenceParametre "$#" "${1}" "${parametre}" echo "iso parametre=${parametre}" # Debogage shift commandes_a_executer+=( "nouvMV iso ${1}") ;; '-r') # Reseau echo "reseau" # Debogage parametre="${2}" presenceParametre "$#" "${1}" "${parametre}" echo "reseau parametre=${parametre}" # Debogage shift # Interface réseau simple : ## :(virtio|e1000): # :(virtio|e1000):n # # Interface réseau dans un pont ## :(virtio|e1000):o:: # :(virtio|e1000):o::n # # Interface réseau dans un pont avec gestion des VLAN # :(virtio|e1000):o::o:(t:|a:) # :(virtio|e1000):(n|o::(n|o:(t:|a:))) # 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 : :(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 : :(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 : :(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:(virtio|e1000):n\n\tAvec pont :\n\t\t:(virtio|e1000):o::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 : :(virtio|e1000):o::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:(virtio|e1000):o::n\n\tAvec VLAN :\n\t\t:(virtio|e1000):o::o:(t:|a:)" 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 : :(virtio|e1000):o::o:(t:|a:)" 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 : :(virtio|e1000):o::o:(t:|a:).\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 : :(virtio|e1000):o::o:(t:|a:).\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 : :(virtio|e1000):o::o:(t:|a:)\n" ;; esac ;; *) die "${reseau_activ_8021q} n'est pas une valeur connue.\nVoici les deux syntaxes minimum posisbles : \n\tSans VLAN :\n\t\t:(virtio|e1000):o::n\n\tAvec VLAN :\n\t\t:(virtio|e1000):o::o:(t:|a:)" 5 ;; esac ;; *) die "${reseau_activ_pont} n'est pas une valeur connue.\nVoici les deux syntaxes minimum posisbles : \n\tSans pont :\n\t\t:(virtio|e1000):n\n\tAvec pont :\n\t\t:(virtio|e1000):o::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}" "${parametre}" 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}" "${parametre}" shift # (gtk|(spice:(|):(|unix)[:])) 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:(|):(|unix)[:]))." 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:(|):(|unix)[:]))." 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:(|):(|unix)[:]))." 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)::))." 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}" "${parametre}" 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