Move error detection for attach() into Go

This commit is contained in:
Bryan Boreham committed 2016-05-25 17:34:13 +01:00
1 parent ac14b19db8
commit 161446d55d
2 files changed
+51 -81

No files matched your search

+42 -13
View File
@@ -1,9 +1,12 @@
package main
import (
"fmt"
"net"
"strconv"
"syscall"
docker "github.com/fsouza/go-dockerclient"
"github.com/vishvananda/netns"
weavenet "github.com/weaveworks/weave/net"
@@ -11,7 +14,7 @@ import (
func attach(args []string) error {
if len(args) < 4 {
cmdUsage("attach-container", "[--no-multicast-route] <pid> <bridge-name> <mtu> <cidr>...")
cmdUsage("attach-container", "[--no-multicast-route] <container-id> <bridge-name> <mtu> <cidr>...")
}
withMulticastRoute := true
@@ -20,23 +23,53 @@ func attach(args []string) error {
args = args[1:]
}
pid, err := strconv.Atoi(args[0])
pid, nsContainer, err := containerPidAndNs(args[0])
if err != nil {
return err
}
ns, err := netns.GetFromPid(pid)
if err != nil {
return err
if nsHost, err := netns.GetFromPid(1); err != nil {
return fmt.Errorf("unable to open host namespace: %s", err)
} else if nsHost.Equal(nsContainer) {
return fmt.Errorf("Container is running in the host network namespace, and therefore cannot be\nconnected to weave. Perhaps the container was started with --net=host.")
}
mtu, err := strconv.Atoi(args[2])
if err != nil && args[3] != "" {
return err
return fmt.Errorf("unable to parse mtu %q: %s", args[2], err)
}
cidrs, err := parseCIDRs(args[3:])
if err != nil {
return err
}
return weavenet.AttachContainer(ns, args[0], "ethwe", args[1], mtu, withMulticastRoute, cidrs)
err = weavenet.AttachContainer(nsContainer, fmt.Sprint(pid), "ethwe", args[1], mtu, withMulticastRoute, cidrs)
// If we detected an error but the container has died, tell the user that instead.
if err != nil && !processExists(pid) {
err = fmt.Errorf("Container %s died", args[0])
}
return err
}
func containerPidAndNs(containerID string) (int, netns.NsHandle, error) {
c, err := docker.NewVersionedClientFromEnv("1.18")
if err != nil {
return 0, 0, fmt.Errorf("unable to connect to docker: %s", err)
}
container, err := c.InspectContainer(containerID)
if err != nil {
return 0, 0, fmt.Errorf("unable to inspect container %s: %s", containerID, err)
}
if container.State.Pid == 0 {
return 0, 0, fmt.Errorf("container %s not running", containerID)
}
ns, err := netns.GetFromPid(container.State.Pid)
if err != nil {
return 0, 0, fmt.Errorf("unable to open namespace for container %s: %s", containerID, err)
}
return container.State.Pid, ns, nil
}
func processExists(pid int) bool {
err := syscall.Kill(pid, syscall.Signal(0))
return err == nil || err == syscall.EPERM
}
func parseCIDRs(args []string) (cidrs []*net.IPNet, err error) {
@@ -53,14 +86,10 @@ func parseCIDRs(args []string) (cidrs []*net.IPNet, err error) {
func detach(args []string) error {
if len(args) < 2 {
cmdUsage("detach-container", "<pid> <cidr>...")
cmdUsage("detach-container", "<container-id> <cidr>...")
}
pid, err := strconv.Atoi(args[0])
if err != nil {
return err
}
ns, err := netns.GetFromPid(pid)
_, ns, err := containerPidAndNs(args[0])
if err != nil {
return err
}
+9 -68
View File
@@ -788,56 +788,11 @@ docker_bridge_ip() {
DOCKER_BRIDGE_IP=${DOCKER_BRIDGE_IP#inet }
}
# the following borrows from https://github.com/jpetazzo/pipework
# Set $CONTAINER_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() {
do_or_die() {
CONTAINER="$1"
CONTAINER_PID=$(docker inspect --format='{{.State.Pid}}' $CONTAINER) || return 1
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
CONTAINER_NETNS=/proc/$CONTAINER_PID/ns/net
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 /proc/$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
kill_container $1
if ! "$@" ; then
kill_container $CONTAINER
exit 1
fi
}
@@ -893,10 +848,6 @@ ask_version() {
[ -n "$DOCKERIMAGE" ] && docker run --rm --net=none -e WEAVE_CIDR=none $3 $DOCKERIMAGE $COVERAGE_ARGS --version
}
######################################################################
# functions invoked through with_container_netns
######################################################################
setup_router_iface_fastdp() {
true
}
@@ -914,19 +865,9 @@ container_in_host_ns() {
}
attach() {
if container_in_host_ns ; 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
ATTACH_ARGS=""
[ -n "$NO_MULTICAST_ROUTE" ] && ATTACH_ARGS="--no-multicast-route"
util_op attach-container $ATTACH_ARGS $CONTAINER_PID $BRIDGE $MTU "$@"
}
detach() {
util_op detach-container $CONTAINER_PID "$@"
util_op attach-container $ATTACH_ARGS $CONTAINER $BRIDGE $MTU "$@"
}
######################################################################
@@ -2052,7 +1993,7 @@ EOF
create_bridge
ipam_cidrs_or_die allocate $CONTAINER $CIDR_ARGS
[ -n "$REWRITE_HOSTS" ] && extra_hosts_args "$@" && rewrite_etc_hosts $DNS_EXTRA_HOSTS
with_container_netns_or_die $CONTAINER attach $ALL_CIDRS
do_or_die $CONTAINER attach $ALL_CIDRS
when_weave_running with_container_fqdn $CONTAINER put_dns_fqdn $ALL_CIDRS
echo $CONTAINER
;;
@@ -2072,7 +2013,7 @@ EOF
CONTAINER=$(container_id $1)
create_bridge
ipam_cidrs_or_die allocate $CONTAINER $CIDR_ARGS
with_container_netns_or_die $CONTAINER attach $ALL_CIDRS
do_or_die $CONTAINER attach $ALL_CIDRS
when_weave_running with_container_fqdn $CONTAINER put_dns_fqdn $ALL_CIDRS
echo $RES
;;
@@ -2108,7 +2049,7 @@ EOF
create_bridge
ipam_cidrs allocate $CONTAINER $CIDR_ARGS
[ -n "$REWRITE_HOSTS" ] && rewrite_etc_hosts $DNS_EXTRA_HOSTS
with_container_netns $CONTAINER attach $ALL_CIDRS >/dev/null
attach $ALL_CIDRS >/dev/null
when_weave_running with_container_fqdn $CONTAINER put_dns_fqdn $ALL_CIDRS
show_addrs $ALL_CIDRS
;;
@@ -2118,7 +2059,7 @@ EOF
[ $# -eq 1 ] || usage
CONTAINER=$(container_id $1)
ipam_cidrs lookup $CONTAINER $CIDR_ARGS
with_container_netns $CONTAINER detach $ALL_CIDRS >/dev/null
util_op detach-container $CONTAINER $ALL_CIDRS >/dev/null
when_weave_running with_container_fqdn $CONTAINER delete_dns_fqdn $ALL_CIDRS
for CIDR in $IPAM_CIDRS ; do
call_weave DELETE /ip/$CONTAINER/${CIDR%/*}
@@ -2134,7 +2075,7 @@ EOF
for CIDR in $ALL_CIDRS ; do
call_weave PUT /ip/$CONTAINER/$CIDR?check-alive=true
done
with_container_netns_or_die $CONTAINER attach $ALL_CIDRS
do_or_die $CONTAINER attach $ALL_CIDRS
when_weave_running with_container_fqdn $CONTAINER put_dns_fqdn $ALL_CIDRS
echo $RES
;;