diff --git a/README.md b/README.md index 9188ef54..49fe82dd 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,30 @@ will work. And, more interestingly, will work too, which is talking to a container that resides on $HOST1. +### Attach to already-running containers + +If you don't want to start containers via the `weave` script, e.g. because +you are controlling them as part of some larger orchestration scheme, you can +attach the weave network to an already-running container. To illustrate, we +can achieve the same effect as the first example like this: + + host1# C=$(docker run -d -t -i ubuntu) + host1# weave attach 10.0.1.1/24 $C + +There is a matching `weave detach` command: + + host1# weave detach 10.0.1.1/24 $C + +You can detach a container from one subnet and re-attach it to another: + + host1# weave detach 10.0.1.1/24 $C + host1# weave attach 10.0.2.1/24 $C + +or attach a container to multiple subnets: + + host1# weave attach 10.0.1.1/24 $C + host1# weave attach 10.0.2.1/24 $C + ### Service export Services running in containers on a weave network can be made diff --git a/weaver/weave b/weaver/weave index e673f9f9..d7a617ed 100755 --- a/weaver/weave +++ b/weaver/weave @@ -5,6 +5,8 @@ usage() { echo "Usage:" echo "weave launch / [-passwd ] ..." echo "weave run / ..." + echo "weave attach / " + echo "weave detach / " echo "weave expose /" echo "weave hide /" echo "weave status" @@ -101,7 +103,7 @@ stop_masquerading() { } # the following borrows from https://github.com/jpetazzo/pipework -configure_container_networking() { +container_netns_preamble() { DOCKERPID=$(docker inspect --format='{{ .State.Pid }}' $1) [ "$DOCKERPID" = 0 ] && { echo "Container $1 not running." >&2 @@ -111,15 +113,40 @@ configure_container_networking() { echo "Container $1 unknown to Docker." >&2 exit 1 } + NSPID=$DOCKERPID [ ! -d /var/run/netns ] && mkdir -p /var/run/netns rm -f /var/run/netns/$NSPID ln -s /proc/$NSPID/ns/net /var/run/netns/$NSPID - - EXITCODE=1 LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}" GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}" + + return 0 +} + +container_netns_cleanup() { + rm -f /var/run/netns/$NSPID +} + +# Parameters are container ID, CIDR address +configure_container_networking() { + container_netns_preamble $1 + + EXITCODE=1 + + # If veth name already exists then assume we set it up already; + # just add the IP address + if ip link show $LOCAL_IFNAME >/dev/null 2>&1 ; then + if ip netns exec $NSPID ip addr add $2 dev $CONTAINER_IFNAME ; then + EXITCODE=0 + else + echo "Failed to attach address $2 to container $1" >&2 + fi + container_netns_cleanup + return $EXITCODE + fi + IP_TMPFILE=/tmp/weave_ip_output_$$ rm -f $IP_TMPFILE if ip link add name $LOCAL_IFNAME mtu $MTU type veth peer name $GUEST_IFNAME mtu $MTU >$IP_TMPFILE 2>&1 ; then @@ -148,11 +175,35 @@ configure_container_networking() { fi rm -f $IP_TMPFILE - rm -f /var/run/netns/$NSPID + container_netns_cleanup return $EXITCODE } +# Parameters are container ID, CIDR address, interface-name +detach() { + container_netns_preamble $1 + + EXITCODE=1 + if ip netns exec $NSPID ip addr del $2 dev $CONTAINER_IFNAME ; then + # if no inet addresses remain then delete the veth + if [ -z "$(ip netns exec $NSPID ip -f inet addr list dev ethwe)" ] ; then + if ip link del $LOCAL_IFNAME type veth ; then + EXITCODE=0 + else + echo "Failed to delete virtual ethernet device $LOCAL_IFNAME from container $1" >&2 + fi + else + EXITCODE=0 + fi + else + echo "Failed to detach address $2 from container $1" >&2 + fi + + container_netns_cleanup + return $EXITCODE +} + case "$COMMAND" in launch) [ $# -gt 0 ] || usage @@ -226,6 +277,15 @@ case "$COMMAND" in configure_container_networking $CONTAINER $IPADDR $CONTAINER_IFNAME echo $CONTAINER ;; + attach) + [ $# -gt 1 ] || usage + create_bridge + configure_container_networking $2 $1 $CONTAINER_IFNAME + ;; + detach) + [ $# -gt 1 ] || usage + detach $2 $1 + ;; expose) [ $# -gt 0 ] || usage IPADDR=$1