Permalink
Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign up
Fetching contributors…
Cannot retrieve contributors at this time.
Cannot retrieve contributors at this time
| #!/bin/sh | |
| set -e | |
| SCRIPT_VERSION="(unreleased version)" | |
| usage() { | |
| echo "Usage:" | |
| echo "weave setup" | |
| echo "weave launch [-password <password> | -passwordfile <path>] <peer> ..." | |
| echo "weave launch-dns <cidr>" | |
| echo "weave connect <peer>" | |
| echo "weave run [--with-dns] <cidr> <docker run args> ..." | |
| echo "weave start <cidr> <container_id>" | |
| echo "weave attach <cidr> <container_id>" | |
| echo "weave detach <cidr> <container_id>" | |
| echo "weave expose <cidr>" | |
| echo "weave hide <cidr>" | |
| echo "weave ps" | |
| echo "weave status" | |
| echo "weave version" | |
| echo "weave stop" | |
| echo "weave stop-dns" | |
| echo "weave reset" | |
| echo | |
| echo "where <peer> is of the form <ip_address_or_fqdn>[:<port>], and" | |
| echo " <cidr> is of the form <ip_address>/<routing_prefix_length>" | |
| exit 1 | |
| } | |
| [ $(id -u) = 0 ] || { | |
| echo "weave must be run as 'root'" >&2 | |
| exit 1 | |
| } | |
| [ $# -gt 0 ] || usage | |
| if [ "$SCRIPT_VERSION" = "(unreleased version)" ] ; then | |
| IMAGE_VERSION=latest | |
| else | |
| IMAGE_VERSION=$SCRIPT_VERSION | |
| fi | |
| IMAGE_VERSION=${VERSION:-$IMAGE_VERSION} | |
| BASE_IMAGE=zettio/weave | |
| BASE_DNS_IMAGE=zettio/weavedns | |
| BASE_TOOLS_IMAGE=zettio/weavetools | |
| IMAGE=$BASE_IMAGE:$IMAGE_VERSION | |
| DNS_IMAGE=$BASE_DNS_IMAGE:$IMAGE_VERSION | |
| TOOLS_IMAGE=$BASE_TOOLS_IMAGE:$IMAGE_VERSION | |
| CONTAINER_NAME=weave | |
| DNS_CONTAINER_NAME=weavedns | |
| BRIDGE=weave | |
| CONTAINER_IFNAME=ethwe | |
| MTU=65535 | |
| PORT=6783 | |
| HTTP_PORT=6784 | |
| DNS_HTTP_PORT=6785 | |
| DOCKER_BRIDGE=${DOCKER_BRIDGE:-docker0} | |
| COMMAND=$1 | |
| shift 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 | |
| } | |
| run_tool() { | |
| TOOL_NET=$1 | |
| TOOL_COMMAND=$2 | |
| shift 2 | |
| docker run --rm --privileged --net=$TOOL_NET $TOOLS_IMAGE /bin/$TOOL_COMMAND "$@" | |
| } | |
| is_cidr() { | |
| # The regexp here is far from precise, but good enough. | |
| echo "$1" | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$' >/dev/null | |
| } | |
| validate_cidr() { | |
| if ! is_cidr "$1" ; then | |
| echo "Invalid CIDR: $1" >&2 | |
| echo "CIDR must of be of form <ip_address>/<routing_prefix_length>, e.g. 10.0.1.1/24" >&2 | |
| exit 1 | |
| fi | |
| } | |
| run_iptables() { | |
| # -w is recent addition to iptables | |
| if [ -z "$CHECKED_IPTABLES_W" ] ; then | |
| if iptables -S -w >/dev/null 2>&1 ; then | |
| IPTABLES_W=-w | |
| fi | |
| CHECKED_IPTABLES_W=1 | |
| fi | |
| iptables $IPTABLES_W "$@" | |
| } | |
| # Add a rule to iptables, if it doesn't exist already | |
| add_iptables_rule() { | |
| IPTABLES_TABLE="$1" | |
| shift 1 | |
| if ! run_iptables -t $IPTABLES_TABLE -C "$@" >/dev/null 2>&1 | |
| then | |
| run_iptables -t $IPTABLES_TABLE -A "$@" >/dev/null | |
| fi | |
| } | |
| # Delete a rule from iptables, if it exist | |
| delete_iptables_rule() { | |
| IPTABLES_TABLE="$1" | |
| shift 1 | |
| if run_iptables -t $IPTABLES_TABLE -C "$@" >/dev/null 2>&1 | |
| then | |
| run_iptables -t $IPTABLES_TABLE -D "$@" >/dev/null | |
| fi | |
| } | |
| create_bridge() { | |
| [ ! -d /sys/class/net/$BRIDGE ] && { | |
| ip link add name $BRIDGE type bridge | |
| ip link set dev $BRIDGE address 7a:$(od -txC -An -N5 /dev/urandom | 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 | |
| # disable offloading | |
| run_tool host ethtool -K $BRIDGE tx off >/dev/null | |
| # Work around the situation where there are no rules allowing traffic | |
| # across our bridge. E.g. ufw | |
| add_iptables_rule filter FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT | |
| # create a chain for masquerading | |
| run_iptables -t nat -N WEAVE >/dev/null 2>&1 || true | |
| add_iptables_rule nat POSTROUTING -j WEAVE | |
| } | |
| ip link set dev $BRIDGE up | |
| } | |
| destroy_bridge() { | |
| if [ -d /sys/class/net/$BRIDGE ] ; then | |
| ip link del dev $BRIDGE | |
| fi | |
| run_iptables -t filter -D FORWARD -i $BRIDGE -o $BRIDGE -j ACCEPT 2>/dev/null || true | |
| run_iptables -t nat -F WEAVE >/dev/null 2>&1 || true | |
| run_iptables -t nat -D POSTROUTING -j WEAVE >/dev/null 2>&1 || true | |
| run_iptables -t nat -X WEAVE >/dev/null 2>&1 || true | |
| } | |
| docker_bridge_ip() { | |
| DOCKER_BRIDGE_IP=$(ip -4 addr show dev $DOCKER_BRIDGE | grep -m1 -o 'inet [.0-9]*') | |
| DOCKER_BRIDGE_IP=${DOCKER_BRIDGE_IP#inet } | |
| } | |
| # the following borrows from https://github.com/jpetazzo/pipework | |
| # Set $NETNS to the network namespace of container $1, $LOCAL_IFNAME | |
| # and $GUEST_IFNAME to suitable names for two ends of a veth pair, | |
| # specific to the container, and execute args $2 $3 ... as a command. | |
| # If an error is caused by container dying, swallow output from error. | |
| with_container_netns () { | |
| CONTAINER="$1" | |
| CONTAINER_PID=$(docker inspect --format='{{ .State.Pid }}' $CONTAINER) | |
| if [ "$CONTAINER_PID" = 0 ] ; then | |
| echo "Container $CONTAINER not running." >&2 | |
| exit 1 | |
| fi | |
| if [ "$CONTAINER_PID" = "<no value>" ] ; then | |
| echo "Container $CONTAINER unknown to Docker." >&2 | |
| exit 1 | |
| fi | |
| NETNS=$CONTAINER_PID | |
| [ ! -d /var/run/netns ] && mkdir -p /var/run/netns | |
| rm -f /var/run/netns/$NETNS | |
| ln -s /proc/$CONTAINER_PID/ns/net /var/run/netns/$NETNS | |
| LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${CONTAINER_PID}" | |
| GUEST_IFNAME="v${CONTAINER_IFNAME}pg${CONTAINER_PID}" | |
| IP_TMPOUT=/tmp/weave_ip_out_$$ | |
| IP_TMPERR=/tmp/weave_ip_err_$$ | |
| rm -f $IP_TMPOUT $IP_TMPERR | |
| # Run the wrapped command | |
| STATUS=0 | |
| shift 1 | |
| if ! "$@" >$IP_TMPOUT 2>$IP_TMPERR ; then | |
| STATUS=1 | |
| if [ "$(docker inspect --format='{{ .State.Pid }}' $CONTAINER)" != "$CONTAINER_PID" ] ; then | |
| echo "Container $CONTAINER died" >&2 | |
| else | |
| echo "Failure during network configuration for container $CONTAINER:" >&2 | |
| cat $IP_TMPERR >&2 | |
| fi | |
| else | |
| cat $IP_TMPOUT | |
| cat $IP_TMPERR >&2 | |
| fi | |
| rm -f $IP_TMPOUT $IP_TMPERR /var/run/netns/$NETNS | |
| return $STATUS | |
| } | |
| connect_container_to_bridge() { | |
| if [ "$(readlink /proc/$CONTAINER_PID/ns/net)" = "$(readlink /proc/$$/ns/net)" ] ; then | |
| echo "Container is running in the host network namespace, and therefore cannot be" >&2 | |
| echo "connected to weave. Perhaps the container was started with --net=host." >&2 | |
| return 1 | |
| fi | |
| if ! ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU ; then | |
| return 1 | |
| fi | |
| if run_tool host ethtool -K $GUEST_IFNAME tx off >/dev/null && | |
| ip link set $LOCAL_IFNAME master $BRIDGE && | |
| ip link set $LOCAL_IFNAME up && | |
| ip link set $GUEST_IFNAME netns $NETNS ; then | |
| ip netns exec $NETNS ip link set $GUEST_IFNAME name $CONTAINER_IFNAME | |
| else | |
| # failed before we assigned the veth to the container's | |
| # namespace - delete it | |
| ip link del $LOCAL_IFNAME type veth || true | |
| return 1 | |
| fi | |
| } | |
| launch() { | |
| if ! ip netns exec $NETNS ip link show eth0 >/dev/null ; then | |
| echo "Perhaps you are running the docker daemon with container networking disabled (-b=none)." >&2 | |
| return 1 | |
| fi | |
| connect_container_to_bridge && | |
| run_tool container:$CONTAINER ethtool -K eth0 tx off >/dev/null && | |
| ip netns exec $NETNS ip link set $CONTAINER_IFNAME up | |
| } | |
| attach() { | |
| if ip netns exec $NETNS ip link show $CONTAINER_IFNAME >/dev/null 2>&1 ; then | |
| # container already has the expected network interface, so assume we set it up already; | |
| # just add the IP address. | |
| if ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then | |
| # address was there already | |
| return 0 | |
| fi | |
| if ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME ; then | |
| return 1 | |
| fi | |
| return 0 | |
| fi | |
| if ! connect_container_to_bridge || | |
| ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME || | |
| ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up ; then | |
| return 1 | |
| fi | |
| # Route multicast packets across the weave network. | |
| if ! ip netns exec $NETNS ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then | |
| ip netns exec $NETNS ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME | |
| fi | |
| } | |
| detach() { | |
| if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $1 >/dev/null ; then | |
| # address is not there, leave the device alone | |
| return 0 | |
| fi | |
| if ! ip netns exec $NETNS ip addr del $1 dev $CONTAINER_IFNAME ; then | |
| return 1 | |
| fi | |
| if [ -n "$(ip netns exec $NETNS ip -f inet addr show dev $CONTAINER_IFNAME)" ] ; then | |
| # other addresses are left, leave the device alone | |
| return 0 | |
| fi | |
| # Deleting the interface will delete the multicast route we set up | |
| ip netns exec $NETNS ip link del $CONTAINER_IFNAME type veth | |
| } | |
| # Call url $4 with http verb $3 on container $1 at port $2 | |
| http_call() { | |
| if ! status=$(docker inspect --format='{{ .State.Running }} {{ .NetworkSettings.IPAddress }}' $1 2>/dev/null); then | |
| echo "$1 container is not present; have you launched it?" >&2 | |
| return 1 | |
| fi | |
| case "$status" in | |
| "true ") | |
| echo "$1 container has no IP address; is Docker networking enabled?" >&2 | |
| return 1 | |
| ;; | |
| true*) | |
| ip="${status#true }" | |
| ;; | |
| *) | |
| echo "$1 container is not running." >&2 | |
| return 1 | |
| ;; | |
| esac | |
| shift 1 | |
| http_call_ip $ip "$@" | |
| } | |
| http_call_ip() { | |
| ip="$1" | |
| port="$2" | |
| http_verb="$3" | |
| url="$4" | |
| shift 4 | |
| if command_exists curl ; then | |
| curl -s -X $http_verb "$@" http://$ip:$port$url | |
| else | |
| echo "Cannot find curl, which is required for this operation." >&2 | |
| exit 1 | |
| fi | |
| } | |
| # Perform operation $1 on container ID $2 to local DNS database at address $3 | |
| # This function is only called where we know $2 is a valid container name | |
| tell_dns() { | |
| if ! status=$(docker inspect --format='{{ .State.Running }}' $DNS_CONTAINER_NAME 2>/dev/null) || [ "$status" != "true" ] ; then | |
| # weavedns not running - silently return | |
| return | |
| fi | |
| # get the long form of the container ID | |
| CONTAINER=$(docker inspect --format='{{ .Id }}' $2 2>/dev/null) | |
| # extract IP address and routing prefix from CIDR | |
| WEAVE_ADDR_IP=$(echo $3 | sed -e 's/\([^/]*\)\/\(.*\)/\1/') | |
| MORE_ARGS=$(docker inspect --format='--data-urlencode fqdn={{ .Config.Hostname }}.{{ .Config.Domainname }}.' $CONTAINER 2>/dev/null) && true | |
| http_call $DNS_CONTAINER_NAME $DNS_HTTP_PORT $1 /name/$CONTAINER/$WEAVE_ADDR_IP $MORE_ARGS || true | |
| } | |
| # Tell the newly-started weaveDNS about existing weave IPs | |
| populate_dns() { | |
| DNS_IP=$(docker inspect --format='{{ .NetworkSettings.IPAddress }}' $DNS_CONTAINER_NAME) | |
| WAIT_TIME=1 | |
| while ! http_call_ip $DNS_IP $DNS_HTTP_PORT GET /status >/dev/null && [ $WAIT_TIME -lt 4 ]; do | |
| sleep $WAIT_TIME | |
| WAIT_TIME=$((WAIT_TIME+1)) | |
| done | |
| if [ $WAIT_TIME = 4 ]; then | |
| echo "Timed out waiting for weaveDNS container to start." >&2 | |
| echo "If running, it will not be pre-populated." >&2 | |
| fi | |
| for CONTAINER in $(docker ps -q --no-trunc); do | |
| MORE_ARGS=$(docker inspect --format='--data-urlencode fqdn={{ .Config.Hostname }}.{{ .Config.Domainname }}.' $CONTAINER 2>/dev/null) && true | |
| if CONTAINER_ADDRS=$(with_container_netns $CONTAINER container_weave_addrs 2>&1) ; then | |
| CONTAINER_IPS=$(echo "$CONTAINER_ADDRS" | grep -o 'inet .*' | sed -e 's/inet \([^/]*\)\/\(.*\)/\1/') | |
| for IP in $CONTAINER_IPS; do | |
| http_call_ip $DNS_IP $DNS_HTTP_PORT PUT /name/$CONTAINER/$IP $MORE_ARGS | |
| done | |
| fi | |
| done | |
| } | |
| # Check that a container named $1 with image $2 is not running | |
| check_not_running() { | |
| case $(docker inspect --format='{{ .State.Running }} {{ .Config.Image }}' $1 2>/dev/null) in | |
| "true $2") | |
| echo "$1 is already running." >&2 | |
| exit 1 | |
| ;; | |
| "true $2:"*) | |
| echo "$1 is already running." >&2 | |
| exit 1 | |
| ;; | |
| "false $2") | |
| docker rm $1 >/dev/null | |
| ;; | |
| "false $2:"*) | |
| docker rm $1 >/dev/null | |
| ;; | |
| true*) | |
| echo "Found another running container named '$1'. Aborting." >&2 | |
| exit 1 | |
| ;; | |
| false*) | |
| echo "Found another container named '$1'. Aborting." >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| } | |
| container_weave_addrs() { | |
| ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | |
| } | |
| uname -s -r | sed -n 's|^\([^ ]*\) \([0-9]\+\)\.\([0-9]\+\).*|\1 \2 \3|p' | { | |
| if ! read sys maj min ; then | |
| echo "ERROR: Unable to parse operating system version $(uname -s -r)" >&2 | |
| exit 1 | |
| fi | |
| if [ "$sys" != 'Linux' ] ; then | |
| echo "ERROR: Operating systems other than Linux are not supported (you have $(uname -s -r))" >&2 | |
| exit 1 | |
| fi | |
| if ! [ \( "$maj" -eq 3 -a "$min" -ge 5 \) -o "$maj" -gt 3 ] ; then | |
| echo "WARNING: Linux kernel version 3.5 or newer is required (you have ${maj}.${min})" >&2 | |
| fi | |
| } | |
| ask_version() { | |
| if ! DOCKERIMAGE=$(docker inspect --format='{{ .Image }}' $1 2>/dev/null) ; then | |
| if ! DOCKERIMAGE=$(docker inspect --format='{{ .Id }}' $2 2>/dev/null) ; then | |
| echo "Unable to find $2 image." >&2 | |
| fi | |
| fi | |
| [ -n "$DOCKERIMAGE" ] && docker run --rm $DOCKERIMAGE --version | |
| } | |
| if ! command_exists ip ; then | |
| echo "ERROR: ip utility is missing. Please install it." >&2 | |
| exit 1 | |
| fi | |
| if ! ip netns list >/dev/null 2>&1 ; then | |
| echo "ERROR: $(ip -V) does not support network namespaces." >&2 | |
| echo " Please install iproute2-ss111010 or later." >&2 | |
| exit 1 | |
| fi | |
| if ! DOCKER_VERSION=$(docker -v | sed -n 's|^Docker version \([0-9]\+\.[0-9]\+.[0-9]\+\).*|\1|p') || [ -z "$DOCKER_VERSION" ] ; then | |
| echo "ERROR: Unable to parse docker version" >&2 | |
| exit 1 | |
| fi | |
| # guard against https://github.com/docker/docker/issues/8632 | |
| if [ "$DOCKER_VERSION" = "1.3.0" ] ; then | |
| echo "You are running Docker version $DOCKER_VERSION, which contains a bug that prevents weave from working properly. Please upgrade." >&2 | |
| exit 1 | |
| fi | |
| DOCKER_VERSION_MAJOR=$(echo "$DOCKER_VERSION" | cut -d. -f 1) | |
| DOCKER_VERSION_MINOR=$(echo "$DOCKER_VERSION" | cut -d. -f 2) | |
| DOCKER_VERSION_PATCH=$(echo "$DOCKER_VERSION" | cut -d. -f 3) | |
| case "$COMMAND" in | |
| setup) | |
| for img in $IMAGE $DNS_IMAGE $TOOLS_IMAGE ; do | |
| docker pull $img | |
| done | |
| ;; | |
| launch) | |
| check_not_running $CONTAINER_NAME $BASE_IMAGE | |
| create_bridge | |
| # 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) | |
| # backward compatibility... | |
| if is_cidr "$1" ; then | |
| echo "WARNING: $1 parameter ignored; 'weave launch' no longer takes a CIDR as the first parameter" >&2 | |
| shift 1 | |
| fi | |
| if [ "$1" = "-password" ] ; then | |
| [ $# -gt 1 ] || usage | |
| PASSWORD=$2 | |
| shift 2 | |
| elif [ "$1" = "-passwordfile" ] ; then | |
| [ $# -gt 1 ] || usage | |
| PASSWORDFILE=$2 | |
| shift 2 | |
| fi | |
| # Set WEAVE_DOCKER_ARGS in the environment in order to supply | |
| # additional parameters, such as resource limits, to docker | |
| # when launching the weave container. | |
| CONTAINER=$(docker run --privileged -d --name=$CONTAINER_NAME \ | |
| -p $PORT:$PORT/tcp -p $PORT:$PORT/udp \ | |
| ${PASSWORD:+-e WEAVE_PASSWORD="$PASSWORD"} ${PASSWORDFILE:+--env-file="$PASSWORDFILE"} \ | |
| $WEAVE_DOCKER_ARGS $IMAGE -name $MACADDR -iface $CONTAINER_IFNAME "$@") | |
| with_container_netns $CONTAINER launch >/dev/null | |
| echo $CONTAINER | |
| ;; | |
| launch-dns) | |
| [ $# -gt 0 ] || usage | |
| CIDR=$1 | |
| shift 1 | |
| check_not_running $DNS_CONTAINER_NAME $BASE_DNS_IMAGE | |
| create_bridge | |
| docker_bridge_ip | |
| DNS_CONTAINER=$(docker run --privileged -d --name=$DNS_CONTAINER_NAME \ | |
| -p $DOCKER_BRIDGE_IP:53:53/udp -v /var/run/docker.sock:/var/run/docker.sock \ | |
| $DNS_IMAGE -iface $CONTAINER_IFNAME "$@") | |
| with_container_netns $DNS_CONTAINER attach $CIDR >/dev/null | |
| populate_dns | |
| echo $DNS_CONTAINER | |
| ;; | |
| connect) | |
| [ $# -eq 1 ] || usage | |
| http_call $CONTAINER_NAME $HTTP_PORT POST /connect -d "peer=$1" | |
| ;; | |
| status) | |
| http_call $CONTAINER_NAME $HTTP_PORT GET /status | |
| ;; | |
| ps) | |
| [ $# -eq 0 ] || usage | |
| for CONTAINER_ID in $(docker ps -q) ; do | |
| if CONTAINER_ADDRS=$(with_container_netns $CONTAINER_ID container_weave_addrs 2>&1) ; then | |
| CONTAINER_MAC=$(echo "$CONTAINER_ADDRS" | grep -o 'link/ether .*' | cut -d ' ' -f 2) | |
| CONTAINER_IPS=$(echo "$CONTAINER_ADDRS" | grep -o 'inet .*' | cut -d ' ' -f 2) | |
| echo $CONTAINER_ID $CONTAINER_MAC $CONTAINER_IPS | |
| fi | |
| done | |
| ;; | |
| version) | |
| [ $# -eq 0 ] || usage | |
| echo weave script $SCRIPT_VERSION | |
| ask_version $CONTAINER_NAME $IMAGE | |
| ask_version $DNS_CONTAINER_NAME $DNS_IMAGE | |
| if ! TOOLS_IMAGE_ID=$(docker inspect --format='{{ .Id }}' $TOOLS_IMAGE 2>/dev/null) ; then | |
| echo "Unable to find $TOOLS_IMAGE image." >&2 | |
| else | |
| TOOLS_VERSION=$(docker images --no-trunc | grep $TOOLS_IMAGE_ID | grep -v latest | tr -s ' ' | cut -d ' ' -f 2 | tr "\n" ' ') | |
| if [ -n "$TOOLS_VERSION" ] ; then | |
| echo "weave tools $TOOLS_VERSION" | |
| else | |
| echo "weave tools (unreleased version)" | |
| fi | |
| fi | |
| ;; | |
| run) | |
| [ $# -gt 0 ] || usage | |
| if [ "$1" = "--with-dns" ] ; then | |
| shift 1 | |
| if [ \( "$DOCKER_VERSION_MAJOR" -lt 1 \) -o \ | |
| \( "$DOCKER_VERSION_MAJOR" -eq 1 -a \ | |
| "$DOCKER_VERSION_MINOR" -lt 2 \) ] ; then | |
| echo "ERROR: The '--with-dns' option requires Docker 1.2.0 or later; you are running $DOCKER_VERSION" >&2 | |
| exit 1 | |
| fi | |
| docker_bridge_ip | |
| DNS_ARG="--dns $DOCKER_BRIDGE_IP" | |
| DNS_SEARCH_ARG="--dns-search=." | |
| for arg in "$@"; do | |
| case $arg in | |
| --dns-search=*) | |
| DNS_SEARCH_ARG="" | |
| ;; | |
| *) | |
| ;; | |
| esac; | |
| done | |
| fi | |
| validate_cidr $1 | |
| CIDR=$1 | |
| shift 1 | |
| create_bridge | |
| CONTAINER=$(docker run $DNS_ARG $DNS_SEARCH_ARG -d "$@") | |
| with_container_netns $CONTAINER attach $CIDR >/dev/null | |
| tell_dns PUT $CONTAINER $CIDR | |
| echo $CONTAINER | |
| ;; | |
| start) | |
| [ $# -eq 2 ] || usage | |
| validate_cidr $1 | |
| create_bridge | |
| CONTAINER=$(docker start $2) | |
| with_container_netns $CONTAINER attach $1 >/dev/null | |
| tell_dns PUT $CONTAINER $1 | |
| echo $CONTAINER | |
| ;; | |
| attach) | |
| [ $# -eq 2 ] || usage | |
| validate_cidr $1 | |
| create_bridge | |
| with_container_netns $2 attach $1 >/dev/null | |
| tell_dns PUT $2 $1 | |
| ;; | |
| detach) | |
| [ $# -eq 2 ] || usage | |
| validate_cidr $1 | |
| with_container_netns $2 detach $1 >/dev/null | |
| tell_dns DELETE $2 $1 | |
| ;; | |
| expose) | |
| [ $# -eq 1 ] || usage | |
| validate_cidr $1 | |
| create_bridge | |
| if ! ip addr show dev $BRIDGE | grep -qF $1 | |
| then | |
| ip addr add dev $BRIDGE $1 | |
| add_iptables_rule nat WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE | |
| add_iptables_rule nat WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE | |
| fi | |
| ;; | |
| hide) | |
| [ $# -eq 1 ] || usage | |
| validate_cidr $1 | |
| create_bridge | |
| if ip addr show dev $BRIDGE | grep -qF $1 | |
| then | |
| ip addr del dev $BRIDGE $1 | |
| delete_iptables_rule nat WEAVE -o $BRIDGE ! -s $1 -j MASQUERADE | |
| delete_iptables_rule nat WEAVE -s $1 ! -o $BRIDGE -j MASQUERADE | |
| fi | |
| ;; | |
| stop) | |
| [ $# -eq 0 ] || usage | |
| if ! docker kill $CONTAINER_NAME >/dev/null 2>&1 ; then | |
| echo "Weave is not running." >&2 | |
| fi | |
| docker rm -f $CONTAINER_NAME >/dev/null 2>&1 || true | |
| run_tool host conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true | |
| ;; | |
| stop-dns) | |
| [ $# -eq 0 ] || usage | |
| if ! docker kill $DNS_CONTAINER_NAME >/dev/null 2>&1 ; then | |
| echo "WeaveDNS is not running." >&2 | |
| fi | |
| docker rm -f $DNS_CONTAINER_NAME >/dev/null 2>&1 || true | |
| ;; | |
| reset) | |
| [ $# -eq 0 ] || usage | |
| docker kill $CONTAINER_NAME >/dev/null 2>&1 || true | |
| docker kill $DNS_CONTAINER_NAME >/dev/null 2>&1 || true | |
| docker rm -f $CONTAINER_NAME >/dev/null 2>&1 || true | |
| docker rm -f $DNS_CONTAINER_NAME >/dev/null 2>&1 || true | |
| run_tool host conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true | |
| destroy_bridge | |
| for LOCAL_IFNAME in $(ip link show | grep v${CONTAINER_IFNAME}pl | cut -d ' ' -f 2 | tr -d ':') ; do | |
| ip link del $LOCAL_IFNAME | |
| done | |
| ;; | |
| *) | |
| echo "Unknown weave command '$COMMAND'" >&2 | |
| usage | |
| ;; | |
| esac |