Files
weave/weaver/weave
T

125 lines
3.7 KiB
Bash
Executable File

#!/bin/sh
set -e
BRIDGE=weave
CONTAINER_IFNAME=ethwe
MTU=65535
SCRIPT_DIR=$(dirname $(readlink -f $0))
COMMAND=$1
IPADDR=$2
usage() {
echo "Usage:"
echo "weave launch <ipaddr>/<subnet> [-passwd <passwd>] <peer_host> ..."
echo "weave run <ipaddr>/<subnet> <docker run args> ..."
echo "weave status"
exit 1
}
# utility function to check whether a command can be executed by the shell
# see http://stackoverflow.com/questions/592620/how-to-check-if-a-program-exists-from-a-bash-script
command_exists () {
command -v $1 >/dev/null 2>&1
}
if [ "$COMMAND" != "status" -a "$#" -lt 2 ]; then
usage
exit 1
fi
[ `id -u` = 0 ] || {
echo "weave must be run as 'root'"
exit 1
}
# pre-create bridge so we can set the MTU
[ ! -d /sys/class/net/$BRIDGE ] && {
ip link add dev $BRIDGE type bridge
ip link set dev $BRIDGE address 7a:$(od -txC -An -N5 /dev/random | tr \ : | tail -c+2)
# attempting to set the bridge MTU to a high value directly
# fails. Bridges take the lowest MTU of their interfaces. So
# instead we create a temporary interface with the desired MTU,
# attach that to the bridge, and then remove it again.
ip link add name v${CONTAINER_IFNAME}du mtu $MTU type dummy
ip link set dev v${CONTAINER_IFNAME}du master $BRIDGE
ip link del dev v${CONTAINER_IFNAME}du
ip link set dev $BRIDGE up
}
# We set the router name to the bridge mac since that is stable across
# re-creations of the containers.
#
# TODO use the mac of one of the physical host interfaces (eth0,
# wlan0, etc) so the name becomes stable across host restarts.
MACADDR=`cat /sys/class/net/$BRIDGE/address`
case "$COMMAND" in
launch)
shift 2
CONTAINER=$(docker run --privileged -d --name=weave -p 6783:6783/tcp -p 6783:6783/udp $WEAVE_DOCKER_ARGS zettio/weave -name $MACADDR "$@")
IFACE=eth0
;;
status)
DOCKERIP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' weave)
if command_exists wget ; then
wget -O - -q $DOCKERIP:6784/status
elif command_exists curl ; then
curl $DOCKERIP:6784/status
else
echo "weave status needs either curl or wget to function" >&2
exit 1
fi
# return the status from the wget or curl command, so if they fail then we fail.
exit $?
;;
run)
shift 2
CONTAINER=$(docker run -d "$@")
IFACE=$CONTAINER_IFNAME
;;
*)
echo "Unknown weave command '$COMMAND'"
usage
;;
esac
# the following borrows from https://github.com/jpetazzo/pipework
DOCKERPID=$(docker inspect --format='{{ .State.Pid }}' $CONTAINER)
[ "$DOCKERPID" = 0 ] && {
echo "Docker inspect returned invalid PID 0"
exit 1
}
[ "$DOCKERPID" = "<no value>" ] && {
echo "Container $CONTAINER unknown to Docker."
exit 1
}
NSPID=$DOCKERPID
[ ! -d /var/run/netns ] && mkdir -p /var/run/netns
[ -f /var/run/netns/$NSPID ] && rm -f /var/run/netns/$NSPID
ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID
LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}"
GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}"
ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU
ip link set $LOCAL_IFNAME master $BRIDGE
ip link set $LOCAL_IFNAME up
ip link set $GUEST_IFNAME netns $NSPID
ip netns exec $NSPID ip link set $GUEST_IFNAME name $CONTAINER_IFNAME
ip netns exec $NSPID ip addr add $IPADDR dev $CONTAINER_IFNAME
ip netns exec $NSPID ip link set $CONTAINER_IFNAME up
if command_exists ethtool
then
ip netns exec $NSPID ethtool -K $IFACE tx off > /dev/null
else
echo "Cannot find ethtool; continuing without it" >&2
fi
[ -f /var/run/netns/$NSPID ] && rm -f /var/run/netns/$NSPID
echo $CONTAINER