Skip to content
This repository was archived by the owner on Jun 20, 2024. It is now read-only.

Commit d14fa9e

Browse files
committed
add support for ips in ipam config
1 parent ba64f8e commit d14fa9e

File tree

2 files changed

+157
-15
lines changed

2 files changed

+157
-15
lines changed

plugin/ipam/cni.go

+66-15
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package ipamplugin
22

33
import (
44
"encoding/json"
5+
"errors"
56
"fmt"
67
"net"
78

@@ -35,31 +36,80 @@ func (i *Ipam) Allocate(args *skel.CmdArgs) (types.Result, error) {
3536
if containerID == "" {
3637
return nil, fmt.Errorf("Weave CNI Allocate: blank container name")
3738
}
38-
var ipnet *net.IPNet
3939

40-
if conf.Subnet == "" {
41-
ipnet, err = i.weave.AllocateIP(containerID, false)
40+
var ipconfigs []*current.IPConfig
41+
42+
if len(conf.IPs) > 0 {
43+
// configuration includes desired IPs
44+
45+
var ips []net.IP
46+
for _, ip := range conf.IPs {
47+
ip4 := net.ParseIP(ip).To4()
48+
ip16 := net.ParseIP(ip).To16()
49+
50+
if ip4 == nil && ip16 == nil {
51+
return nil, errors.New("provided value is not an IP")
52+
}
53+
54+
if ip4 == nil && ip16 != nil {
55+
return nil, errors.New("allocation of ipv6 addresses is not implemented")
56+
}
57+
58+
ips = append(ips, ip4)
59+
}
60+
61+
for j := range ips {
62+
ipnet := &net.IPNet{
63+
IP: ips[j],
64+
Mask: net.CIDRMask(32, 32),
65+
}
66+
67+
err := i.weave.ClaimIP(containerID, ipnet, false)
68+
if err != nil {
69+
return nil, err
70+
}
71+
72+
ipconfigs = append(ipconfigs, &current.IPConfig{
73+
Version: "4",
74+
Address: *ipnet,
75+
Gateway: conf.Gateway,
76+
})
77+
}
78+
} else if conf.Subnet == "" {
79+
// configuration doesn't include Subnet or IPs, so ask the allocator for an IP
80+
ipnet, err := i.weave.AllocateIP(containerID, false)
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
ipconfigs = append(ipconfigs, &current.IPConfig{
86+
Version: "4",
87+
Address: *ipnet,
88+
Gateway: conf.Gateway,
89+
})
4290
} else {
43-
var subnet *net.IPNet
44-
subnet, err = types.ParseCIDR(conf.Subnet)
91+
// configuration includes desired Subnet
92+
93+
subnet, err := types.ParseCIDR(conf.Subnet)
4594
if err != nil {
4695
return nil, fmt.Errorf("subnet given in config, but not parseable: %s", err)
4796
}
48-
ipnet, err = i.weave.AllocateIPInSubnet(containerID, subnet, false)
49-
}
97+
ipnet, err := i.weave.AllocateIPInSubnet(containerID, subnet, false)
98+
if err != nil {
99+
return nil, err
100+
}
50101

51-
if err != nil {
52-
return nil, err
53-
}
54-
result := &current.Result{
55-
IPs: []*current.IPConfig{{
102+
ipconfigs = append(ipconfigs, &current.IPConfig{
56103
Version: "4",
57104
Address: *ipnet,
58105
Gateway: conf.Gateway,
59-
}},
60-
Routes: conf.Routes,
106+
})
61107
}
62-
return result, nil
108+
109+
return &current.Result{
110+
IPs: ipconfigs,
111+
Routes: conf.Routes,
112+
}, nil
63113
}
64114

65115
func (i *Ipam) CmdDel(args *skel.CmdArgs) error {
@@ -74,6 +124,7 @@ type ipamConf struct {
74124
Subnet string `json:"subnet,omitempty"`
75125
Gateway net.IP `json:"gateway,omitempty"`
76126
Routes []*types.Route `json:"routes"`
127+
IPs []string `json:"ips,omitempty"`
77128
}
78129

79130
type netConf struct {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#! /bin/bash
2+
3+
. "$(dirname "$0")/config.sh"
4+
5+
start_suite "Test CNI plugin"
6+
7+
cni_connect() {
8+
pid=$(container_pid $1 $2)
9+
id=$(docker_on $1 inspect -f '{{.Id}}' $2)
10+
run_on $1 sudo CNI_COMMAND=ADD CNI_CONTAINERID=$id CNI_IFNAME=eth0 \
11+
CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net
12+
}
13+
14+
run_on $HOST1 sudo mkdir -p /opt/cni/bin
15+
# setup-cni is a subset of 'weave setup', without doing any 'docker pull's
16+
weave_on $HOST1 setup-cni
17+
weave_on $HOST1 launch
18+
19+
C0=$(docker_on $HOST1 run --net=none --name=c0 --privileged -dt $SMALL_IMAGE /bin/sh)
20+
C1=$(docker_on $HOST1 run --net=none --name=c1 --privileged -dt $SMALL_IMAGE /bin/sh)
21+
C2=$(docker_on $HOST1 run --net=none --name=c2 --privileged -dt $SMALL_IMAGE /bin/sh)
22+
23+
# Enable unsolicited ARPs so that ping after the address reuse does not time out
24+
exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1
25+
26+
cni_connect $HOST1 c0 <<EOF
27+
{
28+
"name": "weave",
29+
"type": "weave-net",
30+
"ipam": {
31+
"type": "weave-ipam",
32+
"ips": [
33+
"10.32.1.30"
34+
]
35+
},
36+
"hairpinMode": true
37+
}
38+
EOF
39+
40+
cni_connect $HOST1 c1 <<EOF
41+
{
42+
"name": "weave",
43+
"type": "weave-net",
44+
"ipam": {
45+
"type": "weave-ipam",
46+
"ips": [
47+
"10.32.1.40"
48+
]
49+
},
50+
"hairpinMode": true
51+
}
52+
EOF
53+
54+
cni_connect $HOST1 c2 <<EOF
55+
{
56+
"name": "weave",
57+
"type": "weave-net",
58+
"ipam": {
59+
"type": "weave-ipam",
60+
"ips": [
61+
"10.32.1.42"
62+
]
63+
},
64+
"hairpinMode": true
65+
}
66+
EOF
67+
68+
69+
C0IP=$(container_ip $HOST1 c0)
70+
C1IP=$(container_ip $HOST1 c1)
71+
C2IP=$(container_ip $HOST1 c2)
72+
73+
echo $C0IP
74+
echo $C1IP
75+
echo $C2IP
76+
77+
# Ensure existing containers can reclaim their IP addresses after CNI has been used -- see #2548
78+
stop_weave_on $HOST1
79+
80+
# Ensure no warning is printed to the standard error:
81+
ACTUAL_OUTPUT=$(CHECKPOINT_DISABLE="$CHECKPOINT_DISABLE" $WEAVE launch 2>&1)
82+
EXPECTED_OUTPUT=$(docker inspect --format="{{.Id}}" weave)
83+
84+
assert_raises "[ $EXPECTED_OUTPUT == $ACTUAL_OUTPUT ]"
85+
86+
assert "$SSH $HOST1 \"curl -s -X GET 127.0.0.1:6784/ip/$C1 | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'\"" "$C1IP"
87+
assert "$SSH $HOST1 \"curl -s -X GET 127.0.0.1:6784/ip/$C2 | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'\"" "$C2IP"
88+
assert "$SSH $HOST1 \"curl -s -X GET 127.0.0.1:6784/ip/$C3 | grep -o -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'\"" "$C3IP"
89+
90+
91+
end_suite

0 commit comments

Comments
 (0)