You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
887 lines
32 KiB
887 lines
32 KiB
#!/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}" # Debogage
|
|
if [[ ! -z "${2}" && "${2}" =~ ^(raw|qcow2)$ ]]; 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}
|
|
else
|
|
die "Le format du disque doit être raw ou qcow2." 5
|
|
fi
|
|
if [[ "${4}" =~ ^(virtio|ide)$ ]]; then
|
|
echo "-drive file=${1},if=${4} \\" >> ${chemin_mv}
|
|
else
|
|
die "Le type du disque doit être virtio ou ide." 5
|
|
fi
|
|
;;
|
|
"iso")
|
|
echo "-cdrom ${1} \\" >> ${chemin_mv}
|
|
;;
|
|
"reseau")
|
|
if [[ "${1}" != "faux" ]]; then
|
|
if [[ "${5}" != "faux" ]]; then
|
|
echo "#PONT=${5}" >> ${chemin_mv}
|
|
if [[ "${6}" == "n" ]]; then
|
|
echo "#VLAN=0" >> ${chemin_mv}
|
|
fi
|
|
fi
|
|
case "${7}" in
|
|
"a")
|
|
echo "#VLAN=${8}" >> ${chemin_mv}
|
|
;;
|
|
"t")
|
|
echo "#8021Q=${8}" >> ${chemin_mv}
|
|
;;
|
|
esac
|
|
if [[ "${4}" != "faux" ]]; then
|
|
echo "#INTERFACE=${2}" >> ${chemin_mv}
|
|
fi
|
|
echo "-device ${3},netdev=${2} -netdev tap,id=${2},ifname=${2},script=no,downscript=no \\" >> ${chemin_mv}
|
|
else
|
|
echo "-net none \\" >> ${chemin_mv}
|
|
fi
|
|
;;
|
|
"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
|
|
# <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}" "${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
|
|
|
|
# <chemin disque>|(<chemin disque>|<nom disque>):(raw|qcow2):<capacité>:(virtio|ide))
|
|
|
|
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é>:(virtio|ide))." 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é>:(virtio|ide))." 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é>:(virtio|ide))." 5
|
|
fi
|
|
|
|
disque_type=$( echo ${1} | awk -F: '{print $4}' )
|
|
echo "disque_type=${disque_type}" # Debogage
|
|
if [[ -z "${disque_type}" && "$(dirname ${1})" == "." ]]; then
|
|
die "Le type du disque n'est pas renseigné.\nSyntaxe attendue : <chemin disque>|(<chemin disque>|<nom disque>):(raw|qcow2):<capacité>:(virtio|ide))." 5
|
|
fi
|
|
|
|
commandes_a_executer+=( "nouvMV disque ${disque_nom} ${disque_format} ${disque_capacite} ${disque_type}")
|
|
;;
|
|
"-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
|
|
|
|
# Aucune interface réseau (désactive le réseau par défaut de Qemu si non spécifié par l'utilisateur) :
|
|
# n
|
|
# Interface réseau simple :
|
|
## (n|o:<nom interface>:(virtio|e1000):<activation pont>)
|
|
# (n|o:<nom interface>:(virtio|e1000):n)
|
|
#
|
|
# Interface réseau dans un pont
|
|
## (n|o:<nom interface>:(virtio|e1000):o:<nom pont>:<activation 8021q>)
|
|
# (n|o:<nom interface>:(virtio|e1000):o:<nom pont>:n)
|
|
#
|
|
# Interface réseau dans un pont avec gestion des VLAN
|
|
# (n|o:<nom interface>:(virtio|e1000):o:<nom pont>:o:(t:<VIDs>|a:<VID>))
|
|
# (n|o:<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_activ_interface=$( echo ${1} | awk -F: '{print $1}' )
|
|
if [[ -z "${reseau_activ_interface}" ]]; then
|
|
die "L'activation du réseau n'est pas renseigné.\nSpécifiez (n|N) pour désactiver le réseau sur la machine virtuelle ou (o|O) pour créer une interface réseau.\nVoici les deux syntaxes minimales posisbles : \n\tSans réseau :\n\t\tn\n\tAvec réseau :\n\t\to:<nom interface>:(virtio|e1000):n." 5
|
|
fi
|
|
case ${reseau_activ_interface} in
|
|
"n"|"N")
|
|
reseau_activ_interface="faux"
|
|
;;
|
|
"o"|"O")
|
|
reseau_nom_interface=$( echo ${1} | awk -F: '{print $2}' )
|
|
if [[ -z "${reseau_nom_interface}" ]]; then
|
|
die "L'interface réseau n'est pas renseigné.\nSyntaxe minimale attendue : o:<nom interface>:(virtio|e1000):n." 5
|
|
fi
|
|
|
|
reseau_type=$( echo ${1} | awk -F: '{print $3}' )
|
|
if [[ -z "${reseau_type}" ]]; then
|
|
die "Le type d'interface réseau n'est pas renseigné.\nSyntaxe minimale attendue : o:<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 minimale attendue : o:<nom interface>:(virtio|e1000):n." 5
|
|
;;
|
|
esac
|
|
|
|
reseau_activ_pont=$( echo ${1} | awk -F: '{print $4}' )
|
|
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 minimale posisbles : \n\tSans pont :\n\t\to:<nom interface>:(virtio|e1000):n\n\tAvec pont :\n\t\to:<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 $5}' )
|
|
if [[ -z "${reseau_nom_pont}" ]]; then
|
|
die "Le nom du pont réseau n'est pas renseigné.\nSyntaxe minimale attendue : o:<nom interface>:(virtio|e1000):o:<nom pont>:n" 5
|
|
fi
|
|
|
|
reseau_activ_8021q=$( echo ${1} | awk -F: '{print $6}' )
|
|
if [[ -z "${reseau_activ_8021q}" ]]; then
|
|
die "L'activation du VLAN n'est pas renseigné.\nVoici les deux syntaxes minimales posisbles :\n\tSans VLAN :\n\t\to:<nom interface>:(virtio|e1000):o:<nom pont>:n\n\tAvec VLAN :\n\t\to:<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 $7}' )
|
|
if [[ -z "${reseau_mode_8021q}" ]]; then
|
|
die "Le mode du 802.1Q n'est pas renseigné.\nSyntaxe attendue : o:<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 $8}' )
|
|
echo "reseau_vid=${reseau_vid}" # Debogage
|
|
if [[ -z "${reseau_vid}" ]]; then
|
|
die "Les identifiants de VLAN ne sont pas renseignés.\nSyntaxe attendue : o:<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 $8}' )
|
|
if [[ -z "${reseau_vid}" ]]; then
|
|
die "L'identifiant de VLAN n'est pas renseignés.\nSyntaxe attendue : o:<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 : o:<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 minimales posisbles : \n\tSans VLAN :\n\t\to:<nom interface>:(virtio|e1000):o:<nom pont>:n\n\tAvec VLAN :\n\t\to:<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 minimales posisbles : \n\tSans pont :\n\t\to:<nom interface>:(virtio|e1000):n\n\tAvec pont :\n\t\to:<nom interface>:(virtio|e1000):o:<nom pont>:n" 5
|
|
;;
|
|
esac
|
|
;;
|
|
*)
|
|
die "${reseau_activ_interface} n'est pas une valeur connue.\nSpécifiez (n|N) pour désactiver le réseau sur la machine virtuelle ou (o|O) pour créer une interface réseau.\nVoici les deux syntaxes minimales posisbles : \n\tSans réseau :\n\t\tn\n\tAvec réseau :\n\t\to:<nom interface>:(virtio|e1000):n" 5
|
|
;;
|
|
esac
|
|
|
|
commandes_a_executer+=( "nouvMV reseau ${reseau_activ_interface} ${reseau_nom_interface} ${reseau_type} ${reseau_activ_pont} ${reseau_nom_pont} ${reseau_activ_8021q} ${reseau_mode_8021q} ${reseau_vid}")
|
|
echo "nouvMV reseau ${reseau_activ_interface} ${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:(<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}" "${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
|