Merge pull request #498 from awh/467_multi_cidr_launch

Allow multiple CIDR arguments to run/start/attach/detach/expose/hide

Closes #467.
This commit is contained in:
rade committed 2015-04-01 10:58:36 +01:00
commit 254b837a92
3 files changed
+212 -68

No files matched your search

+17
View File
@@ -90,6 +90,11 @@ each other but not the containers of our first application...
This isolation-through-subnets scheme is an example of carrying over a
well-known technique from the 'on metal' days to containers.
If desired, a container can be attached to multiple subnets when it is
started:
host1# weave run 10.2.2.1/24 10.2.3.1/24 -t -i ubuntu
NB: By default docker permits communication between containers on the
same host, via their docker-assigned IP addresses. For complete
isolation between application containers, that feature needs to be
@@ -128,6 +133,12 @@ sharing it between applications:
host1# weave attach 10.2.1.1/24 $C
host1# weave attach 10.2.2.1/24 $C
Finally, multiple addresses can be attached or detached with a single
invocation:
host1# weave attach 10.2.1.1/24 10.2.2.1/24 10.2.3.1/24 $C
host1# weave detach 10.2.1.1/24 10.2.2.1/24 10.2.3.1/24 $C
### <a name="security"></a>Security
In order to connect containers across untrusted networks, weave peers
@@ -173,6 +184,12 @@ will work. And, more interestingly,
will work too, which is talking to a container that resides on `$HOST1`.
Multiple subnet addresses can be exposed or hidden with a single
invocation:
host2# weave expose 10.2.1.102/24 10.2.2.102/24
host2# weave hide 10.2.1.102/24 10.2.2.102/24
### <a name="service-export"></a>Service export
Services running in containers on a weave network can be made
+94
View File
@@ -0,0 +1,94 @@
#! /bin/bash
. ./config.sh
start_suite "Weave run/start/attach/detach with multiple cidr arguments"
# Cleanup from previous run
weave_on $HOST1 stop || true
weave_on $HOST1 stop-dns || true
docker_on $HOST1 rm -f multicidr || true
weave_on $HOST1 launch
weave_on $HOST1 launch-dns 10.254.254.254/24
# weave_status_on <host>
weave_status_on() {
HOST=$1; shift
DOCKER_HOST=tcp://$HOST:2375 $WEAVE status
}
# weave_ps_on <host>
weave_ps_on() {
HOST=$1; shift
DOCKER_HOST=tcp://$HOST:2375 $WEAVE ps
}
# assert_container_cidrs <host> <cid> <cidr> [<cidr> ...]
assert_container_cidrs() {
HOST=$1; shift
CID=$1; shift
CIDRS=$@
# Assert container has attached CIDRs
assert_raises "weave_ps_on $HOST | grep \"^$CID [^ ]* $CIDRS$\""
}
# assert_zone_records <host> <cid> <fqdn> <ip> [<ip> ...]
assert_zone_records() {
HOST=$1; shift
CID=$1; shift
FQDN=$1; shift
# Assert correct number of records exist
assert "weave_status_on $HOST | grep \"^$CID\" | wc -l" $#
# Assert correct records exist
for IP in $@; do
assert_raises "weave_status_on $HOST | grep \"^$CID $IP $FQDN$\""
done
}
# assert_bridge_cidrs <host> <dev> <cidr> [<cidr> ...]
assert_bridge_cidrs() {
HOST=$1; shift
DEV=$1; shift
CIDRS=$@
BRIDGE_CIDRS=$($SSH $HOST ip addr show dev $DEV | grep -o 'inet .*' | cut -d ' ' -f 2)
assert "echo $BRIDGE_CIDRS" "$CIDRS"
}
# Run container with three cidrs
CID=$(DOCKER_HOST=tcp://$HOST1:2375 $WEAVE run 10.0.1.1/24 10.0.2.1/24 10.0.3.1/24 -t --name multicidr -h multicidr.weave.local ubuntu | cut -b 1-12)
assert_container_cidrs $HOST1 $CID 10.0.1.1/24 10.0.2.1/24 10.0.3.1/24
assert_zone_records $HOST1 $CID multicidr.weave.local. 10.0.1.1 10.0.2.1 10.0.3.1
# Remove two of them
weave_on $HOST1 detach 10.0.1.1/24 10.0.3.1/24 $CID
assert_container_cidrs $HOST1 $CID 10.0.2.1/24
assert_zone_records $HOST1 $CID multicidr.weave.local. 10.0.2.1
# Put them both back
weave_on $HOST1 attach 10.0.1.1/24 10.0.3.1/24 $CID
assert_container_cidrs $HOST1 $CID 10.0.2.1/24 10.0.1.1/24 10.0.3.1/24
assert_zone_records $HOST1 $CID multicidr.weave.local. 10.0.2.1 10.0.1.1 10.0.3.1
# Stop the container, restart with three IPs
docker_on $HOST1 stop $CID
weave_on $HOST1 start 10.0.1.1/24 10.0.2.1/24 10.0.3.1/24 $CID
assert_container_cidrs $HOST1 $CID 10.0.1.1/24 10.0.2.1/24 10.0.3.1/24
assert_zone_records $HOST1 $CID multicidr.weave.local. 10.0.1.1 10.0.2.1 10.0.3.1
# Expose some cidrs
weave_on $HOST1 expose 10.0.1.2/24 10.0.2.2/24 10.0.3.2/24
assert_bridge_cidrs $HOST1 weave 10.0.1.2/24 10.0.2.2/24 10.0.3.2/24
# Hide some cidrs
weave_on $HOST1 hide 10.0.1.2/24 10.0.3.2/24
assert_bridge_cidrs $HOST1 weave 10.0.2.2/24
end_suite
+101 -68
View File
@@ -19,10 +19,10 @@ usage() {
echo "weave launch-dns <cidr>"
echo "weave connect <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> <container_id>"
echo "weave run [--with-dns] <cidr> [<cidr> ...] <docker run args> ..."
echo "weave start <cidr> [<cidr> ...] <container_id>"
echo "weave attach <cidr> [<cidr> ...] <container_id>"
echo "weave detach <cidr> [<cidr> ...] <container_id>"
echo "weave expose <cidr>"
echo "weave hide <cidr>"
echo "weave ps"
@@ -71,6 +71,7 @@ exec_remote() {
if [ "$1" = "--local" ]; then
LOCAL="$1"
shift 1
[ -t 0 ] && stty -onlcr
elif [ "$1" != "run" ]; then
exec_remote "$@"
exit $?
@@ -138,6 +139,16 @@ validate_cidr() {
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
}
run_iptables() {
# -w is recent addition to iptables
if [ -z "$CHECKED_IPTABLES_W" ] ; then
@@ -326,23 +337,33 @@ launch() {
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
for ADDR; do
# 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 $ADDR >/dev/null ; then
# address was there already
continue
fi
if ! ip netns exec $NETNS ip addr add $1 dev $CONTAINER_IFNAME ; then
return 1
fi
if ! ip netns exec $NETNS ip addr add $ADDR dev $CONTAINER_IFNAME ; then
return 1
fi
done
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
if ! connect_container_to_bridge; then
return 1
fi
for ADDR; do
if ! ip netns exec $NETNS ip addr add $ADDR dev $CONTAINER_IFNAME; then
return 1
fi
done
if ! ip netns exec $NETNS ip link set $CONTAINER_IFNAME up ; then
return 1
fi
@@ -355,14 +376,16 @@ attach() {
}
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
for ADDR; do
if ! ip netns exec $NETNS ip addr show dev $CONTAINER_IFNAME | grep -F $ADDR >/dev/null ; then
# address is not there, leave the device alone
continue
fi
if ! ip netns exec $NETNS ip addr del $1 dev $CONTAINER_IFNAME ; then
return 1
fi
if ! ip netns exec $NETNS ip addr del $ADDR dev $CONTAINER_IFNAME ; then
return 1
fi
done
if [ -n "$(ip netns exec $NETNS ip -f inet addr show dev $CONTAINER_IFNAME)" ] ; then
# other addresses are left, leave the device alone
@@ -408,15 +431,21 @@ http_call_ip() {
# 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() {
METHOD="$1"
CONTAINER_ID="$2"
shift 2
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)
CONTAINER=$(docker inspect --format='{{.Id}}' $CONTAINER_ID 2>/dev/null)
# extract IP address and routing prefix from CIDR
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/${3%/*} $MORE_ARGS || true
for ADDR; do
http_call $DNS_CONTAINER_NAME $DNS_HTTP_PORT $METHOD /name/$CONTAINER/${ADDR%/*} $MORE_ARGS || true
done
}
# Tell the newly-started weaveDNS about existing weave IPs
@@ -645,16 +674,15 @@ case "$COMMAND" in
DNS_ARGS=$(exec_remote dns-args "$@")
[ "$1" = "--with-dns" ] && shift 1
fi
CIDR=$1
shift 1
validate_cidr $CIDR
collect_cidr_args "$@"
shift $CIDR_COUNT
CONTAINER=$(docker run $DNS_ARGS -d "$@")
if [ "$LOCAL" = "--local" ]; then
create_bridge
with_container_netns $CONTAINER attach $CIDR >/dev/null
tell_dns PUT $CONTAINER $CIDR
with_container_netns $CONTAINER attach $CIDR_ARGS >/dev/null
tell_dns PUT $CONTAINER $CIDR_ARGS
else
exec_remote attach $CIDR $CONTAINER
exec_remote attach $CIDR_ARGS $CONTAINER
fi
echo $CONTAINER
;;
@@ -663,54 +691,59 @@ case "$COMMAND" in
echo -n $DNS_ARGS
;;
start)
[ $# -eq 2 ] || usage
CIDR=$1
validate_cidr $CIDR
[ $# -gt 1 ] || usage
collect_cidr_args "$@"
shift $CIDR_COUNT
CONTAINER_ID="$1"
create_bridge
CONTAINER=$(docker start $2)
with_container_netns $CONTAINER attach $CIDR >/dev/null
tell_dns PUT $CONTAINER $CIDR
CONTAINER=$(docker start $CONTAINER_ID)
with_container_netns $CONTAINER_ID attach $CIDR_ARGS >/dev/null
tell_dns PUT $CONTAINER_ID $CIDR_ARGS
echo $CONTAINER
;;
attach)
[ $# -eq 2 ] || usage
CIDR=$1
validate_cidr $CIDR
[ $# -gt 1 ] || usage
collect_cidr_args "$@"
shift $CIDR_COUNT
CONTAINER_ID="$1"
create_bridge
with_container_netns $2 attach $CIDR >/dev/null
tell_dns PUT $2 $CIDR
with_container_netns $CONTAINER_ID attach $CIDR_ARGS >/dev/null
tell_dns PUT $CONTAINER_ID $CIDR_ARGS
;;
detach)
[ $# -eq 2 ] || usage
CIDR=$1
validate_cidr $CIDR
with_container_netns $2 detach $CIDR >/dev/null
tell_dns DELETE $2 $CIDR
[ $# -gt 1 ] || usage
collect_cidr_args "$@"
shift $CIDR_COUNT
CONTAINER_ID="$1"
with_container_netns $CONTAINER_ID detach $CIDR_ARGS >/dev/null
tell_dns DELETE $CONTAINER_ID $CIDR_ARGS
;;
expose)
[ $# -eq 1 ] || usage
CIDR=$1
validate_cidr $CIDR
create_bridge --without-ethtool
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 -o $BRIDGE ! -s $CIDR -j MASQUERADE
add_iptables_rule nat WEAVE -s $CIDR ! -o $BRIDGE -j MASQUERADE
fi
[ $# -gt 0 ] || usage
for CIDR; do
validate_cidr $CIDR
create_bridge --without-ethtool
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 -o $BRIDGE ! -s $CIDR -j MASQUERADE
add_iptables_rule nat WEAVE -s $CIDR ! -o $BRIDGE -j MASQUERADE
fi
done
;;
hide)
[ $# -eq 1 ] || usage
CIDR=$1
validate_cidr $CIDR
create_bridge --without-ethtool
if ip addr show dev $BRIDGE | grep -qF $CIDR
then
ip addr del dev $BRIDGE $CIDR
delete_iptables_rule nat WEAVE -o $BRIDGE ! -s $CIDR -j MASQUERADE
delete_iptables_rule nat WEAVE -s $CIDR ! -o $BRIDGE -j MASQUERADE
fi
[ $# -gt 0 ] || usage
for CIDR; do
validate_cidr $CIDR
create_bridge --without-ethtool
if ip addr show dev $BRIDGE | grep -qF $CIDR
then
ip addr del dev $BRIDGE $CIDR
delete_iptables_rule nat WEAVE -o $BRIDGE ! -s $CIDR -j MASQUERADE
delete_iptables_rule nat WEAVE -s $CIDR ! -o $BRIDGE -j MASQUERADE
fi
done
;;
stop)
[ $# -eq 0 ] || usage