From 8f1a2c449eeffba0c6e710d5f751e221dbcc2d44 Mon Sep 17 00:00:00 2001 From: ycharbi Date: Fri, 17 Jul 2020 16:56:41 +0200 Subject: [PATCH] =?UTF-8?q?D=C3=A9p=C3=B4t=20initial.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 30 +++++++++++++ apache1.nspawn | 13 ++++++ ifdown.sh | 4 ++ ifup.sh | 94 +++++++++++++++++++++++++++++++++++++++++ systemd-nspawn@.service | 52 +++++++++++++++++++++++ 5 files changed, 193 insertions(+) create mode 100644 README.md create mode 100644 apache1.nspawn create mode 100755 ifdown.sh create mode 100755 ifup.sh create mode 100644 systemd-nspawn@.service diff --git a/README.md b/README.md new file mode 100644 index 0000000..f75dd2c --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# Fichier *ifup.sh* +Ce fichier est le script d'initialisation des interfaces réseau pour les conteneurs *Systemd-nspawn* que j'ai écrit. + +Il gère la création de plusieurs interfaces réseau ainsi que les VLAN et peut mettre ces interfaces dans des ponts différents. Afin qu'il s'exécute au démarrage d'un conteneur, il faut ajouter à la directive *[Service]* du fichier */lib/systemd/system/systemd-nspawn@.service* le paramètre suivant: +``` bash +ExecStartPre=/etc/systemd/nspawn/ifup.sh %i +``` + + Il faut au préalable ajouter deux lignes de commentaires au dessus de chaque directive "*Interface=*" dans le fichier de configuration de votre conteneur: +``` bash +PONT=votrepont +VLAN=vid +``` +Le script vérifie que ce que vous avez renseigné est valide. Si non, il ne fait rien. Le fichier "*apache1.nspawn*" est un exemple (se trouve dans */etc/systemd/nspawn/* sur le système de test). + +Pour tester le script sans créer les interfaces, veillez remplacer les lignes d'initialisation du tableau *commandes_a_executer[]* de la fonction *generCmdIntRzo()* par les lignes suivantes: + +``` bash +commandes_a_executer+=( "echo \"ip link add ${interface} type veth peer name ${interface}_h\"" ) +commandes_a_executer+=( "echo \"ip link set ${interface}_h up\"" ) +commandes_a_executer+=( "echo \"ip link set ${interface}_h master ${pont}\"" ) +commandes_a_executer+=( "echo \"bridge vlan del dev ${interface}_h vid 1 PVID untagged master\"" ) +commandes_a_executer+=( "echo \"bridge vlan add dev ${interface}_h vid ${vlan} pvid untagged master\"" ) +``` +# À tester +Tester le comportement du script lorsque aucun fichier de configuration n'existe et en fonction du résultat, ajouter un test sur ce critaire. + diff --git a/apache1.nspawn b/apache1.nspawn new file mode 100644 index 0000000..caeca3f --- /dev/null +++ b/apache1.nspawn @@ -0,0 +1,13 @@ +[Exec] +Boot=on + +[Network] +#PONT=br0 +#VLAN=150 +Interface=apache1 +#PONT=br0 +#VLAN=151 +Interface=apache1bis +#PONT=br0 +#VLAN=2 +Interface=apache1ter diff --git a/ifdown.sh b/ifdown.sh new file mode 100755 index 0000000..7a703c8 --- /dev/null +++ b/ifdown.sh @@ -0,0 +1,4 @@ +#!/bin/bash +#echo "$1 éteint." >> /tmp/$1 + +#ip link del ${1}_h diff --git a/ifup.sh b/ifup.sh new file mode 100755 index 0000000..d83f1d7 --- /dev/null +++ b/ifup.sh @@ -0,0 +1,94 @@ +#!/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 + +generCmdIntRzo(){ + # Fonction exécuté en deuxième. Permet la génération de commandes pour la création d'interfaces réseau. + 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 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 + fi +} + +recupParams(){ + # Fonction exécuté en premier. Récuppère les paramètres du fichier de configuration du conteneur + declare -a params_int=( $(grep -B 2 "^Interface" /etc/systemd/nspawn/"${nom_conteneur}".nspawn | sed "/^--/d") ) + nb_params="${#params_int[*]}" + + for ((i=0 ; "${nb_params}" - "${i}" ; i++)); do + nom_param=$(echo "${params_int[${i}]}" | sed "s/=.*//" | sed "s/#//") + val_param=$(echo "${params_int[${i}]}" | 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) ]]; 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}" == "Interface" ]; then + if [[ ! $(ip link show "${val_param}" 2> /dev/null) ]]; then + if [[ "${vlan_init}" -eq 1 ]]; then + interface="${val_param}" + interface_init=1 + else + echo "Erreur: le paramètre \"#vlan=votreVLAN\" est manquant." + exit 1 + fi + 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 + else + echo "Erreur: le paramètre numéro $((${i}+1)) (\"${params_int[${i}]}\") dans le fichier de configuration est mal formé (faute de frappe)." + exit 1 + fi + + # Génération des commandes de création des interfaces réseau du conteneur + generCmdIntRzo + done +} + +execCmdIntRzo(){ + for ((i=0 ; "${#commandes_a_executer[*]}" - "${i}"; i++)); do + ${commandes_a_executer["${i}"]} + done +} + +principale(){ + # Fonction d'exécution du script de création d'interfaces réseau pour le conteneur en cours. + recupParams + execCmdIntRzo +} + +principale diff --git a/systemd-nspawn@.service b/systemd-nspawn@.service new file mode 100644 index 0000000..3fe75cb --- /dev/null +++ b/systemd-nspawn@.service @@ -0,0 +1,52 @@ +# SPDX-License-Identifier: LGPL-2.1+ +# +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Container %i +Documentation=man:systemd-nspawn(1) +Wants=modprobe@tun.service modprobe@loop.service modprobe@dm-mod.service +PartOf=machines.target +Before=machines.target +After=network.target systemd-resolved.service modprobe@tun.service modprobe@loop.service modprobe@dm-mod.service +RequiresMountsFor=/var/lib/machines/%i + +[Service] +# Make sure the DeviceAllow= lines below can properly resolve the 'block-loop' expression (and others) +ExecStartPre=/etc/systemd/nspawn/ifup.sh %i +ExecStart=systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth -U --settings=override --machine=%i +ExecStopPost=/etc/systemd/nspawn/ifdown.sh %i +KillMode=mixed +Type=notify +RestartForceExitStatus=133 +SuccessExitStatus=133 +Slice=machine.slice +Delegate=yes +TasksMax=16384 +WatchdogSec=3min + +# Enforce a strict device policy, similar to the one nspawn configures when it +# allocates its own scope unit. Make sure to keep these policies in sync if you +# change them! +DevicePolicy=closed +DeviceAllow=/dev/net/tun rwm +DeviceAllow=char-pts rw + +# nspawn itself needs access to /dev/loop-control and /dev/loop, to implement +# the --image= option. Add these here, too. +DeviceAllow=/dev/loop-control rw +DeviceAllow=block-loop rw +DeviceAllow=block-blkext rw + +# nspawn can set up LUKS encrypted loopback files, in which case it needs +# access to /dev/mapper/control and the block devices /dev/mapper/*. +DeviceAllow=/dev/mapper/control rw +DeviceAllow=block-device-mapper rw + +[Install] +WantedBy=machines.target