@ -1,4 +1,4 @@
#!/bin/ ba sh
#!/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, ERR OR , 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
# 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" )
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
# 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
fi
done
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' )
# 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
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 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
# 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
# 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