Browse code

Do not mask ipam driver if no ip config is passed

Signed-off-by: Alessandro Boch <aboch@docker.com>

Alessandro Boch authored on 2015/10/20 08:17:05
Showing 2 changed files
... ...
@@ -99,9 +99,7 @@ func (daemon *Daemon) CreateNetwork(name, driver string, ipam network.IPAM, opti
99 99
 		return nil, err
100 100
 	}
101 101
 
102
-	if len(ipam.Config) > 0 {
103
-		nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf))
104
-	}
102
+	nwOptions = append(nwOptions, libnetwork.NetworkOptionIpam(ipam.Driver, "", v4Conf, v6Conf))
105 103
 	nwOptions = append(nwOptions, libnetwork.NetworkOptionDriverOpts(options))
106 104
 	return c.NewNetwork(driver, name, nwOptions...)
107 105
 }
... ...
@@ -16,11 +16,14 @@ import (
16 16
 	"github.com/docker/docker/pkg/integration/checker"
17 17
 	"github.com/docker/libnetwork/driverapi"
18 18
 	remoteapi "github.com/docker/libnetwork/drivers/remote/api"
19
+	"github.com/docker/libnetwork/ipamapi"
20
+	remoteipam "github.com/docker/libnetwork/ipams/remote/api"
19 21
 	"github.com/docker/libnetwork/netlabel"
20 22
 	"github.com/go-check/check"
21 23
 )
22 24
 
23 25
 const dummyNetworkDriver = "dummy-network-driver"
26
+const dummyIpamDriver = "dummy-ipam-driver"
24 27
 
25 28
 var remoteDriverNetworkRequest remoteapi.CreateNetworkRequest
26 29
 
... ...
@@ -52,9 +55,10 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
52 52
 
53 53
 	mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
54 54
 		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
55
-		fmt.Fprintf(w, `{"Implements": ["%s"]}`, driverapi.NetworkPluginEndpointType)
55
+		fmt.Fprintf(w, `{"Implements": ["%s", "%s"]}`, driverapi.NetworkPluginEndpointType, ipamapi.PluginEndpointType)
56 56
 	})
57 57
 
58
+	// Network driver implementation
58 59
 	mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
59 60
 		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
60 61
 		fmt.Fprintf(w, `{"Scope":"local"}`)
... ...
@@ -75,12 +79,99 @@ func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
75 75
 		fmt.Fprintf(w, "null")
76 76
 	})
77 77
 
78
+	// Ipam Driver implementation
79
+	var (
80
+		poolRequest       remoteipam.RequestPoolRequest
81
+		poolReleaseReq    remoteipam.ReleasePoolRequest
82
+		addressRequest    remoteipam.RequestAddressRequest
83
+		addressReleaseReq remoteipam.ReleaseAddressRequest
84
+		lAS               = "localAS"
85
+		gAS               = "globalAS"
86
+		pool              = "172.28.0.0/16"
87
+		poolID            = lAS + "/" + pool
88
+		gw                = "172.28.255.254/16"
89
+	)
90
+
91
+	mux.HandleFunc(fmt.Sprintf("/%s.GetDefaultAddressSpaces", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
92
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
93
+		fmt.Fprintf(w, `{"LocalDefaultAddressSpace":"`+lAS+`", "GlobalDefaultAddressSpace": "`+gAS+`"}`)
94
+	})
95
+
96
+	mux.HandleFunc(fmt.Sprintf("/%s.RequestPool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
97
+		err := json.NewDecoder(r.Body).Decode(&poolRequest)
98
+		if err != nil {
99
+			http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
100
+			return
101
+		}
102
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
103
+		if poolRequest.AddressSpace != lAS && poolRequest.AddressSpace != gAS {
104
+			fmt.Fprintf(w, `{"Error":"Unknown address space in pool request: `+poolRequest.AddressSpace+`"}`)
105
+		} else if poolRequest.Pool != "" && poolRequest.Pool != pool {
106
+			fmt.Fprintf(w, `{"Error":"Cannot handle explicit pool requests yet"}`)
107
+		} else {
108
+			fmt.Fprintf(w, `{"PoolID":"`+poolID+`", "Pool":"`+pool+`"}`)
109
+		}
110
+	})
111
+
112
+	mux.HandleFunc(fmt.Sprintf("/%s.RequestAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
113
+		err := json.NewDecoder(r.Body).Decode(&addressRequest)
114
+		if err != nil {
115
+			http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
116
+			return
117
+		}
118
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
119
+		// make sure libnetwork is now querying on the expected pool id
120
+		if addressRequest.PoolID != poolID {
121
+			fmt.Fprintf(w, `{"Error":"unknown pool id"}`)
122
+		} else if addressRequest.Address != "" {
123
+			fmt.Fprintf(w, `{"Error":"Cannot handle explicit address requests yet"}`)
124
+		} else {
125
+			fmt.Fprintf(w, `{"Address":"`+gw+`"}`)
126
+		}
127
+	})
128
+
129
+	mux.HandleFunc(fmt.Sprintf("/%s.ReleaseAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
130
+		err := json.NewDecoder(r.Body).Decode(&addressReleaseReq)
131
+		if err != nil {
132
+			http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
133
+			return
134
+		}
135
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
136
+		// make sure libnetwork is now asking to release the expected address fro mthe expected poolid
137
+		if addressRequest.PoolID != poolID {
138
+			fmt.Fprintf(w, `{"Error":"unknown pool id"}`)
139
+		} else if addressReleaseReq.Address != gw {
140
+			fmt.Fprintf(w, `{"Error":"unknown address"}`)
141
+		} else {
142
+			fmt.Fprintf(w, "null")
143
+		}
144
+	})
145
+
146
+	mux.HandleFunc(fmt.Sprintf("/%s.ReleasePool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
147
+		err := json.NewDecoder(r.Body).Decode(&poolReleaseReq)
148
+		if err != nil {
149
+			http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
150
+			return
151
+		}
152
+		w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
153
+		// make sure libnetwork is now asking to release the expected poolid
154
+		if addressRequest.PoolID != poolID {
155
+			fmt.Fprintf(w, `{"Error":"unknown pool id"}`)
156
+		} else {
157
+			fmt.Fprintf(w, "null")
158
+		}
159
+	})
160
+
78 161
 	err := os.MkdirAll("/etc/docker/plugins", 0755)
79 162
 	c.Assert(err, checker.IsNil)
80 163
 
81 164
 	fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", dummyNetworkDriver)
82 165
 	err = ioutil.WriteFile(fileName, []byte(s.server.URL), 0644)
83 166
 	c.Assert(err, checker.IsNil)
167
+
168
+	ipamFileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", dummyIpamDriver)
169
+	err = ioutil.WriteFile(ipamFileName, []byte(s.server.URL), 0644)
170
+	c.Assert(err, checker.IsNil)
84 171
 }
85 172
 
86 173
 func (s *DockerNetworkSuite) TearDownSuite(c *check.C) {
... ...
@@ -227,6 +318,21 @@ func (s *DockerNetworkSuite) TestDockerNetworkIpamMultipleNetworks(c *check.C) {
227 227
 	}
228 228
 }
229 229
 
230
+func (s *DockerNetworkSuite) TestDockerNetworkCustomIpam(c *check.C) {
231
+	// Create a bridge network using custom ipam driver
232
+	dockerCmd(c, "network", "create", "--ipam-driver", dummyIpamDriver, "br0")
233
+	assertNwIsAvailable(c, "br0")
234
+
235
+	// Verify expected network ipam fields are there
236
+	nr := getNetworkResource(c, "br0")
237
+	c.Assert(nr.Driver, checker.Equals, "bridge")
238
+	c.Assert(nr.IPAM.Driver, checker.Equals, dummyIpamDriver)
239
+
240
+	// remove network and exercise remote ipam driver
241
+	dockerCmd(c, "network", "rm", "br0")
242
+	assertNwNotAvailable(c, "br0")
243
+}
244
+
230 245
 func (s *DockerNetworkSuite) TestDockerNetworkInspect(c *check.C) {
231 246
 	// if unspecified, network gateway will be selected from inside preferred pool
232 247
 	dockerCmd(c, "network", "create", "--driver=bridge", "--subnet=172.28.0.0/16", "--ip-range=172.28.5.0/24", "--gateway=172.28.5.254", "br0")