virt-lib 6.46 KB
Newer Older
Maria Matejka's avatar
INIT  
Maria Matejka committed
1
#!/bin/bash
2 3
#ROOT=$(readlink -f $(dirname $(readlink -f $0))/../)
ROOT=/var/lib/virt
Maria Matejka's avatar
INIT  
Maria Matejka committed
4 5 6 7 8 9 10

VIRTBR=virtbr
VIRTCTRL=virtctrl
VIRTUPLINK=virtuplink
VIRTUALS=$ROOT/etc/virtlist
VIRTUSER=virt-qemu

11 12 13 14
function E() {
  $QUIET || echo "$@"
}

Maria Matejka's avatar
INIT  
Maria Matejka committed
15 16 17 18 19 20 21 22
function virtns() {
	"$@"
}

function vsctl() {
	virtns ovs-vsctl "$@"
}

Maria Matejka's avatar
Maria Matejka committed
23 24 25 26
function mactotap() {
	echo vl-$(tr -d ':' <<<"$1")
}

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
function wait_pidfiles() {
  local -A PIDS
  while [ -r $1 ]; do
    ${PIDS[$(<$1)]}=1
    shift
  done
  TIMEOUT=${1:-30}

  while [ ! -z "${!PIDS[@]}" ]; do
		E -n "."
    for pid in "${!PIDS[@]}"; do
      if [ ! -d /proc/$pid ]; then
        unset PIDS[$pid]
      fi
    done
  done
}

Maria Matejka's avatar
INIT  
Maria Matejka committed
45 46 47 48 49
function wait_pidfile() {
	CNT=0
	FILE=$1
	TIMEOUT=${2:-30}
	while [ -d /proc/$(<$FILE) ]; do
50
		E -n "."
Maria Matejka's avatar
INIT  
Maria Matejka committed
51 52 53
		sleep 1
		CNT=$((CNT+1))
		if [ $CNT -eq $TIMEOUT ]; then
54 55
			E
			E "Timeout ${TIMEOUT}s reached."
Maria Matejka's avatar
INIT  
Maria Matejka committed
56 57 58 59 60 61
			return 1
		fi
	done
	return 0
}

Maria Matejka's avatar
Maria Matejka committed
62
SOCAT=$ROOT/bin/socat
Maria Jan Matejka's avatar
Maria Jan Matejka committed
63
#SOCAT=$(which socat)
Maria Matejka's avatar
Maria Matejka committed
64 65 66

declare -A HOSTS
declare -A CONF
Maria Matejka's avatar
Maria Matejka committed
67

68 69 70 71
function getmac() {
	echo 52:54:$(sed -r 's/^.*(..)(..)(..)(..)$/\1:\2:\3:\4/'<<<"$1")
}

Maria Matejka's avatar
Maria Matejka committed
72 73 74
function hostctlnet() {
	if [ -z "${CONF[$1;NETWORK]}" ]; then
		local SHA=$(sha1sum <<<"$1" | head -c 12)
75
		CONF[$1;MAC]=$(getmac $SHA)
76 77
    CONF[$1;TAP]=$(mactotap ${CONF[$1;MAC]} | sed 's/vl-/vc-/')
		CONF[$1;IP4]=192.168.$((193+((0x$SHA / 254) % 62))).$((0x$SHA % 254))
Maria Matejka's avatar
Maria Matejka committed
78 79 80 81 82 83
	else
		read CONF[$1;TAP] CONF[$1;MAC] CONF[$1;IP4] <<<"${CONF[$1;NETWORK]}"
	fi
}


Maria Matejka's avatar
Maria Matejka committed
84 85 86 87
function hostdefaults() {
	if [ -z "${CONF[$HOSTNAME;IMAGE]}" ]; then echo "Error: Image not set"; return 1; fi
	if [ -z "${CONF[$HOSTNAME;ARCH]}" ]; then CONF[$HOSTNAME;ARCH]=x86_64; fi
	if [ -z "${CONF[$HOSTNAME;MEMORY]}" ]; then CONF[$HOSTNAME;MEMORY]=64M; fi
88
	if [ "${CONF[$HOSTNAME;COW]^^}" = "YES" ] || [ "${CONF[$HOSTNAME;COW]}" = "-snapshot" ]; then CONF[$HOSTNAME;COW]=-snapshot; else CONF[$HOSTNAME;COW]=; fi
Maria Matejka's avatar
INIT  
Maria Matejka committed
89

Maria Matejka's avatar
Maria Matejka committed
90
	hostctlnet $HOSTNAME
Maria Matejka's avatar
Maria Matejka committed
91 92 93

	HOSTS[$HOSTNAME]=true
	HOSTNAME=
Maria Matejka's avatar
INIT  
Maria Matejka committed
94 95
}

Maria Matejka's avatar
Maria Matejka committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
function copyhost() {
	local src=$1
	shift
	if [ -z "${HOSTS[$src]}" ]; then
		echo "No host '$src' found to copy from in config."
		exit 2
	fi

	for H in "$@"; do
		eval $(echo ${!CONF[@]} | tr ' ' '\n' | sed -rn "/^$src;/{ s/$src;//; s/.*/CONF[$H;&]=\\\${CONF[$src;&]}/p }")
		hostctlnet $H
		HOSTS[$H]=true
	done
}

function linkhosts() {
Maria Matejka's avatar
Maria Matejka committed
112 113 114 115 116
	local NAME=$1
	local an=$2
	local ai=$3
	local bn=$4
	local bi=$5
117
	
Maria Matejka's avatar
Maria Matejka committed
118 119 120 121
	if [ -z "$an" ] || [ -z "$ai" ] || [ -z "$bn" ] || [ -z "$bi" ]; then
		echo "Link usage: 'Link host IP host IP' in config."
		exit 2
	fi
122

Maria Matejka's avatar
Maria Matejka committed
123
	local SHA=$(sha1sum <<<"$an;$ai;$bn;$bi" | head -c 20)
124 125
	local AMAC=$(getmac ${SHA:0:8})
	local BMAC=$(getmac ${SHA:8:8})
Maria Matejka's avatar
Maria Matejka committed
126
	local TAG=$((100 + (0x${SHA:16:4} % 3800)))
127

Maria Matejka's avatar
Maria Matejka committed
128 129 130
	CONF[$an;NIC]="${CONF[$an;NIC]} $NAME;$AMAC;$TAG;$ai;$bi"
	CONF[$bn;NIC]="${CONF[$bn;NIC]} $NAME;$BMAC;$TAG;$bi;$ai"
}
131

Maria Matejka's avatar
Maria Matejka committed
132 133 134 135 136 137 138 139 140
function nethosts() {
	local SHA=$(sha1sum <<<"$*" | head -c 20)
	local TAG=$((100 + (0x${SHA:0:4} % 3800)))
	local H
	local A
	local MAC

	local NAME=$1
	shift
141

Maria Matejka's avatar
Maria Matejka committed
142 143 144 145 146 147 148 149 150 151 152 153 154
	until [ -z "$1" ]; do
		if [ -z "$2" ]; then
			echo "Missing address for interface $1 in config."
			exit 2
		fi

		H=$1
		A=$2
		SHA=$(sha1sum <<<"$SHA $H $A" | head -c 20)
		MAC=$(getmac ${SHA:0:8})
		shift 2
		CONF[$H;NIC]="${CONF[$H;NIC]} $NAME;$MAC;$TAG;$A;"
	done
Maria Matejka's avatar
Maria Matejka committed
155 156
}

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
function grehosts() {
	local NAME=$1
	local an=$2
	local ai=$3
	local bn=$4
	local bi=$5
	
	if [ -z "$an" ] || [ -z "$ai" ] || [ -z "$bn" ] || [ -z "$bi" ]; then
		echo "Link usage: 'Link host IP host IP' in config."
		exit 2
	fi

	CONF[$an;GRE]="${CONF[$an;GRE]} $NAME;$bn;$ai;$bi"
	CONF[$bn;GRE]="${CONF[$bn;GRE]} $NAME;$an;$bi;$ai"
}

function sockethosts() {
  local NAME=$1
  local PORT=$2
  local an=$3
  local ai=$4

  shift 4

  if [ -z "$PORT" ] || [ -z "$NAME" ] || [ -z "$an" ] || [ -z "$ai" ]; then
    echo "Socket usage: Socket PORT host IP [[host IP] ...]"
    exit 2
  fi

	local SHA=$(sha1sum <<<"$NAME;$PORT;$an;$ai" | head -c 20)
	local AMAC=$(getmac ${SHA:0:8})

  CONF[$an;SOCK]="${CONF[$an;SOCK]} $NAME;listen=127.0.0.1:$PORT;$AMAC;$ai"

  while [ ! -z "$1" ] && [ ! -z "$2" ]; do
    local bn=$1
    local bi=$2
    local SHA=$(sha1sum <<<"$NAME;$PORT;$an;$ai;$bn;$bi" | head -c 20)
    local BMAC=$(getmac ${SHA:0:8})
    shift 2
    CONF[$bn;SOCK]="${CONF[$bn;SOCK]} $NAME;connect=127.0.0.1:$PORT;$BMAC;$bi"
  done

  if [ ! -z "$1" ]; then
    echo "Socket usage: Socket PORT host IP [[host IP] ...]"
    exit 2
  fi
}

function dummynic() {
	local h=$1
	local n=$2
	local v4=$3
	local v6=$4

	if [ -z "$v4" ] || [ -z "$v6" ]; then
		echo "Dummy usage: 'Dummy name IP4 IP6' in config."
		exit 2
	fi

	CONF[$h;DUMMY]="${CONF[$h;DUMMY]} $n;$v4;$v6"
}

varput() {
	local h=$1
	shift

	while [ -n "$1" ]; do
		CONF[$h;VARS]="${CONF[$h;VARS]} $1"
		shift
	done
}

Maria Matejka's avatar
Maria Matejka committed
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
HOSTNAME=
while read item value; do
	if [ -z "$HOSTNAME" ]; then
		if [ -z "$item" ]; then
			continue
		elif [ "${item^^}" = "HOST" ]; then
			HOSTNAME=$value
			continue
		else
			echo "Config must begin by host definition."
			exit 2
		fi
	fi
	
	if [ -z "$item" ]; then continue; fi
Maria Matejka's avatar
INIT  
Maria Matejka committed
245

Maria Matejka's avatar
Maria Matejka committed
246 247 248 249 250 251 252 253 254 255 256 257 258
	case ${item^^} in
		\#*)	continue ;;
		HOST)	hostdefaults
			HOSTNAME=$value
			;;
		IMAGE)	CONF[$HOSTNAME;IMAGE]="$value" ;;
		NETWORK)CONF[$HOSTNAME;NETWORK]="$value" ;;
		CDROM)	CONF[$HOSTNAME;CDROM]="$value" ;;
		ARCH)	CONF[$HOSTNAME;ARCH]="$value" ;;
		MEMORY)	CONF[$HOSTNAME;MEMORY]="$value" ;;
		COW)	CONF[$HOSTNAME;COW]="$value" ;;
		VNC)	CONF[$HOSTNAME;VNCID]="$value" ;;
		TYPE)	CONF[$HOSTNAME;TYPE]="$value" ;;
Maria Matejka's avatar
Maria Matejka committed
259 260
		COPY)	copyhost $value ;;
		LINK)	linkhosts $value ;;
Maria Matejka's avatar
Maria Matejka committed
261
		NET)	nethosts $value ;;
262
		GRE)	grehosts $value ;;
Maria Matejka's avatar
Maria Matejka committed
263
		DUMMY)	dummynic $value ;;
264 265
		VAR)	varput $value ;;
		SOCKET)	sockethosts $value ;;
Maria Matejka's avatar
Maria Matejka committed
266 267 268 269
		*)	echo "Unknown directive '$item' in config"
			exit 2 ;;
	esac
done <$VIRTUALS
Maria Matejka's avatar
INIT  
Maria Matejka committed
270

Maria Matejka's avatar
Maria Matejka committed
271 272 273 274
hostdefaults
HOSTNAME=

function gethost() {
275 276 277 278 279 280 281 282 283 284 285
  local NAME=$1 SUFFIX ID HEXID
  if [ -e $ROOT/run/tmp-$NAME ]; then
    SUFFIX=$(<$ROOT/run/tmp-$NAME)
    ID=$(basename $(readlink -f $ROOT/run/tmp-$NAME))
    ID=${ID##tmp-}
    HEXID=$(printf "%02x" $ID)
    NAME=${NAME%%-$SUFFIX}
  fi

	if ${HOSTS[$NAME]}; then
		eval $(echo ${!CONF[@]} | tr ' ' '\n' | sed -rn "/^$NAME;/{ s/$NAME;//; s/.*/HOST&=\"\\\${CONF[$NAME;&]}\"/p }")
Maria Matejka's avatar
Maria Matejka committed
286
		HOSTNAME=$1
287 288 289 290 291 292 293 294
    if [ -n "$SUFFIX" ]; then
#      echo "Assigned MAC for $NAME is $HOSTMAC, tapname is $HOSTTAP"
      HOSTMAC=$(echo $HOSTMAC | sed "s/^52:54/52:$HEXID/")
      HOSTTAP=$(echo $HOSTTAP | sed "s/^vc-5254/vc-52$HEXID/")
      HOSTIP4=192.168.255.$(($ID % 254))
      HOSTNIC=
#      echo "Changed to $HOSTMAC, tapname $HOSTTAP"
    fi
Maria Matejka's avatar
Maria Matejka committed
295
		return 0
Maria Matejka's avatar
Maria Matejka committed
296
	else
Maria Matejka's avatar
Maria Matejka committed
297 298
		echo "Unknown host: $1"
		return 1
Maria Matejka's avatar
Maria Matejka committed
299
	fi
Maria Matejka's avatar
INIT  
Maria Matejka committed
300
}
Maria Matejka's avatar
Maria Matejka committed
301

Maria Matejka's avatar
Maria Matejka committed
302
function hostlist() {
303
	for H in ${!HOSTS[@]}; do echo $H; ls $ROOT/run/tmp-$H-* 2>/dev/null | sed "s#.*run/tmp-##"; done | sort
Maria Matejka's avatar
Maria Matejka committed
304
}