/
driver.go
139 lines (121 loc) · 3.83 KB
/
driver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package ipamplugin
import (
"fmt"
"net"
"strings"
"github.com/docker/libnetwork/discoverapi"
"github.com/docker/libnetwork/netlabel"
"github.com/weaveworks/weave/api"
"github.com/weaveworks/weave/common"
)
type Ipam struct {
weave *api.Client
}
func NewIpam(weave *api.Client) *Ipam {
return &Ipam{weave: weave}
}
func (i *Ipam) GetCapabilities() (RequiresMACAddress bool, RequiresRequestReplay bool, err error) {
i.logReq("GetCapabilities")
return false, false, nil
}
func (i *Ipam) GetDefaultAddressSpaces() (string, string, error) {
i.logReq("GetDefaultAddressSpaces")
return "weavelocal", "weaveglobal", nil
}
func (i *Ipam) RequestPool(addressSpace, pool, subPool string, options map[string]string, v6 bool) (poolname string, subnet *net.IPNet, data map[string]string, err error) {
i.logReq("RequestPool", addressSpace, pool, subPool, options)
defer func() { i.logRes("RequestPool", err, poolname, subnet, data) }()
if pool == "" {
subnet, err = i.weave.DefaultSubnet()
} else {
_, subnet, err = net.ParseCIDR(pool)
}
if err != nil {
return
}
iprange := subnet
if subPool != "" {
if _, iprange, err = net.ParseCIDR(subPool); err != nil {
return
}
}
// Cunningly-constructed pool "name" which gives us what we need later
poolname = strings.Join([]string{"weave", subnet.String(), iprange.String()}, "-")
// Pass back a fake "gateway address"; we don't actually use it,
// so just give the network address.
data = map[string]string{netlabel.Gateway: subnet.String()}
return
}
func (i *Ipam) ReleasePool(poolID string) error {
i.logReq("ReleasePool", poolID)
return nil
}
func splitPoolID(poolID string) (subnet, iprange *net.IPNet, err error) {
parts := strings.Split(poolID, "-")
if len(parts) != 3 || parts[0] != "weave" {
err = fmt.Errorf("Unrecognized pool ID: %s", poolID)
return
}
if _, subnet, err = net.ParseCIDR(parts[1]); err != nil {
return
}
if _, iprange, err = net.ParseCIDR(parts[2]); err != nil {
return
}
return
}
func (i *Ipam) RequestAddress(poolID string, address net.IP, options map[string]string) (ip *net.IPNet, _ map[string]string, err error) {
i.logReq("RequestAddress", poolID, address, options)
defer func() { i.logRes("RequestAddress", err, ip) }()
if poolID == "weavepool" { // old-style
ip, err = i.weave.AllocateIP(api.NoContainerID, false)
return
}
subnet, iprange, err := splitPoolID(poolID)
if err != nil {
return
}
if address != nil { // try to claim specific address requested
ip = &net.IPNet{IP: address, Mask: subnet.Mask}
if err = i.weave.ClaimIP(api.NoContainerID, ip, false); err != nil {
return
}
} else {
// We are lying slightly to IPAM here: the range is not a subnet
if ip, err = i.weave.AllocateIPInSubnet(api.NoContainerID, iprange, false); err != nil {
return
}
ip.Mask = subnet.Mask // fix up the subnet we lied about
}
return
}
func (i *Ipam) ReleaseAddress(poolID string, address net.IP) error {
i.logReq("ReleaseAddress", poolID, address)
if subnet, _, err := splitPoolID(poolID); err != nil {
return err
} else if address.Equal(subnet.IP) { // is it the gateway address we faked earlier?
return nil
}
return i.weave.ReleaseIPsFor(address.String())
}
func (i *Ipam) IsBuiltIn() bool {
return false
}
// Functions required by ipamapi "contract" but not actually used.
func (i *Ipam) DiscoverNew(discoverapi.DiscoveryType, interface{}) error {
return nil
}
func (i *Ipam) DiscoverDelete(discoverapi.DiscoveryType, interface{}) error {
return nil
}
// logging
func (i *Ipam) logReq(fun string, args ...interface{}) {
common.Log.Infoln(append([]interface{}{fmt.Sprintf("[ipam] %s", fun)}, args...)...)
}
func (i *Ipam) logRes(fun string, err error, args ...interface{}) {
if err == nil {
common.Log.Debugln(append([]interface{}{fmt.Sprintf("[ipam] %s result", fun)}, args...)...)
return
}
common.Log.Errorf("[ipam] %s: %s", fun, err)
}