There are two problems with obtaining the proxy status via the normal proxy endpoint... 1. when TLS is enabled, this requires using TLS at the client end 2. the status URL is mixed in with the docker remote API, which is rather unclean There is limited value to having some status output from the proxy, since all the output is constant. So instead we log the version and command line args, and in `weave status` only report whether the proxy is running. We still want a way to wait for the proxy to start up, and log a nice error if it dies. We do this by polling the docker logs for a startup message. Fixes #877. Fixes #876. Undoes most of #756, #800, #854.
1150 lines
37 KiB
Bash
Executable File
1150 lines
37 KiB
Bash
Executable File
#!/bin/sh
|
|
set -e
|
|
|
|
[ -n "$WEAVE_DEBUG" ] && set -x
|
|
|
|
SCRIPT_VERSION="(unreleased version)"
|
|
if [ "$SCRIPT_VERSION" = "(unreleased version)" ] ; then
|
|
IMAGE_VERSION=latest
|
|
else
|
|
IMAGE_VERSION=$SCRIPT_VERSION
|
|
fi
|
|
IMAGE_VERSION=${VERSION:-$IMAGE_VERSION}
|
|
|
|
# These are potentially used for remote execs, and have defaults, so
|
|
# we introduce them here
|
|
DOCKERHUB_USER=weaveworks
|
|
BASE_EXEC_IMAGE=$DOCKERHUB_USER/weaveexec
|
|
EXEC_IMAGE=$BASE_EXEC_IMAGE:$IMAGE_VERSION
|
|
|
|
# Define some regular expressions for matching addresses.
|
|
# The regexp here is far from precise, but good enough.
|
|
IP_REGEXP="[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}"
|
|
CIDR_REGEXP="$IP_REGEXP/[0-9]{1,2}"
|
|
|
|
usage() {
|
|
echo "Usage:"
|
|
echo "weave setup"
|
|
echo "weave launch [-password <password>] [-nickname <nickname>] [-nodiscovery]"
|
|
echo " [-iprange <cidr>] <peer> ..."
|
|
echo "weave launch-dns <cidr>"
|
|
echo "weave launch-proxy [-H <docker_endpoint>] [--with-dns] [--with-ipam]"
|
|
echo "weave connect [--replace] [<peer> ...]"
|
|
echo "weave forget <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> [<cidr> ...] <container_id>"
|
|
echo "weave dns-add <ip_address> [<ip_address> ...] <container_id> [-h <fqdn>]"
|
|
echo "weave dns-remove <ip_address> [<ip_address> ...] <container_id> [-h <fqdn>]"
|
|
echo "weave expose [<cidr> ...] [-h <fqdn>]"
|
|
echo "weave hide [<cidr> ...]"
|
|
echo "weave ps [<container_id> ...]"
|
|
echo "weave status"
|
|
echo "weave version"
|
|
echo "weave stop"
|
|
echo "weave stop-dns"
|
|
echo "weave stop-proxy"
|
|
echo "weave reset"
|
|
echo "weave rmpeer <peer_id>"
|
|
echo
|
|
echo "where <peer> = <ip_address_or_fqdn>[:<port>]"
|
|
echo " <cidr> = <ip_address>/<routing_prefix_length>"
|
|
echo " <peer_id> = <nickname> or weave internal peer ID"
|
|
exit 1
|
|
}
|
|
|
|
exec_remote() {
|
|
docker $DOCKER_CLIENT_ARGS run --rm --privileged --net=host \
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
-v /proc:/hostproc \
|
|
-e PROCFS=/hostproc \
|
|
-e VERSION \
|
|
-e WEAVE_DEBUG \
|
|
-e WEAVE_DOCKER_ARGS \
|
|
-e WEAVEDNS_DOCKER_ARGS \
|
|
-e WEAVEPROXY_DOCKER_ARGS \
|
|
-e WEAVE_PASSWORD \
|
|
-e WEAVE_PORT \
|
|
-e WEAVE_CONTAINER_NAME \
|
|
-e DOCKER_BRIDGE \
|
|
$WEAVEEXEC_DOCKER_ARGS $EXEC_IMAGE --local "$@"
|
|
}
|
|
|
|
check_docker_version() {
|
|
if ! DOCKER_VERSION=$(docker -v | sed -n -e 's|^Docker version \([0-9][0-9]*\.[0-9][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
|
|
}
|
|
|
|
is_cidr() {
|
|
echo "$1" | grep -E "^$CIDR_REGEXP$" >/dev/null
|
|
}
|
|
|
|
validate_cidr() {
|
|
if ! is_cidr "$1" ; then
|
|
echo "Invalid address prefix: $1" >&2
|
|
echo "Must be in CIDR notation <ip_address>/<prefix_length>, e.g. 10.2.1.1/24" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
collect_cidr_args() {
|
|
CIDR_ARGS=""
|
|
CIDR_COUNT=0
|
|
while is_cidr "$1" ; do
|
|
CIDR_ARGS="$CIDR_ARGS $1"
|
|
CIDR_COUNT=$((CIDR_COUNT + 1))
|
|
shift 1
|
|
done
|
|
}
|
|
|
|
is_ip() {
|
|
echo "$1" | grep -E "^$IP_REGEXP$" >/dev/null
|
|
}
|
|
|
|
validate_ip() {
|
|
if ! is_ip "$1" ; then
|
|
echo "Invalid IP: $1" >&2
|
|
echo "IP must be of the form <aaa.bbb.ccc.ddd>, e.g. 10.2.1.1" >&2
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
collect_ip_args() {
|
|
IP_ARGS=""
|
|
IP_COUNT=0
|
|
while is_ip "$1" ; do
|
|
IP_ARGS="$IP_ARGS $1"
|
|
IP_COUNT=$((IP_COUNT + 1))
|
|
shift 1
|
|
done
|
|
if [ $IP_COUNT -eq 0 ] ; then
|
|
[ $# -gt 0 ] && validate_ip "$1" || usage
|
|
fi
|
|
}
|
|
|
|
# "run" is a special case because we want to use docker directly,
|
|
# rather than the docker in $EXEC_IMAGE remotely. That's because we
|
|
# are passing arbitrary arguments on to docker run, and we can't rely
|
|
# on our baked-in docker to support those arguments.
|
|
if [ "$1" = "run" ] ; then
|
|
shift 1
|
|
check_docker_version
|
|
if [ "$1" = "--with-dns" ] ; then
|
|
shift 1
|
|
DNS_ARGS=$(exec_remote dns-args "$@")
|
|
fi
|
|
collect_cidr_args "$@"
|
|
shift $CIDR_COUNT
|
|
CONTAINER=$(docker $DOCKER_CLIENT_ARGS run $DNS_ARGS -d "$@")
|
|
exec_remote attach $CIDR_ARGS $CONTAINER
|
|
echo $CONTAINER
|
|
exit 0
|
|
elif [ "$1" != "--local" ] ; then
|
|
exec_remote "$@"
|
|
exit $?
|
|
fi
|
|
|
|
shift 1
|
|
|
|
BASE_IMAGE=$DOCKERHUB_USER/weave
|
|
BASE_DNS_IMAGE=$DOCKERHUB_USER/weavedns
|
|
IMAGE=$BASE_IMAGE:$IMAGE_VERSION
|
|
DNS_IMAGE=$BASE_DNS_IMAGE:$IMAGE_VERSION
|
|
|
|
PROCFS=${PROCFS:-/proc}
|
|
DOCKER_BRIDGE=${DOCKER_BRIDGE:-docker0}
|
|
CONTAINER_NAME=${WEAVE_CONTAINER_NAME:-weave}
|
|
DNS_CONTAINER_NAME=weavedns
|
|
BRIDGE=weave
|
|
CONTAINER_IFNAME=ethwe
|
|
MTU=65535
|
|
PORT=${WEAVE_PORT:-6783}
|
|
HTTP_PORT=6784
|
|
DNS_HTTP_PORT=6785
|
|
PROXY_PORT=12375
|
|
PROXY_CONTAINER_NAME=weaveproxy
|
|
|
|
|
|
######################################################################
|
|
# general helpers; independent of docker and weave
|
|
######################################################################
|
|
|
|
# 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_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
|
|
}
|
|
|
|
# Configure the ARP cache parameters for the given interface. This
|
|
# makes containers react more quickly to a change in the MAC address
|
|
# associated with an IP address.
|
|
configure_arp_cache() {
|
|
$2 sh -c "echo 5 >/proc/sys/net/ipv4/neigh/$1/base_reachable_time &&
|
|
echo 2 >/proc/sys/net/ipv4/neigh/$1/delay_first_probe_time &&
|
|
echo 1 >/proc/sys/net/ipv4/neigh/$1/ucast_solicit"
|
|
}
|
|
|
|
# Send out an unsolicated ARP response to update ARP cache entries
|
|
# accross the weave network. We do this in addition to
|
|
# configure_arp_cache because a) with those ARP cache settings it
|
|
# still takes a few seconds to correct a stale ARP mapping, and b)
|
|
# there is a kernel bug that means that the base_reachable_time
|
|
# setting is not promptly obeyed
|
|
# (<https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=4bf6980dd0328530783fd657c776e3719b421d30>>).
|
|
arp_update() {
|
|
# It's not the end of the world if this doesn't run - we configure
|
|
# ARP caches so that stale entries will be noticed quickly.
|
|
if command_exists arping ; then
|
|
$3 arping -U -q -I $1 -c 1 ${2%/*}
|
|
fi
|
|
}
|
|
|
|
# Generate a random MAC value
|
|
random_mac() {
|
|
# In the first byte of the MAC, the 'multicast' bit should be
|
|
# clear and 'locally administered' bit should be set. All other
|
|
# bits should be random.
|
|
od -txC -An -N6 /dev/urandom | ( read a b c d e f && printf "%02x:$b:$c:$d:$e:$f" $((0x$a & ~1 | 2)) )
|
|
}
|
|
|
|
######################################################################
|
|
# weave and docker specific helpers
|
|
######################################################################
|
|
|
|
create_bridge() {
|
|
if [ ! -d /sys/class/net/$BRIDGE ] ; then
|
|
ip link add name $BRIDGE type bridge
|
|
# Set a random MAC address on the bridge. Current Linux
|
|
# kernels already do this when creating a bridge, but there
|
|
# are rumours it was not always so.
|
|
ip link set dev $BRIDGE address $(random_mac)
|
|
# 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
|
|
# Drop traffic from Docker bridge to Weave; it can break subnet isolation
|
|
if [ "$DOCKER_BRIDGE" != "$BRIDGE" ] ; then
|
|
# Note using -I to insert ahead of Docker's bridge rules
|
|
run_iptables -t filter -I FORWARD -i $DOCKER_BRIDGE -o $BRIDGE -j DROP
|
|
fi
|
|
# 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
|
|
fi
|
|
if [ ! "$1" = "--without-ethtool" ] ; then
|
|
ethtool -K $BRIDGE tx off >/dev/null
|
|
fi
|
|
|
|
ip link set dev $BRIDGE up
|
|
|
|
# Configure the ARP cache parameters on the bridge interface for
|
|
# the sake of 'weave expose'
|
|
configure_arp_cache $BRIDGE
|
|
}
|
|
|
|
destroy_bridge() {
|
|
if [ -d /sys/class/net/$BRIDGE ] ; then
|
|
ip link del dev $BRIDGE
|
|
fi
|
|
if [ "$DOCKER_BRIDGE" != "$BRIDGE" ] ; then
|
|
run_iptables -t filter -D FORWARD -i $DOCKER_BRIDGE -o $BRIDGE -j DROP 2>/dev/null || true
|
|
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 $CONTAINER_PID to the PID 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
|
|
|
|
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 [ ! -d $PROCFS/$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
|
|
return $STATUS
|
|
}
|
|
|
|
with_container_netns_or_die() {
|
|
if ! with_container_netns "$@" >/dev/null ; then
|
|
docker kill $1 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Execute arguments as a command within the network namespace of $CONTAINER_PID
|
|
netnsenter() {
|
|
nsenter --net=$PROCFS/$CONTAINER_PID/ns/net "$@"
|
|
}
|
|
|
|
connect_container_to_bridge() {
|
|
if [ -h "$PROCFS/$CONTAINER_PID/ns/net" -a -h "$PROCFS/$$/ns/net" -a "$(readlink $PROCFS/$CONTAINER_PID/ns/net)" = "$(readlink $PROCFS/$$/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
|
|
ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU || return 1
|
|
|
|
if ! 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 $PROCFS/$CONTAINER_PID/ns/net ; then
|
|
# failed before we assigned the veth to the container's
|
|
# namespace
|
|
ip link del $LOCAL_IFNAME type veth || true
|
|
return 1
|
|
fi
|
|
|
|
if ! netnsenter ip link set $GUEST_IFNAME name $CONTAINER_IFNAME ||
|
|
! configure_arp_cache $CONTAINER_IFNAME "netnsenter" ; then
|
|
return 1
|
|
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
|
|
}
|
|
|
|
######################################################################
|
|
# functions invoked through with_container_netns
|
|
######################################################################
|
|
|
|
launch() {
|
|
if ! netnsenter 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 &&
|
|
netnsenter ethtool -K eth0 tx off >/dev/null &&
|
|
netnsenter ip link set $CONTAINER_IFNAME up
|
|
}
|
|
|
|
attach() {
|
|
if netnsenter ip link show $CONTAINER_IFNAME >/dev/null 2>&1 ; then
|
|
for ADDR in "$@" ; do
|
|
# container already has the expected network interface, so assume we set it up already;
|
|
# just add the IP address.
|
|
if netnsenter ip addr show dev $CONTAINER_IFNAME | grep -F $ADDR >/dev/null ; then
|
|
# address was there already
|
|
continue
|
|
fi
|
|
netnsenter ip addr add $ADDR dev $CONTAINER_IFNAME || return 1
|
|
done
|
|
|
|
return 0
|
|
fi
|
|
|
|
connect_container_to_bridge || return 1
|
|
|
|
for ADDR in "$@" ; do
|
|
netnsenter ip addr add $ADDR dev $CONTAINER_IFNAME || return 1
|
|
done
|
|
|
|
netnsenter ip link set $CONTAINER_IFNAME up || return 1
|
|
|
|
# Route multicast packets across the weave network.
|
|
if ! netnsenter ip route show | grep '^224\.0\.0\.0/4' >/dev/null ; then
|
|
netnsenter ip route add 224.0.0.0/4 dev $CONTAINER_IFNAME
|
|
fi
|
|
|
|
arp_update $CONTAINER_IFNAME $1 "netnsenter"
|
|
}
|
|
|
|
detach() {
|
|
netnsenter ip link show $CONTAINER_IFNAME >/dev/null 2>&1 || return 0
|
|
|
|
for ADDR in "$@" ; do
|
|
if ! netnsenter ip addr show dev $CONTAINER_IFNAME | grep -F $ADDR >/dev/null ; then
|
|
# address is not there, leave the device alone
|
|
continue
|
|
fi
|
|
netnsenter ip addr del $ADDR dev $CONTAINER_IFNAME || return 1
|
|
done
|
|
|
|
if [ -n "$(netnsenter 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
|
|
netnsenter ip link del $CONTAINER_IFNAME type veth
|
|
}
|
|
|
|
container_weave_addrs() {
|
|
netnsenter ip addr show dev $CONTAINER_IFNAME
|
|
}
|
|
|
|
######################################################################
|
|
# functions for interacting with containers
|
|
######################################################################
|
|
|
|
# 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
|
|
}
|
|
|
|
stop() {
|
|
if ! docker stop $1 >/dev/null 2>&1 ; then
|
|
echo "$2 is not running." >&2
|
|
fi
|
|
docker rm -f $1 >/dev/null 2>&1 || true
|
|
}
|
|
|
|
# Given a container name or short ID in $1, ensure the specified
|
|
# container is running and then print its full ID to stdout. If
|
|
# it's not running or doesn't exist, print an error to stderr and
|
|
# return with an indicative non-zero exit code.
|
|
container_id() {
|
|
if ! status=$(docker inspect --format='{{.State.Running}} {{.Id}}' $1 2>/dev/null) ; then
|
|
echo "Error: No such container: $1" >&2
|
|
return 1
|
|
fi
|
|
case "$status" in
|
|
true*)
|
|
echo "${status#true }"
|
|
;;
|
|
*)
|
|
echo "$1 container is not running." >&2
|
|
return 2
|
|
;;
|
|
esac
|
|
}
|
|
|
|
container_ip() {
|
|
if ! status=$(docker inspect --format='{{.State.Running}} {{.NetworkSettings.IPAddress}}' $1 2>/dev/null) ; then
|
|
echo "$2" >&2
|
|
return 1
|
|
fi
|
|
case "$status" in
|
|
"true ")
|
|
echo "$1 container has no IP address; is Docker networking enabled?" >&2
|
|
return 1
|
|
;;
|
|
true*)
|
|
CONTAINER_IP="${status#true }"
|
|
;;
|
|
*)
|
|
echo "$3" >&2
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
http_call_ip() {
|
|
ip="$1"
|
|
port="$2"
|
|
http_verb="$3"
|
|
url="$4"
|
|
shift 4
|
|
curl --connect-timeout 3 -s -X $http_verb "$@" http://$ip:$port$url
|
|
}
|
|
|
|
# Call url $4 with http verb $3 on container $1 at port $2
|
|
http_call() {
|
|
container_ip $1 \
|
|
"$1 container is not present. Have you launched it?" \
|
|
"$1 container is not running." \
|
|
|| return 1
|
|
shift 1
|
|
http_call_ip $CONTAINER_IP "$@"
|
|
}
|
|
|
|
# Wait until container $1 is alive enough to respond to "GET /status"
|
|
# http request on its docker-assigned IP, port $2
|
|
wait_for_status() {
|
|
container_ip $1 "$1 container has died." "$1 container has died." || return 1
|
|
while true ; do
|
|
http_call_ip $CONTAINER_IP $2 GET /status >/dev/null && return 0
|
|
if ! container_id $1 >/dev/null 2>&1 ; then
|
|
echo "$1 container has died." >&2
|
|
return 1
|
|
fi
|
|
sleep 1
|
|
done
|
|
}
|
|
|
|
# Wait until container $1 outputs a line containing $2 in its log
|
|
wait_for_log() {
|
|
fifo=/tmp/tmpfifo.$$
|
|
mkfifo $fifo || exit 1
|
|
docker logs -f $1 2>/dev/null >$fifo &
|
|
res=0
|
|
grep -q "$2" $fifo || res=1
|
|
kill $! 2>/dev/null || true
|
|
rm $fifo
|
|
if [ $res -eq 1 ] ; then
|
|
echo "$1 container has died." >&2
|
|
fi
|
|
return $res
|
|
}
|
|
|
|
# Call $1 for all containers, passing container ID, all MACs and all IPs
|
|
with_container_addresses() {
|
|
COMMAND=$1
|
|
shift 1
|
|
for CONTAINER_ID in "$@" ; do
|
|
if [ "$CONTAINER_ID" = "weave:expose" ] ; then
|
|
ADDRS_CMD="ip addr show dev $BRIDGE"
|
|
else
|
|
ADDRS_CMD="with_container_netns $CONTAINER_ID container_weave_addrs"
|
|
fi
|
|
if CONTAINER_ADDRS=$($ADDRS_CMD 2>/dev/null) ; 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)
|
|
$COMMAND "$CONTAINER_ID" "$CONTAINER_MAC" "$CONTAINER_IPS"
|
|
fi
|
|
done
|
|
}
|
|
|
|
echo_addresses() {
|
|
echo $1 $2 $3
|
|
}
|
|
|
|
peer_args() {
|
|
res=''
|
|
sep=''
|
|
for p in "$@" ; do
|
|
res="$res${sep}peer=$p"
|
|
sep="&"
|
|
done
|
|
echo "$res"
|
|
}
|
|
|
|
######################################################################
|
|
# weaveDNS helpers
|
|
######################################################################
|
|
|
|
dns_args() {
|
|
if [ \( "$DOCKER_VERSION_MAJOR" -lt 1 \) -o \
|
|
\( "$DOCKER_VERSION_MAJOR" -eq 1 -a \
|
|
"$DOCKER_VERSION_MINOR" -lt 3 \) ] ; then
|
|
# Versions prior to 1.2.0 cannot parse `--dns-search=.`, and
|
|
# versions prior to 1.3.0 fail to include the domain when
|
|
# setting the hostname, so lookups for non-fully-qualified
|
|
# names fail.
|
|
echo "ERROR: The '--with-dns' option requires Docker 1.3.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
|
|
DNS_ARGS="$DNS_ARG $DNS_SEARCH_ARG"
|
|
}
|
|
|
|
# Print an error to stderr and return with an indicative exit status
|
|
# if the container $1 does not exist or isn't running.
|
|
check_running() {
|
|
if ! STATUS=$(docker inspect --format='{{.State.Running}}' $1 2>/dev/null); then
|
|
echo "$1 container is not present. Have you launched it?" >&2
|
|
return 1
|
|
elif [ "$STATUS" != "true" ] ; then
|
|
echo "$1 container is not running." >&2
|
|
return 2
|
|
fi
|
|
}
|
|
|
|
# Execute $@ only if the weaveDNS container is running
|
|
when_dns_running() {
|
|
if check_running $DNS_CONTAINER_NAME 2>/dev/null; then
|
|
"$@"
|
|
fi
|
|
}
|
|
|
|
# Iff the container in $1 has an FQDN, invoke $2 as a command passing
|
|
# the container as the first argument, the FQDN as the second argument
|
|
# and $3.. as additional arguments
|
|
with_container_fqdn() {
|
|
CONTAINER="$1"
|
|
COMMAND="$2"
|
|
shift 2
|
|
|
|
CONTAINER_FQDN=$(docker inspect --format='{{.Config.Hostname}}.{{.Config.Domainname}}.' $CONTAINER 2>/dev/null) || return 0
|
|
|
|
if echo "$CONTAINER_FQDN" | grep -qv '\.\.$' ; then
|
|
$COMMAND "$CONTAINER" "$CONTAINER_FQDN" "$@"
|
|
fi
|
|
}
|
|
|
|
# Register FQDN in $2 as names for addresses $3.. under full container ID $1
|
|
put_dns_fqdn() {
|
|
CONTAINER_ID="$1"
|
|
FQDN="$2"
|
|
shift 2
|
|
|
|
for ADDR in "$@" ; do
|
|
http_call $DNS_CONTAINER_NAME $DNS_HTTP_PORT PUT /name/$CONTAINER_ID/${ADDR%/*} --data-urlencode fqdn=$FQDN || true
|
|
done
|
|
}
|
|
|
|
# Delete all names for addresses $3.. under full container ID $1
|
|
delete_dns() {
|
|
CONTAINER_ID="$1"
|
|
shift 1
|
|
|
|
for ADDR in "$@" ; do
|
|
http_call $DNS_CONTAINER_NAME $DNS_HTTP_PORT DELETE /name/$CONTAINER_ID/${ADDR%/*} || true
|
|
done
|
|
}
|
|
|
|
# Delete any FQDNs $2 from addresses $3.. under full container ID $1
|
|
delete_dns_fqdn() {
|
|
CONTAINER_ID="$1"
|
|
FQDN="$2"
|
|
shift 2
|
|
|
|
for ADDR in "$@" ; do
|
|
http_call $DNS_CONTAINER_NAME $DNS_HTTP_PORT DELETE /name/$CONTAINER_ID/${ADDR%/*}?fqdn=$FQDN || true
|
|
done
|
|
}
|
|
|
|
# Tell the newly-started weaveDNS about existing weave IPs
|
|
populate_dns() {
|
|
if ! wait_for_status $DNS_CONTAINER_NAME $DNS_HTTP_PORT ; then
|
|
echo "If running, it will not be pre-populated." >&2
|
|
return 0
|
|
fi
|
|
for CONTAINER in $(docker ps -q --no-trunc) ; do
|
|
if CONTAINER_IPS=$(with_container_netns $CONTAINER container_weave_addrs 2>&1 | sed -n -e 's/inet \([^/]*\)\/\(.*\)/\1/p') ; then
|
|
with_container_fqdn $CONTAINER put_dns_fqdn $CONTAINER_IPS
|
|
fi
|
|
done
|
|
}
|
|
|
|
######################################################################
|
|
# IP Allocation Management helpers
|
|
######################################################################
|
|
|
|
# Claim addresses for a container in IPAM. Expects to be called from
|
|
# with_container_addresses.
|
|
ipam_claim() {
|
|
for CIDR in $3 ; do
|
|
# NB: CONTAINER_IP is the IP of the weave container; it is set by wait_for_status.
|
|
http_call_ip $CONTAINER_IP $HTTP_PORT PUT /ip/$1/${CIDR%/*}
|
|
done
|
|
}
|
|
|
|
# If we don't already have any CIDRs passed from the command-line, get
|
|
# one from IPAM. $1 is the full container id.
|
|
get_ipam_cidr() {
|
|
if [ -n "$CIDR_ARGS" ] ; then
|
|
return 0
|
|
fi
|
|
CIDR_ARGS="$(http_call $CONTAINER_NAME $HTTP_PORT POST /ip/$1)"
|
|
if [ "$CIDR_ARGS" = "404 page not found" ] ; then
|
|
echo "No IP address supplied (use the -iprange option on 'weave launch' to enable IP address allocation)" >&2
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
######################################################################
|
|
# weave proxy helpers
|
|
######################################################################
|
|
|
|
|
|
# TODO: Handle relative paths for args
|
|
# TODO: Handle args with spaces
|
|
tls_arg() {
|
|
filename=${3:-$2}
|
|
PROXY_VOLUMES="$PROXY_VOLUMES -v $1:/home/weave/tls/$filename.pem"
|
|
PROXY_ARGS="$PROXY_ARGS --tls$2 /home/weave/tls/$filename.pem"
|
|
}
|
|
|
|
proxy_args() {
|
|
PROXY_VOLUMES=""
|
|
PROXY_ARGS=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--tlscacert)
|
|
shift
|
|
tls_arg "$1" cacert ca
|
|
;;
|
|
--tlscacert=*)
|
|
tls_arg "${1#*=}" cacert ca
|
|
;;
|
|
--tlscert)
|
|
shift
|
|
tls_arg "$1" cert
|
|
;;
|
|
--tlscert=*)
|
|
tls_arg "${1#*=}" cert
|
|
;;
|
|
--tlskey)
|
|
shift
|
|
tls_arg "$1" key
|
|
;;
|
|
--tlskey=*)
|
|
tls_arg "${1#*=}" key
|
|
;;
|
|
*)
|
|
PROXY_ARGS="$PROXY_ARGS $1"
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
}
|
|
|
|
##########################################################################################
|
|
|
|
[ $(id -u) = 0 ] || {
|
|
echo "weave must be run as 'root' when run locally" >&2
|
|
exit 1
|
|
}
|
|
|
|
uname -s -r | sed -n -e 's|^\([^ ]*\) \([0-9][0-9]*\)\.\([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 8 \) -o "$maj" -gt 3 ] ; then
|
|
echo "WARNING: Linux kernel version 3.8 or newer is required (you have ${maj}.${min})" >&2
|
|
fi
|
|
}
|
|
|
|
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
|
|
|
|
check_docker_version
|
|
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)
|
|
|
|
[ $# -gt 0 ] || usage
|
|
COMMAND=$1
|
|
shift 1
|
|
|
|
case "$COMMAND" in
|
|
setup)
|
|
for img in $IMAGE $DNS_IMAGE $EXEC_IMAGE ; do
|
|
docker pull $img
|
|
done
|
|
;;
|
|
# intentionally undocumented since it assumes knowledge of weave
|
|
# internals
|
|
create-bridge)
|
|
create_bridge --without-ethtool
|
|
;;
|
|
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.
|
|
PEERNAME=$(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
|
|
CONTAINER_PORT=$PORT
|
|
ARGS=""
|
|
while [ $# -gt 0 ] ; do
|
|
case "$1" in
|
|
-password)
|
|
[ $# -gt 1 ] || usage
|
|
WEAVE_PASSWORD="$2"
|
|
export WEAVE_PASSWORD
|
|
shift 2
|
|
;;
|
|
-port)
|
|
[ $# -gt 1 ] || usage
|
|
CONTAINER_PORT="$2"
|
|
shift 2
|
|
;;
|
|
-iprange)
|
|
[ $# -gt 1 ] || usage
|
|
validate_cidr $2
|
|
IPRANGE="-iprange $2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
ARGS="$ARGS '$(echo "$1" | sed "s|'|'\"'\"'|g")'"
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
eval "set -- $ARGS"
|
|
# 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:$CONTAINER_PORT/tcp -p $PORT:$CONTAINER_PORT/udp \
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
-e WEAVE_PASSWORD \
|
|
$WEAVE_DOCKER_ARGS $IMAGE -iface $CONTAINER_IFNAME -port $CONTAINER_PORT -name "$PEERNAME" -nickname "$(hostname)" $IPRANGE "$@")
|
|
with_container_netns_or_die $CONTAINER launch
|
|
wait_for_status $CONTAINER_NAME $HTTP_PORT
|
|
if [ -n "$IPRANGE" ] ; then
|
|
# Tell the newly-started weave IP allocator about existing weave IPs
|
|
with_container_addresses ipam_claim weave:expose $(docker ps -q --no-trunc)
|
|
fi
|
|
echo $CONTAINER
|
|
;;
|
|
launch-dns)
|
|
[ $# -gt 0 ] || usage
|
|
CIDR=$1
|
|
validate_cidr $CIDR
|
|
shift 1
|
|
check_not_running $DNS_CONTAINER_NAME $BASE_DNS_IMAGE
|
|
create_bridge
|
|
docker_bridge_ip
|
|
# Set WEAVEDNS_DOCKER_ARGS in the environment in order to supply
|
|
# additional parameters, such as resource limits, to docker
|
|
# when launching the weave container.
|
|
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 \
|
|
$WEAVEDNS_DOCKER_ARGS $DNS_IMAGE -iface $CONTAINER_IFNAME "$@")
|
|
with_container_netns_or_die $DNS_CONTAINER attach $CIDR
|
|
populate_dns
|
|
echo $DNS_CONTAINER
|
|
;;
|
|
launch-proxy)
|
|
check_not_running $PROXY_CONTAINER_NAME $EXEC_IMAGE
|
|
# Set WEAVEPROXY_DOCKER_ARGS in the environment in order to supply
|
|
# additional parameters, such as resource limits, to docker
|
|
# when launching the weaveproxy container.
|
|
proxy_args "$@"
|
|
PROXY_CONTAINER=$(docker run --privileged -d --name=$PROXY_CONTAINER_NAME --net=host \
|
|
-p $PROXY_PORT:$PROXY_PORT/tcp \
|
|
$PROXY_VOLUMES \
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|
-v /proc:/hostproc \
|
|
-e PROCFS=/hostproc \
|
|
--entrypoint=/home/weave/weaveproxy \
|
|
$WEAVEPROXY_DOCKER_ARGS $EXEC_IMAGE $PROXY_ARGS)
|
|
wait_for_log $PROXY_CONTAINER_NAME "proxy listening"
|
|
echo $PROXY_CONTAINER
|
|
;;
|
|
connect)
|
|
[ $# -gt 0 ] || usage
|
|
if [ "$1" == "--replace" ]; then
|
|
replace="-d replace=true"
|
|
shift
|
|
fi
|
|
http_call $CONTAINER_NAME $HTTP_PORT POST /connect $replace -d $(peer_args "$@")
|
|
;;
|
|
forget)
|
|
[ $# -gt 0 ] || usage
|
|
http_call $CONTAINER_NAME $HTTP_PORT POST /forget -d $(peer_args "$@")
|
|
;;
|
|
status)
|
|
res=0
|
|
http_call $CONTAINER_NAME $HTTP_PORT GET /status || res=1
|
|
echo
|
|
http_call $DNS_CONTAINER_NAME $DNS_HTTP_PORT GET /status 2>/dev/null || true
|
|
if check_running $PROXY_CONTAINER_NAME 2>/dev/null ; then
|
|
echo
|
|
echo "weave proxy is running"
|
|
fi
|
|
[ $res -eq 0 ]
|
|
;;
|
|
ps)
|
|
[ $# -eq 0 ] && CONTAINERS="weave:expose $(docker ps -q)" || CONTAINERS="$@"
|
|
with_container_addresses echo_addresses $CONTAINERS
|
|
;;
|
|
version)
|
|
[ $# -eq 0 ] || usage
|
|
echo weave script $SCRIPT_VERSION
|
|
ask_version $CONTAINER_NAME $IMAGE || true
|
|
ask_version $DNS_CONTAINER_NAME $DNS_IMAGE || true
|
|
if ! EXEC_IMAGE_ID=$(docker inspect --format='{{.Id}}' $EXEC_IMAGE 2>/dev/null) ; then
|
|
echo "Unable to find $EXEC_IMAGE image." >&2
|
|
else
|
|
EXEC_VERSION=$(docker images --no-trunc | grep $EXEC_IMAGE_ID | grep -v latest | tr -s ' ' | cut -d ' ' -f 2 | tr "\n" ' ')
|
|
if [ -n "$EXEC_VERSION" ] ; then
|
|
echo "weave exec $EXEC_VERSION"
|
|
else
|
|
echo "weave exec (unreleased version)"
|
|
fi
|
|
fi
|
|
;;
|
|
run)
|
|
[ $# -gt 0 ] || usage
|
|
if [ "$1" = "--with-dns" ] ; then
|
|
shift 1
|
|
dns_args "$@"
|
|
fi
|
|
collect_cidr_args "$@"
|
|
shift $CIDR_COUNT
|
|
CONTAINER=$(docker run $DNS_ARGS -d "$@")
|
|
create_bridge
|
|
get_ipam_cidr $CONTAINER
|
|
with_container_netns_or_die $CONTAINER attach $CIDR_ARGS
|
|
when_dns_running with_container_fqdn $CONTAINER put_dns_fqdn $CIDR_ARGS
|
|
echo $CONTAINER
|
|
;;
|
|
dns-args)
|
|
dns_args "$@"
|
|
echo -n $DNS_ARGS
|
|
;;
|
|
docker-bridge-ip)
|
|
docker_bridge_ip
|
|
echo -n $DOCKER_BRIDGE_IP
|
|
;;
|
|
start)
|
|
collect_cidr_args "$@"
|
|
shift $CIDR_COUNT
|
|
[ $# -eq 1 ] || usage
|
|
CONTAINER=$(docker start $1)
|
|
create_bridge
|
|
get_ipam_cidr $CONTAINER
|
|
with_container_netns_or_die $CONTAINER attach $CIDR_ARGS
|
|
when_dns_running with_container_fqdn $CONTAINER put_dns_fqdn $CIDR_ARGS
|
|
echo $CONTAINER
|
|
;;
|
|
attach)
|
|
collect_cidr_args "$@"
|
|
shift $CIDR_COUNT
|
|
[ $# -eq 1 ] || usage
|
|
CONTAINER=$(container_id $1)
|
|
create_bridge
|
|
get_ipam_cidr $CONTAINER
|
|
with_container_netns $CONTAINER attach $CIDR_ARGS >/dev/null
|
|
when_dns_running with_container_fqdn $CONTAINER put_dns_fqdn $CIDR_ARGS
|
|
;;
|
|
detach)
|
|
collect_cidr_args "$@"
|
|
shift $CIDR_COUNT
|
|
[ $# -eq 1 ] || usage
|
|
CONTAINER=$(container_id $1)
|
|
with_container_netns $CONTAINER detach $CIDR_ARGS >/dev/null
|
|
when_dns_running with_container_fqdn $CONTAINER delete_dns_fqdn $CIDR_ARGS
|
|
;;
|
|
dns-add)
|
|
collect_ip_args "$@"
|
|
shift $IP_COUNT
|
|
[ $# -eq 1 -o \( $# -eq 3 -a "$2" = "-h" \) ] || usage
|
|
check_running $DNS_CONTAINER_NAME
|
|
CONTAINER=$(container_id $1)
|
|
if [ $# -eq 1 ] ; then
|
|
with_container_fqdn $CONTAINER put_dns_fqdn $IP_ARGS
|
|
else
|
|
put_dns_fqdn $CONTAINER "$3" $IP_ARGS
|
|
fi
|
|
;;
|
|
dns-remove)
|
|
collect_ip_args "$@"
|
|
shift $IP_COUNT
|
|
[ $# -eq 1 -o \( $# -eq 3 -a "$2" = "-h" \) ] || usage
|
|
check_running $DNS_CONTAINER_NAME
|
|
CONTAINER=$(container_id $1)
|
|
if [ $# -eq 1 ] ; then
|
|
delete_dns $CONTAINER $IP_ARGS
|
|
else
|
|
delete_dns_fqdn $CONTAINER "$3" $IP_ARGS
|
|
fi
|
|
;;
|
|
expose)
|
|
collect_cidr_args "$@"
|
|
shift $CIDR_COUNT
|
|
get_ipam_cidr weave:expose
|
|
if [ $# -eq 0 ] ; then
|
|
FQDN=""
|
|
else
|
|
[ $# -eq 2 -a "$1" = "-h" ] || usage
|
|
FQDN="$2"
|
|
fi
|
|
create_bridge --without-ethtool
|
|
for CIDR in $CIDR_ARGS ; do
|
|
if ! ip addr show dev $BRIDGE | grep -qF $CIDR ; then
|
|
ip addr add dev $BRIDGE $CIDR
|
|
arp_update $BRIDGE $CIDR
|
|
add_iptables_rule nat WEAVE -d $CIDR ! -s $CIDR -j MASQUERADE
|
|
add_iptables_rule nat WEAVE -s $CIDR ! -d $CIDR -j MASQUERADE
|
|
if [ "$FQDN" ] ; then
|
|
when_dns_running put_dns_fqdn 'weave:expose' $FQDN $CIDR
|
|
fi
|
|
fi
|
|
done
|
|
;;
|
|
hide)
|
|
collect_cidr_args "$@"
|
|
shift $CIDR_COUNT
|
|
get_ipam_cidr weave:expose
|
|
create_bridge --without-ethtool
|
|
for CIDR in $CIDR_ARGS ; do
|
|
if ip addr show dev $BRIDGE | grep -qF $CIDR ; then
|
|
ip addr del dev $BRIDGE $CIDR
|
|
delete_iptables_rule nat WEAVE -d $CIDR ! -s $CIDR -j MASQUERADE
|
|
delete_iptables_rule nat WEAVE -s $CIDR ! -d $CIDR -j MASQUERADE
|
|
when_dns_running delete_dns 'weave:expose' $CIDR
|
|
fi
|
|
done
|
|
[ $CIDR_COUNT -eq 0 ] && http_call $CONTAINER_NAME $HTTP_PORT DELETE /ip/weave:expose 2>/dev/null || true
|
|
;;
|
|
stop)
|
|
[ $# -eq 0 ] || usage
|
|
stop $CONTAINER_NAME "Weave"
|
|
conntrack -D -p udp --dport $PORT >/dev/null 2>&1 || true
|
|
;;
|
|
stop-dns)
|
|
[ $# -eq 0 ] || usage
|
|
stop $DNS_CONTAINER_NAME "WeaveDNS"
|
|
;;
|
|
stop-proxy)
|
|
[ $# -eq 0 ] || usage
|
|
stop $PROXY_CONTAINER_NAME "Proxy"
|
|
;;
|
|
reset)
|
|
[ $# -eq 0 ] || usage
|
|
http_call $CONTAINER_NAME $HTTP_PORT DELETE /peer >/dev/null 2>&1 || true
|
|
for NAME in $CONTAINER_NAME $DNS_CONTAINER_NAME $PROXY_CONTAINER_NAME ; do
|
|
docker stop $NAME >/dev/null 2>&1 || true
|
|
docker rm -f $NAME >/dev/null 2>&1 || true
|
|
done
|
|
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
|
|
;;
|
|
rmpeer)
|
|
[ $# -eq 1 ] || usage
|
|
PEER=$1
|
|
http_call $CONTAINER_NAME $HTTP_PORT DELETE /peer/$PEER
|
|
;;
|
|
*)
|
|
echo "Unknown weave command '$COMMAND'" >&2
|
|
usage
|
|
;;
|
|
esac
|