#!/bin/bash
# Script d'initialisation des interfaces réseau d'un conteneur Systemd-nspawn
if [ [ -n " ${ 1 } " ] ] ; then
nom_conteneur = " ${ 1 } "
else
echo "Erreur: aucun nom de conteneur renseigné."
exit 1
fi
# Fonction exécuté en deuxième. Permet la génération de commandes pour la création d'interfaces réseau
genCmdIntRzo( ) {
# Création d'une interface non étiqueté (access)
if [ [ " ${ pont_init } " -eq 1 && " ${ vlan_init } " -eq 1 && " ${ interface_init } " -eq 1 ] ] ; then
commandes_a_executer += ( " ip link add ${ interface } type veth peer name ${ interface } _h " )
commandes_a_executer += ( " ip link set ${ interface } _h mtu 1500 " )
commandes_a_executer += ( " ip link set ${ interface } _h up " )
commandes_a_executer += ( " ip link set ${ interface } _h master ${ pont } " )
commandes_a_executer += ( " bridge vlan del dev ${ interface } _h vid 1 PVID untagged master " )
commandes_a_executer += ( " bridge vlan add dev ${ interface } _h vid ${ vlan } pvid untagged master " )
# 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 += ( " ip link add ${ interface } type veth peer name ${ interface } _h " )
commandes_a_executer += ( " ip link set ${ interface } _h mtu 1500 " )
commandes_a_executer += ( " ip link set ${ interface } _h up " )
commandes_a_executer += ( " ip link set ${ interface } _h master ${ pont } " )
commandes_a_executer += ( " bridge vlan del dev ${ interface } _h vid 1 PVID untagged master " )
for ( ( id_label_vlan = 0 ; " ${ nb_params_label } " - " ${ id_label_vlan } " ; id_label_vlan++) ) ; do
commandes_a_executer += ( " bridge vlan add dev ${ interface } _h vid ${ label_vlan [ ${ id_label_vlan } ] } tagged master " )
done
# Réinitialisation des variables témoins
pont_init = 0
ieee8021q_init = 0
interface_init = 0
# Création d'une interface normale en pont isolé dans un espace de nom réseau
elif [ [ " ${ pont_init } " -eq 1 && " ${ isole_init } " -eq 1 && " ${ interface_init } " -eq 1 ] ] ; then
commandes_a_executer += ( " ip link add ${ interface } type veth peer name ${ interface } _h " )
commandes_a_executer += ( " ip link set netns ${ isole_netns } dev ${ interface } _h " )
commandes_a_executer += ( " ip netns exec ${ isole_netns } ip link set ${ interface } _h master ${ pont } " )
commandes_a_executer += ( " ip netns exec ${ isole_netns } ip link set dev ${ interface } _h type bridge_slave isolated on " )
commandes_a_executer += ( " ip netns exec ${ isole_netns } ip link set dev ${ interface } _h mtu 1500 " )
commandes_a_executer += ( " ip netns exec ${ isole_netns } ip link set dev ${ interface } _h up " )
fi
}
# Fonction exécuté en premier. Récupère les paramètres du fichier de configuration du conteneur
recupParams( ) {
declare -a params_int = ( $( grep -B 2 "^Interface" /etc/systemd/nspawn/" ${ nom_conteneur } " .nspawn | sed "/^--/d" ) )
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 '#.*Interface' | 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 [ [ $( ip link show " ${ val_param } " 2> /dev/null || ip netns | cut -d ' ' -f 1 | xargs -I { } ip netns exec { } sh -c " ip link show ${ val_param } 2> /dev/null " | grep ${ val_param } 2> /dev/null) ] ] ; then
pont = " ${ val_param } "
pont_init = 1
else
echo " Erreur: le pont ${ val_param } n'existe pas. Arrêt immédiat du script \" ${ 0 } \" sans aucune modification du système. "
exit 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
echo "Erreur: le paramètre \"#PONT=votrePont\" est manquant."
exit 1
fi
else
echo " Erreur: le VLAN \" ${ val_param } \" n'est pas un entier compris entre 1 et 4094. Arrêt immédiat du script \" ${ 0 } \" sans aucune modification du système. "
exit 1
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
echo "Erreur: le paramètre \"#PONT=votrePont\" est manquant."
exit 1
fi
else
echo " Erreur: le tronc 802.1Q comporte un identifiant de VLAN (\" ${ val_param } \") qui n'est pas un entier compris entre 1 et 4094. Arrêt immédiat du script \" ${ 0 } \" sans aucune modification du système. "
exit 1
fi
done
elif [ " ${ nom_param } " = = "ISOLE" ] ; then
if [ [ " ${ val_param } " = ~ ^-?[ a-zA-Z0-9_\- ] +$ ] ] ; then
if [ [ " ${ pont_init } " -eq 1 ] ] ; then
isole_netns = " ${ val_param } "
isole_init = 1
else
echo "Erreur: le paramètre \"#ISOLE=espacedenomdupont\" mentionne un espace de nom réseau inexistant."
exit 1
fi
else
echo " Erreur: le nom de l'espace de nom réseau (\" ${ val_param } \") n'est pas valide. Arrêt immédiat du script \" ${ 0 } \" sans aucune modification du système. "
exit 1
fi
elif [ " ${ nom_param } " = = "Interface" ] ; then
if [ [ ! $( ip link show " ${ val_param } " 2> /dev/null || ip netns | cut -d ' ' -f 1 | xargs -I { } ip netns exec { } sh -c " ip link show ${ val_param } 2> /dev/null " | grep ${ val_param } 2> /dev/null) ] ] ; then
if [ [ " ${ vlan_init } " -eq 1 || " ${ ieee8021q_init } " -eq 1 || " ${ isole_init } " ] ] ; then
interface = " ${ val_param } "
interface_init = 1
else
echo "Erreur: le paramètre \"#VLAN=votreVLAN\" ou \"#ISOLE=espacedenomdupont\" est manquant."
exit 1
fi
elif [ [ $( find /sys/class/net/ -type l ! -lname '*/devices/virtual/net/*' -printf '%f ' | grep " ${ val_param } " 2> /dev/null) ] ] ; then
pont_init = 0
vlan_init = 0
ieee8021q_init = 0
interface_init = 0
else
echo " Erreur: l'interface ${ val_param } est déjà existante. Arrêt immédiat du script \" ${ 0 } \" sans aucune modification du système. "
exit 1
fi
fi
# Génération des commandes de création des interfaces réseau du conteneur
genCmdIntRzo
done
}
# Fonction d'exécution des commandes préparées dans la fonction genCmdIntRzo()
execCmdIntRzo( ) {
for ( ( id_commande_rzo = 0 ; " ${# commandes_a_executer [*] } " - " ${ id_commande_rzo } " ; id_commande_rzo++) ) ; do
# Exécution des commandes préparées
# Pour afficher les commandes sans rien exécuter (dans le cas d'un déboggage/modification du script), il faut précéder la ligne suivante par la commande "echo"
echo ${ commandes_a_executer [ " ${ id_commande_rzo } " ] }
${ commandes_a_executer [ " ${ id_commande_rzo } " ] }
done
}
# Fonction d'exécution du script de création d'interfaces réseau pour le conteneur en cours
principale( ) {
recupParams
execCmdIntRzo
}
principale