From f335ed529268e5e8cc96907493ed89a17b6e18ba Mon Sep 17 00:00:00 2001 From: alarig Date: Mon, 21 Jan 2019 14:36:50 +0100 Subject: [PATCH] Too many modifications --- creationRoutesVM.sh | 297 ++++++++++++++++++++------------------------ creds.example | 7 ++ 2 files changed, 144 insertions(+), 160 deletions(-) diff --git a/creationRoutesVM.sh b/creationRoutesVM.sh index 9f7037a..c970bfc 100755 --- a/creationRoutesVM.sh +++ b/creationRoutesVM.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # Script ajout de routes VM @@ -11,21 +11,25 @@ # - CHEMIN_CACHE write_log() { - # $1: log level (INFO, ERR, etc.) + # $1: log level (INFO, ERROR, etc.) # $2: message printf "$(date -Isecond) - $1: $2\n" >> \ ${LOG_PLACE}/$(date -Idate)_vm_routing.log + if [ $1 = 'ERROR' ] || [ $1 = 'FATAL' ] || [ $1 = 'WARN' ]; then + printf "$1: $2\n" + fi } # IPAM creds -if [ -f creds ]; then - source creds +if [ -f ./creds ]; then + source ./creds + CURL='curl -s -k -sS' else - printf 'Can’t source "creds": file not found\n' + write_log ERROR 'The file creads doesn’t exist' fi # check for commands in the path -for bin in curl ipv6calc ip; do +for bin in curl ip ipv6calc jq; do if [ -z $(which ${bin} 2>/dev/null) ]; then MISSING="${MISSING} ${bin}" fi @@ -36,14 +40,6 @@ if [ ! -z "${MISSING}" ]; then exit 1 fi -# ID subnets IPAM V4 et V6 contenants les VMs -ID_RANGES_V4=( "74" "181" ) -ID_RANGES_V6=( "34" ) - -# Booléen si informations trouvées pour V4 ou V6 -BOOL_V4=0 -BOOL_V6=0 - # Chemin fichier de LOG (et création du répertoire s'il n'existe pas) LOG_PLACE='./vm_id_log/' if [ ! -d "${LOG_PLACE}" ];then @@ -67,10 +63,10 @@ usage() { printf "option : \t-h, --help Affiche ce message d’aide\n" } -if [ $? != 0 ]; then - echo "$(date -Isecond) - ERREUR : probleme au lancement du script" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - exit 1 -fi +#if [ $? != 0 ]; then +# echo "$(date -Isecond) - ERREUR : probleme au lancement du script" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log +# exit 1 +#fi # On vérifie la bonne présence d'un paramètre VM_ID if [ $1 ]; then @@ -78,171 +74,152 @@ if [ $1 ]; then usage exit 0 elif [ $# -lt 1 ]; then - echo "Paramètre VM_ID manquant (--help pour plus d'infos)" - echo "$(date -Isecond) - ERREUR : Paramètre VM_ID manquant (--help pour plus d'infos)" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log + write_log FATAL 'VM ID not specified' usage exit 1 + else + # Verification of the VM ID + expr $1 + 0 1>/dev/null 2>&1 + if [ $? -lt 2 ] && [ $1 -gt 0 ]; then + VM_ID=$1 + else + write_log FATAL 'The VM ID must a non-null integer' + exit 1 + fi fi else - echo "Paramètre VM_ID manquant (--help pour plus d'infos)" - echo "$(date -Isecond) - ERREUR : Paramètre VM_ID manquant (--help pour plus d'infos)" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log + write_log FATAL 'No parameter specified' usage exit 1 fi -# On vérifie que le paramètre est bien un entier supérieur à zéro -expr $1 + 0 1>/dev/null 2>&1 -statut=$? -if [ $statut -lt 2 ] && [ $1 -gt 0 ]; then - VM_ID=$1 -else - echo "Paramètre VM_ID incorrect, ce doit être un entier supérieur à zéro (--help pour plus d'infos)" - echo "$(date -Isecond) - ERREUR : Paramètre VM_ID incorrect, ce doit être un entier supérieur à zéro (--help pour plus d'infos)" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - usage - exit 1 -fi - - # Récupération d'un TOKEN pour utiliser IPAM via l'API -RES_AUTHENT=$(curl -k -X POST --user ${USER_IPAM}:${PASSWORD_IPAM} https://ipam.grifon.fr/api/apiculteur/user/ -sS) +write_log DEBUG 'Connecting to API' +RES_AUTHENT=$(${CURL} -X POST --user ${USER_IPAM}:${PASSWORD_IPAM} ${URL}/user/) CODE_RETOUR_RES_AUTHENT=$(echo ${RES_AUTHENT} | jq '.code') # Si OK, on utilise l'IPAM, sinon on passe par le fichier de cache -if [ ${CODE_RETOUR_RES_AUTHENT} -eq 200 ] ;then +if [ ${CODE_RETOUR_RES_AUTHENT} != 200 ]; then + write_log ERROR "Wrong HTTP code from the API: ${CODE_RETOUR_RES_AUTHENT}" + write_log INFO "Using cache instead" +else + FEED_CACHE=1 +fi - # Mise du TOKEN dans une variable et retrait des éventuelles guillemets ajoutées lors de la récupération via jq - TOKEN=$(echo ${RES_AUTHENT} | jq '.data.token') - TOKEN=$(echo $TOKEN | sed -e "s/\"//g") - - # On vérifie que le TOKEN n'est pas vide +# Mise du TOKEN dans une variable et retrait des éventuelles guillemets ajoutées lors de la récupération via jq +if [ ${FEED_CACHE} = 1 ]; then + write_log DEBUG 'Getting token' + TOKEN=$(echo ${RES_AUTHENT} | jq -r '.data.token') if [ ! -n "${TOKEN}" ]; then - echo "TOKEN Vide"; - echo "$(date -Isecond) - ERREUR : TOKEN Vide" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log + write_log FATAL 'Empty token' exit 1 fi - # Pour chaque subnet V4 - for ID_RANGE_V4 in ${ID_RANGES_V4[@]}; do - # Si les infos V4 n'ont pas encore été trouvées - if [ $BOOL_V4 -eq 0 ]; then - # Récupération des informations V4 et vérification du code HTTP - INFOS_V4=$(curl -s -k --header "Content-type: application/x-www-form-urlencoded" --header "token: $TOKEN" -X GET https://ipam.grifon.fr/api/apiculteur/subnets/${ID_RANGE_V4}/addresses) - CODE_RETOUR_INFOS_V4=$(echo ${INFOS_V4} | jq '.code') - # Mise à jour du fichier de cache pour ce ID de subnet - echo ${INFOS_V4} > ${CHEMIN_CACHE}/${ID_RANGE_V4} - if [ ${CODE_RETOUR_INFOS_V4} -eq 200 ] ;then - # Recherche des informations correspondants à la VM_ID - VM_IPV4=$(echo ${INFOS_V4} | jq -r ".data[] | select(.custom_vm_id==\"${VM_ID}\") | .ip") - # Si la valeur n'est pas vide et correspond à une IPV4 - if [ -n "${VM_IPV4}" ]; then - # Ajout de la route associée - echo "ip -4 route add ${VM_IPV4}/32 dev tap${VM_ID}i0 (source : IPAM)" - write_log INFO "ip -4 route add ${VM_IPV4}/32 dev tap${VM_ID}i0 (source : IPAM)" - ip -4 route add ${VM_IPV4}/32 dev tap${VM_ID}i0 - BOOL_V4=1 - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Valeur vide ou ne correspond pas à une IPV4" - echo "$(date -Isecond) - NOTICE : Valeur vide ou ne correspond pas à une IPV4" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Echec de la récupération des infos V4, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V4}" - echo "$(date -Isecond) - NOTICE : Echec de la récupération des infos V4, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V4}" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi + write_log INFO 'Feeding cache' + # IPv4 addresses + for ID_RANGE_V4 in ${ID_RANGES_V4}; do + # Récupération des informations V4 et vérification du code HTTP + INFOS_V4=$(${CURL} --header "Content-type: application/x-www-form-urlencoded" --header "token: $TOKEN" -X GET "${URL}/subnets/${ID_RANGE_V4}/addresses") + CODE_RETOUR_INFOS_V4=$(echo ${INFOS_V4} | jq '.code') + + if [ ${CODE_RETOUR_INFOS_V4} != 200 ]; then + write_log FATAL "Wrong code returned for IPv4 range ${ID_RANGE_V4}: ${CODE_RETOUR_INFOS_V4}" + exit 1 fi + + # Mise à jour du fichier de cache pour ce ID de subnet + echo ${INFOS_V4} > ${CHEMIN_CACHE}/${ID_RANGE_V4} done - # Pour chaque subnet V6 - for ID_RANGE_V6 in ${ID_RANGES_V6[@]}; do - # Si les infos V6 n'ont pas encore été trouvées - if [ $BOOL_V6 -eq 0 ]; then - # Récupération des informations V6 et vérification du code HTTP - INFOS_RANGES_V6=$(curl -s -k --header "Content-type: application/x-www-form-urlencoded" --header "token: $TOKEN" -X GET https://ipam.grifon.fr/api/apiculteur/subnets/${ID_RANGE_V6}/slaves/) - CODE_RETOUR_INFOS_RANGES_V6=$(echo ${INFOS_RANGES_V6} | jq '.code') - # Mise à jour du fichier de cache pour cet ID de subnet - echo ${INFOS_RANGES_V6} > ${CHEMIN_CACHE}/${ID_RANGE_V6} - if [ ${CODE_RETOUR_INFOS_V4} -eq 200 ] ;then - # Recherche des informations correspondants à la VM_ID - VM_IPV6=$(echo ${INFOS_RANGES_V6} | jq -r ".data[] | select(.custom_vm_id==\"${VM_ID}\") | .subnet") - # Si la valeur n'est pas vide et correspond à un range IPV6 - if [ -n "${VM_IPV6}" ]; then - # Ajout de la route associée - echo "ip -6 route add ${VM_IPV6}/48 dev tap${VM_ID}i0 (source : IPAM)" - write_log INFO "ip -6 route add ${VM_IPV6}/48 dev tap${VM_ID}i0 (source IPAM)" - ip -6 route add ${VM_IPV6}/48 dev tap${VM_ID}i0 - BOOL_V6=1 - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Valeur vide ou ne correspond pas à un range IPV6" - echo "$(date -Isecond) - NOTICE : Valeur vide ou ne correspond pas à un range IPV6" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Echec de la récupération des infos V6, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V6}" - echo "$(date -Isecond) - NOTICE : Echec de la récupération des infos V6, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V6}" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi - fi - done -# Sinon, on passe par le fichier de cache -else - # Pour chaque subnet V4 - for ID_RANGE_V4 in ${ID_RANGES_V4[@]}; do - # Si les infos V4 n'ont pas encore été trouvées - if [ $BOOL_V4 -eq 0 ]; then - # Récupération des informations V4 en cache pour cet ID de subnet si le fichier de cache associé existe - if [ -f "${CHEMIN_CACHE}/${ID_RANGE_V4}" ];then - INFOS_V4=$(cat ${CHEMIN_CACHE}/${ID_RANGE_V4}) - # Recherche des informations correspondants à la VM_ID - VM_IPV4=$(echo ${INFOS_V4} | jq -r ".data[] | select(.custom_vm_id==\"${VM_ID}\") | .ip") - # Si la valeur n'est pas vide et correspond à une IPV4 - if [ -n "${VM_IPV4}" ]; then - # Ajout de la route associée - echo "ip -4 route add ${VM_IPV4}/32 dev tap${VM_ID}i0 (source : CACHE)" - write_log INFO "ip -4 route add ${VM_IPV4}/32 dev tap${VM_ID}i0 (source: cache)" - ip -4 route add ${VM_IPV4}/32 dev tap${VM_ID}i0 - BOOL_V4=1 - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Valeur vide ou ne correspond pas à une IPV4" - echo "$(date -Isecond) - NOTICE : Valeur vide ou ne correspond pas à une IPV4" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Echec de la récupération des infos V4, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V4}" - echo "$(date -Isecond) - NOTICE : Echec de la récupération des infos V4, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V4}" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi + # Freeing RAM + INFOS_V4='' + CODE_RETOUR_INFOS_V4='' + + # IPv6 ranges + for ID_RANGE_V6 in ${ID_RANGES_V6}; do + # Récupération des informations V6 et vérification du code HTTP + INFOS_RANGES_V6=$(${CURL} --header "Content-type: application/x-www-form-urlencoded" --header "token: $TOKEN" -X GET ${URL}/subnets/${ID_RANGE_V6}/slaves/) + CODE_RETOUR_INFOS_RANGES_V6=$(echo ${INFOS_RANGES_V6} | jq '.code') + + if [ ${INFOS_RANGES_V6} != 200 ]; then + write_log FATAL "Wrong code returned for IPv4 range ${ID_RANGE_V6}: ${INFOS_RANGES_V6}" + exit 1 fi + + echo ${INFOS_RANGES_V6} > ${CHEMIN_CACHE}/${ID_RANGE_V6} done - # Pour chaque subnet V6 - for ID_RANGE_V6 in ${ID_RANGES_V6[@]}; do - # Si les infos V6 n'ont pas encore été trouvées - if [ $BOOL_V6 -eq 0 ]; then - # Récupération des informations V6 en cache pour cet ID de subnet si le fichier de cache associé existe - if [ -f "${CHEMIN_CACHE}/${ID_RANGE_V6}" ];then - INFOS_RANGES_V6=$(cat ${CHEMIN_CACHE}/${ID_RANGE_V6}) - # Recherche des informations correspondants à la VM_ID - VM_IPV6=$(echo ${INFOS_RANGES_V6} | jq -r ".data[] | select(.custom_vm_id==\"${VM_ID}\") | .subnet") - # Si la valeur n'est pas vide et correspond à un range IPV6 - if [ -n "${VM_IPV6}" ]; then - # Ajout de la route associée - echo "ip -6 route add ${VM_IPV6}/48 dev tap${VM_ID}i0 (source : CACHE)" - write_log INFO "ip -6 route add ${VM_IPV6}/48 dev tap${VM_ID}i0 (source: cache)" - ip -6 route add ${VM_IPV6}/48 dev tap${VM_ID}i0 - BOOL_V6=1 - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Valeur vide ou ne correspond pas à un range IPV6" - echo "$(date -Isecond) - NOTICE : Valeur vide ou ne correspond pas à un range IPV6" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi - else - # En cas d'echec, on continue de parcourir les autres RANGES - echo "Echec de la récupération des infos V6, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V6}" - echo "$(date -Isecond) - NOTICE : Echec de la récupération des infos V6, code HTTP reçu différent de 200 : ${CODE_RETOUR_INFOS_V6}" >> ${LOG_PLACE}/$(date -Idate)_vm_id.log - fi - fi - done + # Freeing RAM + INFOS_RANGES_V6='' + CODE_RETOUR_INFOS_RANGES_V6='' fi + +MAC=$(grep vmbr1 /etc/pve/qemu-server/${VM_ID}.conf | \ + sed -E 's/.*([[:xdigit:]:]{17}).*/\1/') + +# Pour chaque subnet V4 +for ID_RANGE_V4 in ${ID_RANGES_V4}; do + # Récupération des informations V4 en cache pour cet ID de subnet si le fichier de cache associé existe + if [ ! -f "${CHEMIN_CACHE}/${ID_RANGE_V4}" ]; then + write_log FATAL "File not found: ${CHEMIN_CACHE}/${ID_RANGE_V4}" + exit 1 + fi + + VM_IPV4=$(jq -r ".data[] | select(.custom_vm_id==\"${VM_ID}\") | .ip" ${CHEMIN_CACHE}/${ID_RANGE_V4}) + + # Si la valeur n'est pas vide et correspond à une IPV4 + if [ -n "${VM_IPV4}" ]; then + # Ajout de la route associée + COMMAND="ip -4 route add ${VM_IPV4}/32 dev tap${VM_ID}i0" + echo "${COMMAND}" + write_log INFO "${COMMAND}" + ${COMMAND} + + # Updating ARP + COMMAND="ip neigh change ${VM_IPV4} lladdr ${MAC} dev tap${VM_ID}i0" + echo "${COMMAND}" + write_log INFO "${COMMAND}" + ${COMMAND} + else + # En cas d'echec, on continue de parcourir les autres RANGES + write_log WARN 'Empty value or doen’t correspond to an IPv4' + fi +done + +# Pour chaque subnet V6 +for ID_RANGE_V6 in ${ID_RANGES_V6}; do + # Récupération des informations V6 en cache pour cet ID de subnet si le fichier de cache associé existe + if [ ! -f "${CHEMIN_CACHE}/${ID_RANGE_V6}" ]; then + write_log FATAL "File not found: ${CHEMIN_CACHE}/${ID_RANGE_V4}" + exit 1 + fi + + # Recherche des informations correspondants à la VM_ID + VM_IPV6=$(jq -r ".data[] | select(.custom_vm_id==\"${VM_ID}\") | .subnet" ${CHEMIN_CACHE}/${ID_RANGE_V6}) + VM_NH=$(jq -r ".data[] | select(.custom_vm_id==\"${VM_ID}\") | .\"Next-hop\"" ${CHEMIN_CACHE}/${ID_RANGE_V6}) + # Si la valeur n'est pas vide et correspond à un range IPV6 + if [ -n "${VM_IPV6}" ]; then + if [ ${VM_NH} = 'null' ]; then + VM_NH=$(ipv6calc --action prefixmac2ipv6 --in prefix+mac --out ipv6addr fe80:: ${MAC}) + fi + + # Ajout de la route associée + COMMAND="ip -6 route add ${VM_IPV6}/48 via ${VM_NH} dev tap${VM_ID}i0" + echo "${COMMAND}" + write_log INFO "${COMMAND}" + ${COMMAND} + + # Updating NDP + COMMAND="ip neigh change ${VM_NH} lladdr ${MAC} dev tap${VM_ID}i0" + echo "${COMMAND}" + write_log INFO "${COMMAND}" + ${COMMAND} + else + # En cas d'echec, on continue de parcourir les autres RANGES + echo "Valeur vide ou ne correspond pas à un range IPV6" + write_log WARN 'Empty value or doesn’t correspond to an IPv6 range' + fi +done + write_log INFO 'Script ended' exit 0 diff --git a/creds.example b/creds.example index 4651c5c..2304478 100644 --- a/creds.example +++ b/creds.example @@ -1,3 +1,10 @@ # User and password to request a token on phpIPAM API USER_IPAM='user' PASSWORD_IPAM='passwd' + +# URL of the API +URL="https://ipam.example.org/api/${USER_IPAM}" + +# ID of the ranges, you can put multiple ranges per AFI +ID_RANGES_V4='32 42' +ID_RANGES_V6='128'