#!/usr/bin/env bash # FOR DEBUG : tmux kill-session -t name # Options prédéfinies pour ssh lors d'un vdn-ssh. set +u [ -z "$USER" ] && export USER=$(id -un) set -u set -a VDN_RESOURCES_ALLOCATOR=${VDN_RESOURCES_ALLOCATOR:-default} DB_CURRENT_HOST=${DB_CURRENT_USER:-$USER} DB_CURRENT_HOST=${DB_CURRENT_NETWORK:-} DB_CURRENT_HOST=${DB_CURRENT_HOST:-} set +a #SSH_OPTS="-o NoHostAuthenticationForLocalhost=yes -c aes128-ctr" SSH_OPTS="-o NoHostAuthenticationForLocalhost=yes" # Options prédéfinies pour scp lors d'un vdn-scp. SCP_OPTS="-o NoHostAuthenticationForLocalhost=yes -c aes128-ctr" # Utilise le mode master de ssh pour la connexion avec les systèmes virtuels. SSH_GUEST_MASTER=1 #set +u #[ -z "$PAUSE" ] && export PAUSE=1 || : #set -u warning() { echo -e "\n`basename $0` : warning : $@ !" >&2 } error() { echo -e "`basename $0` : error : $@ !" >&2 READ_ON_ERROR=${READ_ON_ERROR:-0} if [ "$READ_ON_ERROR" = "1" ]; then echo "Appuyez sur Entrée pour quitter" read fi exit 64 } request() { echo echo -e "$@" echo echo -n "Confirmez (O/n) : " read if [ -z "$REPLY" -o "$REPLY" = "o" -o "$REPLY" = "O" ]; then return 0 fi return 1 } requestNo() { echo echo -e "$@" echo echo -n "Confirmez (o/N) : " read if [ "$REPLY" = "o" -o "$REPLY" = "O" ]; then return 0 fi return 1 } testInstallDebian() { local notFound=0 #local bin="lsb_release qemu-system-x86_64 neato bzip2 wget" local bin="lsb_release bzip2 wget" for i in $bin; do if ! whereis $i | grep -q bin; then echo "Impossible de trouver l'exécutable : $i !" notFound=1 fi done if [ $notFound = 1 ]; then request "Programme(s) manquant(s) !\nL'administrateur doit préparer le système via la commande :\nvdn-prepare-debian\nAbandonner le démarrage de VDN ?" if [ $? -eq 0 ]; then exit 1 fi fi } computeHostRelease() { set +u [ -n "$HOST_RELEASE" ] && return || : set -u if [ -e /usr/lib/os-release ]; then ID=$(cat /usr/lib/os-release | grep '^ID=' | cut -d '=' -f 2) if [ -z "$ID" ]; then ID="empty" fi VERSION_CODENAME=$(cat /usr/lib/os-release | grep '^VERSION_CODENAME=' | cut -d '=' -f 2) if [ -z "$VERSION_CODENAME" ]; then VERSION_CODENAME="empty" fi export HOST_RELEASE="$ID/$VERSION_CODENAME" else export HOST_RELEASE="empty/empty" fi } # Fixe GUEST_PATH, GUEST_CONF et GUEST_SAVE # $1 : GUEST_NAME setGuestVars() { set -a MODE=tgz GUEST_OWNER=$USER GUEST_NAME=$1 GUEST_PATH="$NETWORK_DIR" GUEST_CONF="$GUEST_PATH/$1.conf" #if [ ! -e "$GUEST_CONF" ]; then # error "WARNING : Le système $(basename $NETWORK_DIR)/$1 n'existe pas !" #fi ##NETWORK="$(basename $NETWORK_DIR)" #IDENT="" #IDENT=$(grep '^IDENT=[0-9]' $GUEST_CONF | \ # sed -re 's/^.*IDENT=([0-9]+).*/\1/') #[ -z "$IDENT" ] && error "IDENT n'est pas fixé dans $GUEST_CONF" || : SSH_IDENTITY="$HOME/.ssh/id_dsa.pub $HOME/.ssh/id_rsa.pub" SWAP_FILE="$TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER-swap" # fichier utilisé pour la partition de l'union. # si fixée à "" alors un tmpfs est utilisé AUFS_FILE="$TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER-part" OUT_FILE="$TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER-out" ALIVE_FILE=$TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER.alive EXCLUDE_SERVICES="" KVM_NETWORKS_OPTS="" KVM_DISKS_OPTS="" KVM_OPTS="" KVM_CMD="" NET_MODEL=${NET_MODEL:-ne2k_pci} set +u [ -n "$EXPR" -a "$EXPR" != '[]' ] && { eval "$EXPR" } set -u set +a } loadGuestVars() { setGuestVars $1 computeNetworks . $VDN_PATH/config.template [ -e $VDN_PATH/config.template.local ] && . $VDN_PATH/config.template.local || : . $GUEST_CONF set -a set +u [ -n "$EXPR" -a "$EXPR" != '[]' ] && { eval "$EXPR" } set -u set +a case "$MODE" in tgz|tgz2) SAVE_FILE="$SAVE_DIR/$GUEST_NAME.tgz" ;; overlay) #SAVE_FILE="$SAVE_DIR/$GUEST_NAME.tgz" SAVE_FILE="$SAVE_DIR/$GUEST_NAME.overlay" ;; *) SAVE_FILE="$SAVE_DIR/$GUEST_NAME.cow" ;; esac [ ! -d "$(dirname $SAVE_FILE)" ] && mkdir -p "$(dirname $SAVE_FILE)" || : } # retourne 0 (vrai) si le système existe isDefined() { GUEST_PATH="$NETWORK_DIR" GUEST_CONF="$GUEST_PATH/$1.conf" test -e "$GUEST_CONF" return $? } resizeMultipleOf512() { local s=$(stat -c %s $1) local n=$(( (($s/512)+($s%512!=0)*1)*512 )) #echo "s=$s, n=$n" truncate -s $n $1 } debugNet1() { set +u [ -z "$DEBUG_NET" ] && export DEBUG_NET="false" set -u echo "debugNet1 host:$KHOST K:$K K_HIGH:$K_HIGH K_LOW:$K_LOW U:$U U1:$U_LOW U2:$U_HIGH" >&2 } computeNetworksOld() { local K U i set +u ident=$1 set -u [ -z "$ident" ] && ident=$IDENT || : # Configuration des réseaux (brins Ethernet, adresse IP et adresses MAC) # Ce fichier est lu avant la lecture du fichier de configuration d'un # système et est utilisé pour définir les réseaux (virtuels). # Lorsque ce fichier est lu, la variable IDENT contenant # l'identificateur du système à démarrer est fixée. # ### # 1. Calcule les adresses "multicast" des brins Ethernet virtuels. # ### # Détermine la clé propre à chaque utilisateur. # Remarque : conflit si même poids faible de l'UID. U=$(($(id -u)%512)) # !!! #[ "$USER" = gudavala ] && U=511 U_LOW=$(($U%256)) U_HIGH=$(($U/256)) # Détermine la clé K propre à la machine hôte (poids faible de l'IP) #K=`/sbin/ifconfig eth0 | grep Bcast | head -n 1 | cut -d ':' -f 2 | \ # cut -d ' ' -f 1 | cut -d '.' -f 4`A IP_LINE=$(ip addr | grep '192\.168' | head -n 1) #IP_LINE=$(echo " inet 192.168.1.37/24 brd 192.168.1.255 scope global dynamic eth0" | grep '192\.168' | head -n 1) K=$(echo $IP_LINE | sed -re 's/.*192\.168\.([0-9]+)\.([0-9]+)\/.*$/\1 \2/') #IP_LINE=$(echo " inet 192.168.1.37/24 brd 192.168.1.255 scope global dynamic eth0" | grep '192\.168' | head -n 1) K=$(echo $IP_LINE | sed -re 's/.*192\.168\.([0-9]+)\.([0-9]+)\/.*$/\1 \2/') [ -z "$K" ] && { echo "Warning : can't find network host uniq number ! use "1" !" K=1 } #KK="" #if [ -e $NETWORK_DIR/hosts.txt ]; then # local h=$(hostname) # h=$(echo $h | sed -re 's/iutclinf(.*)l/\1/') # KK=$(cat $NETWORK_DIR/hosts.txt | grep -n $h | cut -d ':' -f 1) # [ -n "$k2" ] && K=$K_LOW #fi #echo "KEY:$K K_LOW=$KK" K_HIGH=$(echo $K | cut -d ' ' -f 1) K_LOW=$(echo $K | cut -d ' ' -f 2) KHOST=$K_LOW [ "$K_HIGH" = "128" ] && KHOST=$((512+$K_LOW)) [ $K_HIGH = 128 ] && K_HIGH=1 || K_HIGH=0 #K_HIGH=$(($K_HIGH%16)) K_LOW=$(($K_LOW%256)) set +u #[ "$USER" = "gudavala" ] && [ -z "$VDN_FIRST" ] && debugNet1 set -u set -a # Brin Ethernet PARTAGÉ par TOUS les systèmes de TOUS les utilisateurs. # [Internet virtuel] NET_G="239.2.0.0:1999" # Brins privés à une machine hôte for i in `seq 0 64`; do eval NET_$i="234.$K_HIGH.$K_LOW.$U_LOW:$((2000+$U*16+$i))" done # ### # 2. Calcule l'adresse IP "réservée" sur le brin PARTAGÉ # ### ###PUBLIC_IP="$((20+$K_HIGH+U_HIGH*2)).$K_LOW.$U_LOW.$ident" #set -x PUBLIC_IP=$(vdn-query PUBLIC_IP 0 $GUEST_NAME.$NETWORK_NAME) #set +x # ### # 3. Calcule les adresses MAC des cartes Ethernet # ### U_LOW=`printf "%02X" $U_LOW` V=$((54+$K_HIGH+$U_HIGH*2)) V=$(printf "%02d" $V) K_HIGH=`printf "%02X" $K_HIGH` K_LOW=`printf "%02X" $K_LOW` F_IDENT=$(printf "%02d" $ident) MAC_0=52:$V:$K_LOW:$U_LOW:$F_IDENT:00 MAC_1=52:$V:$K_LOW:$U_LOW:$F_IDENT:01 MAC_2=52:$V:$K_LOW:$U_LOW:$F_IDENT:02 MAC_3=52:$V:$K_LOW:$U_LOW:$F_IDENT:03 MAC_4=52:$V:$K_LOW:$U_LOW:$F_IDENT:04 MAC_5=52:$V:$K_LOW:$U_LOW:$F_IDENT:05 MAC_6=52:$V:$K_LOW:$U_LOW:$F_IDENT:06 MAC_7=52:$V:$K_LOW:$U_LOW:$F_IDENT:07 set +a } computeNetworks() { set -a # NET_G ? # NET_ ? #PUBLIC_IP=$(vdn-query PUBLIC_IP 0 $GUEST_NAME.$NETWORK_NAME) # MAC_ ? } # "Calcule" le port utilisé pour une redirection (interface pour la connexion # avec l'hôte). # En unique argument, le port de la machine virtuelle à rediriger vers un port # local. En sortie, affichage du port "théorique" pour la redirection. # En pratique le premier port libre égal ou supérieur au port "théorique" sera # utilisé. vdn_redirOld() { echo $((5000+100*$IDENT+$1)) } getIpNotUsed() { name=$1 eth=$2 #vdn-infos $name >&2 local nets=$(vdn-infos $name | grep '^NETWORKS=' | sed -re 's/^NETWORKS=//') local ip=$(echo $nets | cut -d ' ' -f $((eth+1)) | cut -d '#' -f 2 | sed -re 's/^[^0-9]*([0-9.]+).*$/\1/') echo $ip } # Vérifie l'unicité des identificateurs des systèmes du réseau courant. verifIdentOld() { local i=0 local configs="`find $NETWORK_DIR -follow -type f -name \"*.conf\" 2> /dev/null`" [ -n "$configs" ] || return 0 l=$(grep -E '^[[:space:]]*IDENT=[0-9]+' $configs | \ sed -re 's,^.*/([^/]*)/config:[[:space:]]*IDENT=([0-9]+).*$,\1:\2,' | sort -n -t : -k 2) local t for i in $l; do name=$(echo $i | cut -d ':' -f 1) ident=$(echo $i | cut -d ':' -f 2) set +u t[$ident]="${t[$ident]},$name" set -u done local found=0 for i in ${t[*]}; do l=$(echo $i | sed -re 's/^,//') if echo $l | grep -q ','; then n=$(echo $l | cut -d ',' -f 1) ident=$(vdn-config $n IDENT) echo "Erreur : l'identificateur $ident est partagé par $l !" found=1 fi done return $found } # Démarre un ssh pour un système virtuel en mode "master" sshGuestControlMaster() { Login=${LOGIN}localhost # wait lock local n=0 local lock=$TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER-ssh-lock while ! mkdir $lock 2> /dev/null; do sleep 0.5 # Securité n=$(($n+1)) if [ $n -gt 5 ]; then rmdir $lock 2> /dev/null || : fi done sleep 0.1 #echo "Locked" #echo "Login:$Login" >&2 #ps auwx > /tmp/p #ps auwx | grep -v grep | grep $Login | grep -q -- "-N -M" > /tmp/o || : local sign="$TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER-guest" test="ps auwx | grep -v grep | grep $Login | grep $sign" #[ $GUEST_OWNER = gudavala ] && echo "test:$test" if ! ps auwx | grep -v grep | grep $Login | grep $sign | grep -q -- "-N -M"; then rmdir $lock 2> /dev/null || : #[ $GUEST_OWNER = gudavala ] && echo "Master... $TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER-guest" ssh -g $Login $SSH_OPTS $@ -o ServerAliveInterval=5 -p $SSH_REDIR_PORT -X -f -n -N -M -S $TMPDIR/vdn-$GUEST_NAME-$GUEST_OWNER-guest-%r@%h:%p &> /dev/null else rmdir $lock 2> /dev/null || : fi } findUnusedPort() { # $1 : proto # $2 : port local proto port dst hex proc proto=$1 port=$2 hex=`printf "%04X" $port` proc="/proc/net/$proto" while cat $proc | cut -d : -f2- | cut -d ' ' -f2,3 | grep -q ":$hex"; do #echo "$proto port $port (for $dst) is used ! find next !" >&2 port=$(($port+1)) hex=`printf "%04X" $port ` done echo $port } setEnv() { set +u local save="$NETWORK_DIR" set -u set -a . $VDN_PATH/config.rc # ! set NETWORK_DIR [ -e $VDN_PATH/config.rc.local ] && . $VDN_PATH/config.rc.local || : # NETWORK_DIR priority if [ -n "$save" ]; then NETWORK_DIR=$save fi set +a set +u [ -z "$EDITOR" ] && export EDITOR="vi" set -u export HOST_RELEASE export VDN_WS_PROXY_SOCKET=$TMPDIR/vdn-$USER-ws-sock } vdn_init() { export VDN_NETWORKS_BASE_DIR=${VDN_NETWORKS_BASE_DIR:-$VDN_PATH/networks} set +u CURRENT_NETWORK_DIR="$NETWORK_DIR" # var. d'env. prioritaire NETWORK_NAME="" [ -n "$CURRENT_NETWORK_DIR" ] && NETWORK_NAME=$(basename $CURRENT_NETWORK_DIR) #[ -z "$NETWORK_NAME" ] && error "NETWORK_NAME empty !" set -u PATH="$PATH:$VDN_PATH/bin" setEnv set -a [ ! -e "$TMPDIR" ] && (umask 077 && mkdir -p "$TMPDIR" ) [ -n "$CURRENT_NETWORK_DIR" ] && NETWORK_DIR="$CURRENT_NETWORK_DIR" set +u if [ -n "$NETWORK_DIR" ]; then if [ ! -d "$NETWORK_DIR" ]; then #echo "Le réseau $NETWORK_DIR n'existe pas !" >&2 || : NETWORK_DIR="" SAVE_DIR="" #exit 1 fi if [ "$NETWORK_DIR" != "" ]; then . $NETWORK_DIR/network.vdn SAVE_DIR="$SAVE_PATH/$(basename $NETWORK_DIR)" fi else SAVE_DIR="" fi set -u set +a set +u [ -z "$VDN_DEBUG" ] && export VDN_DEBUG=0 || : set -u } sendToGui() { local pid=$(ps auwx | grep 'ruby' | grep 'vdn-gui' | tr -s " " | cut -d ' ' -f 2) if [ -n "$pid" ]; then #echo "SENDTOGUI ($TMPDIR/vdn-gui-$USER-fifo-ctrl) : $@" echo "$@" > $TMPDIR/vdn-gui-$USER-fifo-ctrl fi } # main set +u [ -z "$VDN_PATH" ] && export VDN_PATH=$(readlink -f $(dirname $0)/..) || : ! echo "$PATH" | grep -q $VDN_PATH && export PATH="$VDN_PATH/bin:$PATH" set -u computeHostRelease setEnv vdn_init