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

Commit

Permalink
add support for ips in ipam config
Browse files Browse the repository at this point in the history
  • Loading branch information
nonsense committed Jan 25, 2021
1 parent ba64f8e commit 49f007f
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 15 deletions.
81 changes: 66 additions & 15 deletions plugin/ipam/cni.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ipamplugin

import (
"encoding/json"
"errors"
"fmt"
"net"

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

if conf.Subnet == "" {
ipnet, err = i.weave.AllocateIP(containerID, false)
var ipconfigs []*current.IPConfig

if len(conf.IPs) > 0 {
// configuration includes desired IPs

var ips []net.IP
for _, ip := range conf.IPs {
ip4 := net.ParseIP(ip).To4()
ip16 := net.ParseIP(ip).To16()

if ip4 == nil && ip16 == nil {
return nil, errors.New("provided value is not an IP")
}

if ip4 == nil && ip16 != nil {
return nil, errors.New("allocation of ipv6 addresses is not implemented")
}

ips = append(ips, ip4)
}

for j := range ips {
ipnet := &net.IPNet{
IP: ips[j],
Mask: ips[j].DefaultMask(),
}

err := i.weave.ClaimIP(containerID, ipnet, false)
if err != nil {
return nil, err
}

ipconfigs = append(ipconfigs, &current.IPConfig{
Version: "4",
Address: *ipnet,
Gateway: conf.Gateway,
})
}
} else if conf.Subnet == "" {
// configuration doesn't include Subnet or IPs, so ask the allocator for an IP
ipnet, err := i.weave.AllocateIP(containerID, false)
if err != nil {
return nil, err
}

ipconfigs = append(ipconfigs, &current.IPConfig{
Version: "4",
Address: *ipnet,
Gateway: conf.Gateway,
})
} else {
var subnet *net.IPNet
subnet, err = types.ParseCIDR(conf.Subnet)
// configuration includes desired Subnet

subnet, err := types.ParseCIDR(conf.Subnet)
if err != nil {
return nil, fmt.Errorf("subnet given in config, but not parseable: %s", err)
}
ipnet, err = i.weave.AllocateIPInSubnet(containerID, subnet, false)
}
ipnet, err := i.weave.AllocateIPInSubnet(containerID, subnet, false)
if err != nil {
return nil, err
}

if err != nil {
return nil, err
}
result := &current.Result{
IPs: []*current.IPConfig{{
ipconfigs = append(ipconfigs, &current.IPConfig{
Version: "4",
Address: *ipnet,
Gateway: conf.Gateway,
}},
Routes: conf.Routes,
})
}
return result, nil

return &current.Result{
IPs: ipconfigs,
Routes: conf.Routes,
}, nil
}

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

type netConf struct {
Expand Down
91 changes: 91 additions & 0 deletions test/880_cni_plugin_ip_address_assignment_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#! /bin/bash

. "$(dirname "$0")/config.sh"

start_suite "Test CNI plugin"

cni_connect() {
pid=$(container_pid $1 $2)
id=$(docker_on $1 inspect -f '{{.Id}}' $2)
run_on $1 sudo CNI_COMMAND=ADD CNI_CONTAINERID=$id CNI_IFNAME=eth0 \
CNI_NETNS=/proc/$pid/ns/net CNI_PATH=/opt/cni/bin /opt/cni/bin/weave-net
}

run_on $HOST1 sudo mkdir -p /opt/cni/bin
# setup-cni is a subset of 'weave setup', without doing any 'docker pull's
weave_on $HOST1 setup-cni
weave_on $HOST1 launch

C0=$(docker_on $HOST1 run --net=none --name=c0 --privileged -dt $SMALL_IMAGE /bin/sh)
C1=$(docker_on $HOST1 run --net=none --name=c1 --privileged -dt $SMALL_IMAGE /bin/sh)
C2=$(docker_on $HOST1 run --net=none --name=c2 --privileged -dt $SMALL_IMAGE /bin/sh)

# Enable unsolicited ARPs so that ping after the address reuse does not time out
exec_on $HOST1 c1 sysctl -w net.ipv4.conf.all.arp_accept=1

cni_connect $HOST1 c0 <<EOF
{
"name": "weave",
"type": "weave-net",
"ipam": {
"type": "weave-ipam",
"ips": [
"10.32.1.30"
]
},
"hairpinMode": true
}
EOF

cni_connect $HOST1 c1 <<EOF
{
"name": "weave",
"type": "weave-net",
"ipam": {
"type": "weave-ipam",
"ips": [
"10.32.1.40"
]
},
"hairpinMode": true
}
EOF

cni_connect $HOST1 c2 <<EOF
{
"name": "weave",
"type": "weave-net",
"ipam": {
"type": "weave-ipam",
"ips": [
"10.32.1.42"
]
},
"hairpinMode": true
}
EOF


C0IP=$(container_ip $HOST1 c0)
C1IP=$(container_ip $HOST1 c1)
C2IP=$(container_ip $HOST1 c2)

echo $C0IP
echo $C1IP
echo $C2IP

# Ensure existing containers can reclaim their IP addresses after CNI has been used -- see #2548
stop_weave_on $HOST1

# Ensure no warning is printed to the standard error:
ACTUAL_OUTPUT=$(CHECKPOINT_DISABLE="$CHECKPOINT_DISABLE" $WEAVE launch 2>&1)
EXPECTED_OUTPUT=$(docker inspect --format="{{.Id}}" weave)

assert_raises "[ $EXPECTED_OUTPUT == $ACTUAL_OUTPUT ]"

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"
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"
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"


end_suite

0 comments on commit 49f007f

Please sign in to comment.