Tizen_4.0 base
[platform/upstream/docker-engine.git] / integration-cli / docker_cli_network_unix_test.go
1 // +build !windows
2
3 package main
4
5 import (
6         "encoding/json"
7         "fmt"
8         "io/ioutil"
9         "net"
10         "net/http"
11         "net/http/httptest"
12         "os"
13         "path/filepath"
14         "strings"
15         "syscall"
16         "time"
17
18         "github.com/docker/docker/api/types"
19         "github.com/docker/docker/api/types/versions/v1p20"
20         "github.com/docker/docker/integration-cli/checker"
21         "github.com/docker/docker/integration-cli/cli"
22         "github.com/docker/docker/integration-cli/daemon"
23         "github.com/docker/docker/pkg/stringid"
24         icmd "github.com/docker/docker/pkg/testutil/cmd"
25         "github.com/docker/docker/runconfig"
26         "github.com/docker/libnetwork/driverapi"
27         remoteapi "github.com/docker/libnetwork/drivers/remote/api"
28         "github.com/docker/libnetwork/ipamapi"
29         remoteipam "github.com/docker/libnetwork/ipams/remote/api"
30         "github.com/docker/libnetwork/netlabel"
31         "github.com/go-check/check"
32         "github.com/vishvananda/netlink"
33 )
34
35 const dummyNetworkDriver = "dummy-network-driver"
36 const dummyIPAMDriver = "dummy-ipam-driver"
37
38 var remoteDriverNetworkRequest remoteapi.CreateNetworkRequest
39
40 func init() {
41         check.Suite(&DockerNetworkSuite{
42                 ds: &DockerSuite{},
43         })
44 }
45
46 type DockerNetworkSuite struct {
47         server *httptest.Server
48         ds     *DockerSuite
49         d      *daemon.Daemon
50 }
51
52 func (s *DockerNetworkSuite) SetUpTest(c *check.C) {
53         s.d = daemon.New(c, dockerBinary, dockerdBinary, daemon.Config{
54                 Experimental: testEnv.ExperimentalDaemon(),
55         })
56 }
57
58 func (s *DockerNetworkSuite) TearDownTest(c *check.C) {
59         if s.d != nil {
60                 s.d.Stop(c)
61                 s.ds.TearDownTest(c)
62         }
63 }
64
65 func (s *DockerNetworkSuite) SetUpSuite(c *check.C) {
66         mux := http.NewServeMux()
67         s.server = httptest.NewServer(mux)
68         c.Assert(s.server, check.NotNil, check.Commentf("Failed to start an HTTP Server"))
69         setupRemoteNetworkDrivers(c, mux, s.server.URL, dummyNetworkDriver, dummyIPAMDriver)
70 }
71
72 func setupRemoteNetworkDrivers(c *check.C, mux *http.ServeMux, url, netDrv, ipamDrv string) {
73
74         mux.HandleFunc("/Plugin.Activate", func(w http.ResponseWriter, r *http.Request) {
75                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
76                 fmt.Fprintf(w, `{"Implements": ["%s", "%s"]}`, driverapi.NetworkPluginEndpointType, ipamapi.PluginEndpointType)
77         })
78
79         // Network driver implementation
80         mux.HandleFunc(fmt.Sprintf("/%s.GetCapabilities", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
81                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
82                 fmt.Fprintf(w, `{"Scope":"local"}`)
83         })
84
85         mux.HandleFunc(fmt.Sprintf("/%s.CreateNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
86                 err := json.NewDecoder(r.Body).Decode(&remoteDriverNetworkRequest)
87                 if err != nil {
88                         http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
89                         return
90                 }
91                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
92                 fmt.Fprintf(w, "null")
93         })
94
95         mux.HandleFunc(fmt.Sprintf("/%s.DeleteNetwork", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
96                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
97                 fmt.Fprintf(w, "null")
98         })
99
100         mux.HandleFunc(fmt.Sprintf("/%s.CreateEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
101                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
102                 fmt.Fprintf(w, `{"Interface":{"MacAddress":"a0:b1:c2:d3:e4:f5"}}`)
103         })
104
105         mux.HandleFunc(fmt.Sprintf("/%s.Join", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
106                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
107
108                 veth := &netlink.Veth{
109                         LinkAttrs: netlink.LinkAttrs{Name: "randomIfName", TxQLen: 0}, PeerName: "cnt0"}
110                 if err := netlink.LinkAdd(veth); err != nil {
111                         fmt.Fprintf(w, `{"Error":"failed to add veth pair: `+err.Error()+`"}`)
112                 } else {
113                         fmt.Fprintf(w, `{"InterfaceName":{ "SrcName":"cnt0", "DstPrefix":"veth"}}`)
114                 }
115         })
116
117         mux.HandleFunc(fmt.Sprintf("/%s.Leave", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
118                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
119                 fmt.Fprintf(w, "null")
120         })
121
122         mux.HandleFunc(fmt.Sprintf("/%s.DeleteEndpoint", driverapi.NetworkPluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
123                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
124                 if link, err := netlink.LinkByName("cnt0"); err == nil {
125                         netlink.LinkDel(link)
126                 }
127                 fmt.Fprintf(w, "null")
128         })
129
130         // IPAM Driver implementation
131         var (
132                 poolRequest       remoteipam.RequestPoolRequest
133                 poolReleaseReq    remoteipam.ReleasePoolRequest
134                 addressRequest    remoteipam.RequestAddressRequest
135                 addressReleaseReq remoteipam.ReleaseAddressRequest
136                 lAS               = "localAS"
137                 gAS               = "globalAS"
138                 pool              = "172.28.0.0/16"
139                 poolID            = lAS + "/" + pool
140                 gw                = "172.28.255.254/16"
141         )
142
143         mux.HandleFunc(fmt.Sprintf("/%s.GetDefaultAddressSpaces", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
144                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
145                 fmt.Fprintf(w, `{"LocalDefaultAddressSpace":"`+lAS+`", "GlobalDefaultAddressSpace": "`+gAS+`"}`)
146         })
147
148         mux.HandleFunc(fmt.Sprintf("/%s.RequestPool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
149                 err := json.NewDecoder(r.Body).Decode(&poolRequest)
150                 if err != nil {
151                         http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
152                         return
153                 }
154                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
155                 if poolRequest.AddressSpace != lAS && poolRequest.AddressSpace != gAS {
156                         fmt.Fprintf(w, `{"Error":"Unknown address space in pool request: `+poolRequest.AddressSpace+`"}`)
157                 } else if poolRequest.Pool != "" && poolRequest.Pool != pool {
158                         fmt.Fprintf(w, `{"Error":"Cannot handle explicit pool requests yet"}`)
159                 } else {
160                         fmt.Fprintf(w, `{"PoolID":"`+poolID+`", "Pool":"`+pool+`"}`)
161                 }
162         })
163
164         mux.HandleFunc(fmt.Sprintf("/%s.RequestAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
165                 err := json.NewDecoder(r.Body).Decode(&addressRequest)
166                 if err != nil {
167                         http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
168                         return
169                 }
170                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
171                 // make sure libnetwork is now querying on the expected pool id
172                 if addressRequest.PoolID != poolID {
173                         fmt.Fprintf(w, `{"Error":"unknown pool id"}`)
174                 } else if addressRequest.Address != "" {
175                         fmt.Fprintf(w, `{"Error":"Cannot handle explicit address requests yet"}`)
176                 } else {
177                         fmt.Fprintf(w, `{"Address":"`+gw+`"}`)
178                 }
179         })
180
181         mux.HandleFunc(fmt.Sprintf("/%s.ReleaseAddress", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
182                 err := json.NewDecoder(r.Body).Decode(&addressReleaseReq)
183                 if err != nil {
184                         http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
185                         return
186                 }
187                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
188                 // make sure libnetwork is now asking to release the expected address from the expected poolid
189                 if addressRequest.PoolID != poolID {
190                         fmt.Fprintf(w, `{"Error":"unknown pool id"}`)
191                 } else if addressReleaseReq.Address != gw {
192                         fmt.Fprintf(w, `{"Error":"unknown address"}`)
193                 } else {
194                         fmt.Fprintf(w, "null")
195                 }
196         })
197
198         mux.HandleFunc(fmt.Sprintf("/%s.ReleasePool", ipamapi.PluginEndpointType), func(w http.ResponseWriter, r *http.Request) {
199                 err := json.NewDecoder(r.Body).Decode(&poolReleaseReq)
200                 if err != nil {
201                         http.Error(w, "Unable to decode JSON payload: "+err.Error(), http.StatusBadRequest)
202                         return
203                 }
204                 w.Header().Set("Content-Type", "application/vnd.docker.plugins.v1+json")
205                 // make sure libnetwork is now asking to release the expected poolid
206                 if addressRequest.PoolID != poolID {
207                         fmt.Fprintf(w, `{"Error":"unknown pool id"}`)
208                 } else {
209                         fmt.Fprintf(w, "null")
210                 }
211         })
212
213         err := os.MkdirAll("/etc/docker/plugins", 0755)
214         c.Assert(err, checker.IsNil)
215
216         fileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", netDrv)
217         err = ioutil.WriteFile(fileName, []byte(url), 0644)
218         c.Assert(err, checker.IsNil)
219
220         ipamFileName := fmt.Sprintf("/etc/docker/plugins/%s.spec", ipamDrv)
221         err = ioutil.WriteFile(ipamFileName, []byte(url), 0644)
222         c.Assert(err, checker.IsNil)
223 }
224
225 func (s *DockerNetworkSuite) TearDownSuite(c *check.C) {
226         if s.server == nil {
227                 return
228         }
229
230         s.server.Close()
231
232         err := os.RemoveAll("/etc/docker/plugins")
233         c.Assert(err, checker.IsNil)
234 }
235
236 func assertNwIsAvailable(c *check.C, name string) {
237         if !isNwPresent(c, name) {
238                 c.Fatalf("Network %s not found in network ls o/p", name)
239         }
240 }
241
242 func assertNwNotAvailable(c *check.C, name string) {
243         if isNwPresent(c, name) {
244                 c.Fatalf("Found network %s in network ls o/p", name)
245         }
246 }
247
248 func isNwPresent(c *check.C, name string) bool {
249         out, _ := dockerCmd(c, "network", "ls")
250         lines := strings.Split(out, "\n")
251         for i := 1; i < len(lines)-1; i++ {
252                 netFields := strings.Fields(lines[i])
253                 if netFields[1] == name {
254                         return true
255                 }
256         }
257         return false
258 }
259
260 // assertNwList checks network list retrieved with ls command
261 // equals to expected network list
262 // note: out should be `network ls [option]` result
263 func assertNwList(c *check.C, out string, expectNws []string) {
264         lines := strings.Split(out, "\n")
265         var nwList []string
266         for _, line := range lines[1 : len(lines)-1] {
267                 netFields := strings.Fields(line)
268                 // wrap all network name in nwList
269                 nwList = append(nwList, netFields[1])
270         }
271
272         // network ls should contains all expected networks
273         c.Assert(nwList, checker.DeepEquals, expectNws)
274 }
275
276 func getNwResource(c *check.C, name string) *types.NetworkResource {
277         out, _ := dockerCmd(c, "network", "inspect", name)
278         nr := []types.NetworkResource{}
279         err := json.Unmarshal([]byte(out), &nr)
280         c.Assert(err, check.IsNil)
281         return &nr[0]
282 }
283
284 func (s *DockerNetworkSuite) TestDockerNetworkLsDefault(c *check.C) {
285         defaults := []string{"bridge", "host", "none"}
286         for _, nn := range defaults {
287                 assertNwIsAvailable(c, nn)
288         }
289 }
290
291 func (s *DockerSuite) TestNetworkLsFormat(c *check.C) {
292         testRequires(c, DaemonIsLinux)
293         out, _ := dockerCmd(c, "network", "ls", "--format", "{{.Name}}")
294         lines := strings.Split(strings.TrimSpace(string(out)), "\n")
295
296         expected := []string{"bridge", "host", "none"}
297         var names []string
298         names = append(names, lines...)
299         c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
300 }
301
302 func (s *DockerSuite) TestNetworkLsFormatDefaultFormat(c *check.C) {
303         testRequires(c, DaemonIsLinux)
304
305         config := `{
306                 "networksFormat": "{{ .Name }} default"
307 }`
308         d, err := ioutil.TempDir("", "integration-cli-")
309         c.Assert(err, checker.IsNil)
310         defer os.RemoveAll(d)
311
312         err = ioutil.WriteFile(filepath.Join(d, "config.json"), []byte(config), 0644)
313         c.Assert(err, checker.IsNil)
314
315         out, _ := dockerCmd(c, "--config", d, "network", "ls")
316         lines := strings.Split(strings.TrimSpace(string(out)), "\n")
317
318         expected := []string{"bridge default", "host default", "none default"}
319         var names []string
320         names = append(names, lines...)
321         c.Assert(expected, checker.DeepEquals, names, check.Commentf("Expected array with truncated names: %v, got: %v", expected, names))
322 }
323
324 func (s *DockerNetworkSuite) TestDockerNetworkCreatePredefined(c *check.C) {
325         predefined := []string{"bridge", "host", "none", "default"}
326         for _, net := range predefined {
327                 // predefined networks can't be created again
328                 out, _, err := dockerCmdWithError("network", "create", net)
329                 c.Assert(err, checker.NotNil, check.Commentf("%v", out))
330         }
331 }
332
333 func (s *DockerNetworkSuite) TestDockerNetworkCreateHostBind(c *check.C) {
334         dockerCmd(c, "network", "create", "--subnet=192.168.10.0/24", "--gateway=192.168.10.1", "-o", "com.docker.network.bridge.host_binding_ipv4=192.168.10.1", "testbind")
335         assertNwIsAvailable(c, "testbind")
336
337         out := runSleepingContainer(c, "--net=testbind", "-p", "5000:5000")
338         id := strings.TrimSpace(out)
339         c.Assert(waitRun(id), checker.IsNil)
340         out, _ = dockerCmd(c, "ps")
341         c.Assert(out, checker.Contains, "192.168.10.1:5000->5000/tcp")
342 }
343
344 func (s *DockerNetworkSuite) TestDockerNetworkRmPredefined(c *check.C) {
345         predefined := []string{"bridge", "host", "none", "default"}
346         for _, net := range predefined {
347                 // predefined networks can't be removed
348                 out, _, err := dockerCmdWithError("network", "rm", net)
349                 c.Assert(err, checker.NotNil, check.Commentf("%v", out))
350         }
351 }
352
353 func (s *DockerNetworkSuite) TestDockerNetworkLsFilter(c *check.C) {
354         testNet := "testnet1"
355         testLabel := "foo"
356         testValue := "bar"
357         out, _ := dockerCmd(c, "network", "create", "dev")
358         defer func() {
359                 dockerCmd(c, "network", "rm", "dev")
360                 dockerCmd(c, "network", "rm", testNet)
361         }()
362         networkID := strings.TrimSpace(out)
363
364         // filter with partial ID
365         // only show 'dev' network
366         out, _ = dockerCmd(c, "network", "ls", "-f", "id="+networkID[0:5])
367         assertNwList(c, out, []string{"dev"})
368
369         out, _ = dockerCmd(c, "network", "ls", "-f", "name=dge")
370         assertNwList(c, out, []string{"bridge"})
371
372         // only show built-in network (bridge, none, host)
373         out, _ = dockerCmd(c, "network", "ls", "-f", "type=builtin")
374         assertNwList(c, out, []string{"bridge", "host", "none"})
375
376         // only show custom networks (dev)
377         out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom")
378         assertNwList(c, out, []string{"dev"})
379
380         // show all networks with filter
381         // it should be equivalent of ls without option
382         out, _ = dockerCmd(c, "network", "ls", "-f", "type=custom", "-f", "type=builtin")
383         assertNwList(c, out, []string{"bridge", "dev", "host", "none"})
384
385         out, _ = dockerCmd(c, "network", "create", "--label", testLabel+"="+testValue, testNet)
386         assertNwIsAvailable(c, testNet)
387
388         out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel)
389         assertNwList(c, out, []string{testNet})
390
391         out, _ = dockerCmd(c, "network", "ls", "-f", "label="+testLabel+"="+testValue)
392         assertNwList(c, out, []string{testNet})
393
394         out, _ = dockerCmd(c, "network", "ls", "-f", "label=nonexistent")
395         outArr := strings.Split(strings.TrimSpace(out), "\n")
396         c.Assert(len(outArr), check.Equals, 1, check.Commentf("%s\n", out))
397
398         out, _ = dockerCmd(c, "network", "ls", "-f", "driver=null")
399         assertNwList(c, out, []string{"none"})
400
401         out, _ = dockerCmd(c, "network", "ls", "-f", "driver=host")
402         assertNwList(c, out, []string{"host"})
403
404         out, _ = dockerCmd(c, "network", "ls", "-f", "driver=bridge")
405         assertNwList(c, out, []string{"bridge", "dev", testNet})
406 }
407
408 func (s *DockerNetworkSuite) TestDockerNetworkCreateDelete(c *check.C) {
409         dockerCmd(c, "network", "create", "test")
410         assertNwIsAvailable(c, "test")
411
412         dockerCmd(c, "network", "rm", "test")
413         assertNwNotAvailable(c, "test")
414 }
415
416 func (s *DockerNetworkSuite) TestDockerNetworkCreateLabel(c *check.C) {
417         testNet := "testnetcreatelabel"
418         testLabel := "foo"
419         testValue := "bar"
420
421         dockerCmd(c, "network", "create", "--label", testLabel+"="+testValue, testNet)
422         assertNwIsAvailable(c, testNet)
423
424         out, _, err := dockerCmdWithError("network", "inspect", "--format={{ .Labels."+testLabel+" }}", testNet)
425         c.Assert(err, check.IsNil)
426         c.Assert(strings.TrimSpace(out), check.Equals, testValue)
427
428         dockerCmd(c, "network", "rm", testNet)
429         assertNwNotAvailable(c, testNet)
430 }
431
432 func (s *DockerSuite) TestDockerNetworkDeleteNotExists(c *check.C) {
433         out, _, err := dockerCmdWithError("network", "rm", "test")
434         c.Assert(err, checker.NotNil, check.Commentf("%v", out))
435 }
436
437 func (s *DockerSuite) TestDockerNetworkDeleteMultiple(c *check.C) {
438         dockerCmd(c, "network", "create", "testDelMulti0")
439         assertNwIsAvailable(c, "testDelMulti0")
440         dockerCmd(c, "network", "create", "testDelMulti1")
441         assertNwIsAvailable(c, "testDelMulti1")
442         dockerCmd(c, "network", "create", "testDelMulti2")
443         assertNwIsAvailable(c, "testDelMulti2")
444         out, _ := dockerCmd(c, "run", "-d", "--net", "testDelMulti2", "busybox", "top")
445         containerID := strings.TrimSpace(out)
446         waitRun(containerID)
447
448         // delete three networks at the same time, since testDelMulti2
449         // contains active container, its deletion should fail.
450         out, _, err := dockerCmdWithError("network", "rm", "testDelMulti0", "testDelMulti1", "testDelMulti2")
451         // err should not be nil due to deleting testDelMulti2 failed.
452         c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
453         // testDelMulti2 should fail due to network has active endpoints
454         c.Assert(out, checker.Contains, "has active endpoints")
455         assertNwNotAvailable(c, "testDelMulti0")
456         assertNwNotAvailable(c, "testDelMulti1")
457         // testDelMulti2 can't be deleted, so it should exist
458         assertNwIsAvailable(c, "testDelMulti2")
459 }
460
461 func (s *DockerSuite) TestDockerNetworkInspect(c *check.C) {
462         out, _ := dockerCmd(c, "network", "inspect", "host")
463         networkResources := []types.NetworkResource{}
464         err := json.Unmarshal([]byte(out), &networkResources)
465         c.Assert(err, check.IsNil)
466         c.Assert(networkResources, checker.HasLen, 1)
467
468         out, _ = dockerCmd(c, "network", "inspect", "--format={{ .Name }}", "host")
469         c.Assert(strings.TrimSpace(out), check.Equals, "host")
470 }
471
472 func (s *DockerSuite) TestDockerNetworkInspectWithID(c *check.C) {
473         out, _ := dockerCmd(c, "network", "create", "test2")
474         networkID := strings.TrimSpace(out)
475         assertNwIsAvailable(c, "test2")
476         out, _ = dockerCmd(c, "network", "inspect", "--format={{ .Id }}", "test2")
477         c.Assert(strings.TrimSpace(out), check.Equals, networkID)
478
479         out, _ = dockerCmd(c, "network", "inspect", "--format={{ .ID }}", "test2")
480         c.Assert(strings.TrimSpace(out), check.Equals, networkID)
481 }
482
483 func (s *DockerSuite) TestDockerInspectMultipleNetwork(c *check.C) {
484         result := dockerCmdWithResult("network", "inspect", "host", "none")
485         c.Assert(result, icmd.Matches, icmd.Success)
486
487         networkResources := []types.NetworkResource{}
488         err := json.Unmarshal([]byte(result.Stdout()), &networkResources)
489         c.Assert(err, check.IsNil)
490         c.Assert(networkResources, checker.HasLen, 2)
491 }
492
493 func (s *DockerSuite) TestDockerInspectMultipleNetworksIncludingNonexistent(c *check.C) {
494         // non-existent network was not at the beginning of the inspect list
495         // This should print an error, return an exitCode 1 and print the host network
496         result := dockerCmdWithResult("network", "inspect", "host", "nonexistent")
497         c.Assert(result, icmd.Matches, icmd.Expected{
498                 ExitCode: 1,
499                 Err:      "Error: No such network: nonexistent",
500                 Out:      "host",
501         })
502
503         networkResources := []types.NetworkResource{}
504         err := json.Unmarshal([]byte(result.Stdout()), &networkResources)
505         c.Assert(err, check.IsNil)
506         c.Assert(networkResources, checker.HasLen, 1)
507
508         // Only one non-existent network to inspect
509         // Should print an error and return an exitCode, nothing else
510         result = dockerCmdWithResult("network", "inspect", "nonexistent")
511         c.Assert(result, icmd.Matches, icmd.Expected{
512                 ExitCode: 1,
513                 Err:      "Error: No such network: nonexistent",
514                 Out:      "[]",
515         })
516
517         // non-existent network was at the beginning of the inspect list
518         // Should not fail fast, and still print host network but print an error
519         result = dockerCmdWithResult("network", "inspect", "nonexistent", "host")
520         c.Assert(result, icmd.Matches, icmd.Expected{
521                 ExitCode: 1,
522                 Err:      "Error: No such network: nonexistent",
523                 Out:      "host",
524         })
525
526         networkResources = []types.NetworkResource{}
527         err = json.Unmarshal([]byte(result.Stdout()), &networkResources)
528         c.Assert(err, check.IsNil)
529         c.Assert(networkResources, checker.HasLen, 1)
530 }
531
532 func (s *DockerSuite) TestDockerInspectNetworkWithContainerName(c *check.C) {
533         dockerCmd(c, "network", "create", "brNetForInspect")
534         assertNwIsAvailable(c, "brNetForInspect")
535         defer func() {
536                 dockerCmd(c, "network", "rm", "brNetForInspect")
537                 assertNwNotAvailable(c, "brNetForInspect")
538         }()
539
540         out, _ := dockerCmd(c, "run", "-d", "--name", "testNetInspect1", "--net", "brNetForInspect", "busybox", "top")
541         c.Assert(waitRun("testNetInspect1"), check.IsNil)
542         containerID := strings.TrimSpace(out)
543         defer func() {
544                 // we don't stop container by name, because we'll rename it later
545                 dockerCmd(c, "stop", containerID)
546         }()
547
548         out, _ = dockerCmd(c, "network", "inspect", "brNetForInspect")
549         networkResources := []types.NetworkResource{}
550         err := json.Unmarshal([]byte(out), &networkResources)
551         c.Assert(err, check.IsNil)
552         c.Assert(networkResources, checker.HasLen, 1)
553         container, ok := networkResources[0].Containers[containerID]
554         c.Assert(ok, checker.True)
555         c.Assert(container.Name, checker.Equals, "testNetInspect1")
556
557         // rename container and check docker inspect output update
558         newName := "HappyNewName"
559         dockerCmd(c, "rename", "testNetInspect1", newName)
560
561         // check whether network inspect works properly
562         out, _ = dockerCmd(c, "network", "inspect", "brNetForInspect")
563         newNetRes := []types.NetworkResource{}
564         err = json.Unmarshal([]byte(out), &newNetRes)
565         c.Assert(err, check.IsNil)
566         c.Assert(newNetRes, checker.HasLen, 1)
567         container1, ok := newNetRes[0].Containers[containerID]
568         c.Assert(ok, checker.True)
569         c.Assert(container1.Name, checker.Equals, newName)
570
571 }
572
573 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnect(c *check.C) {
574         dockerCmd(c, "network", "create", "test")
575         assertNwIsAvailable(c, "test")
576         nr := getNwResource(c, "test")
577
578         c.Assert(nr.Name, checker.Equals, "test")
579         c.Assert(len(nr.Containers), checker.Equals, 0)
580
581         // run a container
582         out, _ := dockerCmd(c, "run", "-d", "--name", "test", "busybox", "top")
583         c.Assert(waitRun("test"), check.IsNil)
584         containerID := strings.TrimSpace(out)
585
586         // connect the container to the test network
587         dockerCmd(c, "network", "connect", "test", containerID)
588
589         // inspect the network to make sure container is connected
590         nr = getNetworkResource(c, nr.ID)
591         c.Assert(len(nr.Containers), checker.Equals, 1)
592         c.Assert(nr.Containers[containerID], check.NotNil)
593
594         // check if container IP matches network inspect
595         ip, _, err := net.ParseCIDR(nr.Containers[containerID].IPv4Address)
596         c.Assert(err, check.IsNil)
597         containerIP := findContainerIP(c, "test", "test")
598         c.Assert(ip.String(), checker.Equals, containerIP)
599
600         // disconnect container from the network
601         dockerCmd(c, "network", "disconnect", "test", containerID)
602         nr = getNwResource(c, "test")
603         c.Assert(nr.Name, checker.Equals, "test")
604         c.Assert(len(nr.Containers), checker.Equals, 0)
605
606         // run another container
607         out, _ = dockerCmd(c, "run", "-d", "--net", "test", "--name", "test2", "busybox", "top")
608         c.Assert(waitRun("test2"), check.IsNil)
609         containerID = strings.TrimSpace(out)
610
611         nr = getNwResource(c, "test")
612         c.Assert(nr.Name, checker.Equals, "test")
613         c.Assert(len(nr.Containers), checker.Equals, 1)
614
615         // force disconnect the container to the test network
616         dockerCmd(c, "network", "disconnect", "-f", "test", containerID)
617
618         nr = getNwResource(c, "test")
619         c.Assert(nr.Name, checker.Equals, "test")
620         c.Assert(len(nr.Containers), checker.Equals, 0)
621
622         dockerCmd(c, "network", "rm", "test")
623         assertNwNotAvailable(c, "test")
624 }
625
626 func (s *DockerNetworkSuite) TestDockerNetworkIPAMMultipleNetworks(c *check.C) {
627         // test0 bridge network
628         dockerCmd(c, "network", "create", "--subnet=192.168.0.0/16", "test1")
629         assertNwIsAvailable(c, "test1")
630
631         // test2 bridge network does not overlap
632         dockerCmd(c, "network", "create", "--subnet=192.169.0.0/16", "test2")
633         assertNwIsAvailable(c, "test2")
634
635         // for networks w/o ipam specified, docker will choose proper non-overlapping subnets
636         dockerCmd(c, "network", "create", "test3")
637         assertNwIsAvailable(c, "test3")
638         dockerCmd(c, "network", "create", "test4")
639         assertNwIsAvailable(c, "test4")
640         dockerCmd(c, "network", "create", "test5")
641         assertNwIsAvailable(c, "test5")
642
643         // test network with multiple subnets
644         // bridge network doesn't support multiple subnets. hence, use a dummy driver that supports
645
646         dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "--subnet=192.168.0.0/16", "--subnet=192.170.0.0/16", "test6")
647         assertNwIsAvailable(c, "test6")
648
649         // test network with multiple subnets with valid ipam combinations
650         // also check same subnet across networks when the driver supports it.
651         dockerCmd(c, "network", "create", "-d", dummyNetworkDriver,
652                 "--subnet=192.168.0.0/16", "--subnet=192.170.0.0/16",
653                 "--gateway=192.168.0.100", "--gateway=192.170.0.100",
654                 "--ip-range=192.168.1.0/24",
655                 "--aux-address", "a=192.168.1.5", "--aux-address", "b=192.168.1.6",
656                 "--aux-address", "c=192.170.1.5", "--aux-address", "d=192.170.1.6",
657                 "test7")
658         assertNwIsAvailable(c, "test7")
659
660         // cleanup
661         for i := 1; i < 8; i++ {
662                 dockerCmd(c, "network", "rm", fmt.Sprintf("test%d", i))
663         }
664 }
665
666 func (s *DockerNetworkSuite) TestDockerNetworkCustomIPAM(c *check.C) {
667         // Create a bridge network using custom ipam driver
668         dockerCmd(c, "network", "create", "--ipam-driver", dummyIPAMDriver, "br0")
669         assertNwIsAvailable(c, "br0")
670
671         // Verify expected network ipam fields are there
672         nr := getNetworkResource(c, "br0")
673         c.Assert(nr.Driver, checker.Equals, "bridge")
674         c.Assert(nr.IPAM.Driver, checker.Equals, dummyIPAMDriver)
675
676         // remove network and exercise remote ipam driver
677         dockerCmd(c, "network", "rm", "br0")
678         assertNwNotAvailable(c, "br0")
679 }
680
681 func (s *DockerNetworkSuite) TestDockerNetworkIPAMOptions(c *check.C) {
682         // Create a bridge network using custom ipam driver and options
683         dockerCmd(c, "network", "create", "--ipam-driver", dummyIPAMDriver, "--ipam-opt", "opt1=drv1", "--ipam-opt", "opt2=drv2", "br0")
684         assertNwIsAvailable(c, "br0")
685
686         // Verify expected network ipam options
687         nr := getNetworkResource(c, "br0")
688         opts := nr.IPAM.Options
689         c.Assert(opts["opt1"], checker.Equals, "drv1")
690         c.Assert(opts["opt2"], checker.Equals, "drv2")
691 }
692
693 func (s *DockerNetworkSuite) TestDockerNetworkInspectDefault(c *check.C) {
694         nr := getNetworkResource(c, "none")
695         c.Assert(nr.Driver, checker.Equals, "null")
696         c.Assert(nr.Scope, checker.Equals, "local")
697         c.Assert(nr.Internal, checker.Equals, false)
698         c.Assert(nr.EnableIPv6, checker.Equals, false)
699         c.Assert(nr.IPAM.Driver, checker.Equals, "default")
700         c.Assert(len(nr.IPAM.Config), checker.Equals, 0)
701
702         nr = getNetworkResource(c, "host")
703         c.Assert(nr.Driver, checker.Equals, "host")
704         c.Assert(nr.Scope, checker.Equals, "local")
705         c.Assert(nr.Internal, checker.Equals, false)
706         c.Assert(nr.EnableIPv6, checker.Equals, false)
707         c.Assert(nr.IPAM.Driver, checker.Equals, "default")
708         c.Assert(len(nr.IPAM.Config), checker.Equals, 0)
709
710         nr = getNetworkResource(c, "bridge")
711         c.Assert(nr.Driver, checker.Equals, "bridge")
712         c.Assert(nr.Scope, checker.Equals, "local")
713         c.Assert(nr.Internal, checker.Equals, false)
714         c.Assert(nr.EnableIPv6, checker.Equals, false)
715         c.Assert(nr.IPAM.Driver, checker.Equals, "default")
716         c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
717         c.Assert(nr.IPAM.Config[0].Subnet, checker.NotNil)
718         c.Assert(nr.IPAM.Config[0].Gateway, checker.NotNil)
719 }
720
721 func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomUnspecified(c *check.C) {
722         // if unspecified, network subnet will be selected from inside preferred pool
723         dockerCmd(c, "network", "create", "test01")
724         assertNwIsAvailable(c, "test01")
725
726         nr := getNetworkResource(c, "test01")
727         c.Assert(nr.Driver, checker.Equals, "bridge")
728         c.Assert(nr.Scope, checker.Equals, "local")
729         c.Assert(nr.Internal, checker.Equals, false)
730         c.Assert(nr.EnableIPv6, checker.Equals, false)
731         c.Assert(nr.IPAM.Driver, checker.Equals, "default")
732         c.Assert(len(nr.IPAM.Config), checker.Equals, 1)
733         c.Assert(nr.IPAM.Config[0].Subnet, checker.NotNil)
734         c.Assert(nr.IPAM.Config[0].Gateway, checker.NotNil)
735
736         dockerCmd(c, "network", "rm", "test01")
737         assertNwNotAvailable(c, "test01")
738 }
739
740 func (s *DockerNetworkSuite) TestDockerNetworkInspectCustomSpecified(c *check.C) {
741         dockerCmd(c, "network", "create", "--driver=bridge", "--ipv6", "--subnet=fd80:24e2:f998:72d6::/64", "--subnet=172.28.0.0/16", "--ip-range=172.28.5.0/24", "--gateway=172.28.5.254", "br0")
742         assertNwIsAvailable(c, "br0")
743
744         nr := getNetworkResource(c, "br0")
745         c.Assert(nr.Driver, checker.Equals, "bridge")
746         c.Assert(nr.Scope, checker.Equals, "local")
747         c.Assert(nr.Internal, checker.Equals, false)
748         c.Assert(nr.EnableIPv6, checker.Equals, true)
749         c.Assert(nr.IPAM.Driver, checker.Equals, "default")
750         c.Assert(len(nr.IPAM.Config), checker.Equals, 2)
751         c.Assert(nr.IPAM.Config[0].Subnet, checker.Equals, "172.28.0.0/16")
752         c.Assert(nr.IPAM.Config[0].IPRange, checker.Equals, "172.28.5.0/24")
753         c.Assert(nr.IPAM.Config[0].Gateway, checker.Equals, "172.28.5.254")
754         c.Assert(nr.Internal, checker.False)
755         dockerCmd(c, "network", "rm", "br0")
756         assertNwNotAvailable(c, "test01")
757 }
758
759 func (s *DockerNetworkSuite) TestDockerNetworkIPAMInvalidCombinations(c *check.C) {
760         // network with ip-range out of subnet range
761         _, _, err := dockerCmdWithError("network", "create", "--subnet=192.168.0.0/16", "--ip-range=192.170.0.0/16", "test")
762         c.Assert(err, check.NotNil)
763
764         // network with multiple gateways for a single subnet
765         _, _, err = dockerCmdWithError("network", "create", "--subnet=192.168.0.0/16", "--gateway=192.168.0.1", "--gateway=192.168.0.2", "test")
766         c.Assert(err, check.NotNil)
767
768         // Multiple overlapping subnets in the same network must fail
769         _, _, err = dockerCmdWithError("network", "create", "--subnet=192.168.0.0/16", "--subnet=192.168.1.0/16", "test")
770         c.Assert(err, check.NotNil)
771
772         // overlapping subnets across networks must fail
773         // create a valid test0 network
774         dockerCmd(c, "network", "create", "--subnet=192.168.0.0/16", "test0")
775         assertNwIsAvailable(c, "test0")
776         // create an overlapping test1 network
777         _, _, err = dockerCmdWithError("network", "create", "--subnet=192.168.128.0/17", "test1")
778         c.Assert(err, check.NotNil)
779         dockerCmd(c, "network", "rm", "test0")
780         assertNwNotAvailable(c, "test0")
781 }
782
783 func (s *DockerNetworkSuite) TestDockerNetworkDriverOptions(c *check.C) {
784         dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, "-o", "opt1=drv1", "-o", "opt2=drv2", "testopt")
785         assertNwIsAvailable(c, "testopt")
786         gopts := remoteDriverNetworkRequest.Options[netlabel.GenericData]
787         c.Assert(gopts, checker.NotNil)
788         opts, ok := gopts.(map[string]interface{})
789         c.Assert(ok, checker.Equals, true)
790         c.Assert(opts["opt1"], checker.Equals, "drv1")
791         c.Assert(opts["opt2"], checker.Equals, "drv2")
792         dockerCmd(c, "network", "rm", "testopt")
793         assertNwNotAvailable(c, "testopt")
794
795 }
796
797 func (s *DockerNetworkSuite) TestDockerPluginV2NetworkDriver(c *check.C) {
798         c.Skip("Plugins aren't supported")
799
800         testRequires(c, DaemonIsLinux, IsAmd64, Network)
801
802         var (
803                 npName        = "tiborvass/test-docker-netplugin"
804                 npTag         = "latest"
805                 npNameWithTag = npName + ":" + npTag
806         )
807         _, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", npNameWithTag)
808         c.Assert(err, checker.IsNil)
809
810         out, _, err := dockerCmdWithError("plugin", "ls")
811         c.Assert(err, checker.IsNil)
812         c.Assert(out, checker.Contains, npName)
813         c.Assert(out, checker.Contains, npTag)
814         c.Assert(out, checker.Contains, "true")
815
816         dockerCmd(c, "network", "create", "-d", npNameWithTag, "v2net")
817         assertNwIsAvailable(c, "v2net")
818         dockerCmd(c, "network", "rm", "v2net")
819         assertNwNotAvailable(c, "v2net")
820
821 }
822
823 func (s *DockerDaemonSuite) TestDockerNetworkNoDiscoveryDefaultBridgeNetwork(c *check.C) {
824         testRequires(c, ExecSupport)
825         // On default bridge network built-in service discovery should not happen
826         hostsFile := "/etc/hosts"
827         bridgeName := "external-bridge"
828         bridgeIP := "192.169.255.254/24"
829         createInterface(c, "bridge", bridgeName, bridgeIP)
830         defer deleteInterface(c, bridgeName)
831
832         s.d.StartWithBusybox(c, "--bridge", bridgeName)
833         defer s.d.Restart(c)
834
835         // run two containers and store first container's etc/hosts content
836         out, err := s.d.Cmd("run", "-d", "busybox", "top")
837         c.Assert(err, check.IsNil)
838         cid1 := strings.TrimSpace(out)
839         defer s.d.Cmd("stop", cid1)
840
841         hosts, err := s.d.Cmd("exec", cid1, "cat", hostsFile)
842         c.Assert(err, checker.IsNil)
843
844         out, err = s.d.Cmd("run", "-d", "--name", "container2", "busybox", "top")
845         c.Assert(err, check.IsNil)
846         cid2 := strings.TrimSpace(out)
847
848         // verify first container's etc/hosts file has not changed after spawning the second named container
849         hostsPost, err := s.d.Cmd("exec", cid1, "cat", hostsFile)
850         c.Assert(err, checker.IsNil)
851         c.Assert(string(hosts), checker.Equals, string(hostsPost),
852                 check.Commentf("Unexpected %s change on second container creation", hostsFile))
853
854         // stop container 2 and verify first container's etc/hosts has not changed
855         _, err = s.d.Cmd("stop", cid2)
856         c.Assert(err, check.IsNil)
857
858         hostsPost, err = s.d.Cmd("exec", cid1, "cat", hostsFile)
859         c.Assert(err, checker.IsNil)
860         c.Assert(string(hosts), checker.Equals, string(hostsPost),
861                 check.Commentf("Unexpected %s change on second container creation", hostsFile))
862
863         // but discovery is on when connecting to non default bridge network
864         network := "anotherbridge"
865         out, err = s.d.Cmd("network", "create", network)
866         c.Assert(err, check.IsNil, check.Commentf(out))
867         defer s.d.Cmd("network", "rm", network)
868
869         out, err = s.d.Cmd("network", "connect", network, cid1)
870         c.Assert(err, check.IsNil, check.Commentf(out))
871
872         hosts, err = s.d.Cmd("exec", cid1, "cat", hostsFile)
873         c.Assert(err, checker.IsNil)
874
875         hostsPost, err = s.d.Cmd("exec", cid1, "cat", hostsFile)
876         c.Assert(err, checker.IsNil)
877         c.Assert(string(hosts), checker.Equals, string(hostsPost),
878                 check.Commentf("Unexpected %s change on second network connection", hostsFile))
879 }
880
881 func (s *DockerNetworkSuite) TestDockerNetworkAnonymousEndpoint(c *check.C) {
882         testRequires(c, ExecSupport, NotArm)
883         hostsFile := "/etc/hosts"
884         cstmBridgeNw := "custom-bridge-nw"
885         cstmBridgeNw1 := "custom-bridge-nw1"
886
887         dockerCmd(c, "network", "create", "-d", "bridge", cstmBridgeNw)
888         assertNwIsAvailable(c, cstmBridgeNw)
889
890         // run two anonymous containers and store their etc/hosts content
891         out, _ := dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "busybox", "top")
892         cid1 := strings.TrimSpace(out)
893
894         hosts1 := readContainerFileWithExec(c, cid1, hostsFile)
895
896         out, _ = dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "busybox", "top")
897         cid2 := strings.TrimSpace(out)
898
899         hosts2 := readContainerFileWithExec(c, cid2, hostsFile)
900
901         // verify first container etc/hosts file has not changed
902         hosts1post := readContainerFileWithExec(c, cid1, hostsFile)
903         c.Assert(string(hosts1), checker.Equals, string(hosts1post),
904                 check.Commentf("Unexpected %s change on anonymous container creation", hostsFile))
905
906         // Connect the 2nd container to a new network and verify the
907         // first container /etc/hosts file still hasn't changed.
908         dockerCmd(c, "network", "create", "-d", "bridge", cstmBridgeNw1)
909         assertNwIsAvailable(c, cstmBridgeNw1)
910
911         dockerCmd(c, "network", "connect", cstmBridgeNw1, cid2)
912
913         hosts2 = readContainerFileWithExec(c, cid2, hostsFile)
914         hosts1post = readContainerFileWithExec(c, cid1, hostsFile)
915         c.Assert(string(hosts1), checker.Equals, string(hosts1post),
916                 check.Commentf("Unexpected %s change on container connect", hostsFile))
917
918         // start a named container
919         cName := "AnyName"
920         out, _ = dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "--name", cName, "busybox", "top")
921         cid3 := strings.TrimSpace(out)
922
923         // verify that container 1 and 2 can ping the named container
924         dockerCmd(c, "exec", cid1, "ping", "-c", "1", cName)
925         dockerCmd(c, "exec", cid2, "ping", "-c", "1", cName)
926
927         // Stop named container and verify first two containers' etc/hosts file hasn't changed
928         dockerCmd(c, "stop", cid3)
929         hosts1post = readContainerFileWithExec(c, cid1, hostsFile)
930         c.Assert(string(hosts1), checker.Equals, string(hosts1post),
931                 check.Commentf("Unexpected %s change on name container creation", hostsFile))
932
933         hosts2post := readContainerFileWithExec(c, cid2, hostsFile)
934         c.Assert(string(hosts2), checker.Equals, string(hosts2post),
935                 check.Commentf("Unexpected %s change on name container creation", hostsFile))
936
937         // verify that container 1 and 2 can't ping the named container now
938         _, _, err := dockerCmdWithError("exec", cid1, "ping", "-c", "1", cName)
939         c.Assert(err, check.NotNil)
940         _, _, err = dockerCmdWithError("exec", cid2, "ping", "-c", "1", cName)
941         c.Assert(err, check.NotNil)
942 }
943
944 func (s *DockerNetworkSuite) TestDockerNetworkLinkOnDefaultNetworkOnly(c *check.C) {
945         // Legacy Link feature must work only on default network, and not across networks
946         cnt1 := "container1"
947         cnt2 := "container2"
948         network := "anotherbridge"
949
950         // Run first container on default network
951         dockerCmd(c, "run", "-d", "--name", cnt1, "busybox", "top")
952
953         // Create another network and run the second container on it
954         dockerCmd(c, "network", "create", network)
955         assertNwIsAvailable(c, network)
956         dockerCmd(c, "run", "-d", "--net", network, "--name", cnt2, "busybox", "top")
957
958         // Try launching a container on default network, linking to the first container. Must succeed
959         dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt1, cnt1), "busybox", "top")
960
961         // Try launching a container on default network, linking to the second container. Must fail
962         _, _, err := dockerCmdWithError("run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top")
963         c.Assert(err, checker.NotNil)
964
965         // Connect second container to default network. Now a container on default network can link to it
966         dockerCmd(c, "network", "connect", "bridge", cnt2)
967         dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top")
968 }
969
970 func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) {
971         // Verify exposed ports are present in ps output when running a container on
972         // a network managed by a driver which does not provide the default gateway
973         // for the container
974         nwn := "ov"
975         ctn := "bb"
976         port1 := 80
977         port2 := 443
978         expose1 := fmt.Sprintf("--expose=%d", port1)
979         expose2 := fmt.Sprintf("--expose=%d", port2)
980
981         dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn)
982         assertNwIsAvailable(c, nwn)
983
984         dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, expose1, expose2, "busybox", "top")
985
986         // Check docker ps o/p for last created container reports the unpublished ports
987         unpPort1 := fmt.Sprintf("%d/tcp", port1)
988         unpPort2 := fmt.Sprintf("%d/tcp", port2)
989         out, _ := dockerCmd(c, "ps", "-n=1")
990         // Missing unpublished ports in docker ps output
991         c.Assert(out, checker.Contains, unpPort1)
992         // Missing unpublished ports in docker ps output
993         c.Assert(out, checker.Contains, unpPort2)
994 }
995
996 func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C) {
997         testRequires(c, DaemonIsLinux, NotUserNamespace)
998         dnd := "dnd"
999         did := "did"
1000
1001         mux := http.NewServeMux()
1002         server := httptest.NewServer(mux)
1003         setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did)
1004
1005         s.d.StartWithBusybox(c)
1006         _, err := s.d.Cmd("network", "create", "-d", dnd, "--subnet", "1.1.1.0/24", "net1")
1007         c.Assert(err, checker.IsNil)
1008
1009         _, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "foo", "--ip", "1.1.1.10", "busybox", "sh")
1010         c.Assert(err, checker.IsNil)
1011
1012         // Kill daemon and restart
1013         c.Assert(s.d.Kill(), checker.IsNil)
1014
1015         server.Close()
1016
1017         startTime := time.Now().Unix()
1018         s.d.Restart(c)
1019         lapse := time.Now().Unix() - startTime
1020         if lapse > 60 {
1021                 // In normal scenarios, daemon restart takes ~1 second.
1022                 // Plugin retry mechanism can delay the daemon start. systemd may not like it.
1023                 // Avoid accessing plugins during daemon bootup
1024                 c.Logf("daemon restart took too long : %d seconds", lapse)
1025         }
1026
1027         // Restart the custom dummy plugin
1028         mux = http.NewServeMux()
1029         server = httptest.NewServer(mux)
1030         setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did)
1031
1032         // trying to reuse the same ip must succeed
1033         _, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "bar", "--ip", "1.1.1.10", "busybox", "sh")
1034         c.Assert(err, checker.IsNil)
1035 }
1036
1037 func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) {
1038         // Verify endpoint MAC address is correctly populated in container's network settings
1039         nwn := "ov"
1040         ctn := "bb"
1041
1042         dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn)
1043         assertNwIsAvailable(c, nwn)
1044
1045         dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, "busybox", "top")
1046
1047         mac := inspectField(c, ctn, "NetworkSettings.Networks."+nwn+".MacAddress")
1048         c.Assert(mac, checker.Equals, "a0:b1:c2:d3:e4:f5")
1049 }
1050
1051 func (s *DockerSuite) TestInspectAPIMultipleNetworks(c *check.C) {
1052         dockerCmd(c, "network", "create", "mybridge1")
1053         dockerCmd(c, "network", "create", "mybridge2")
1054         out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
1055         id := strings.TrimSpace(out)
1056         c.Assert(waitRun(id), check.IsNil)
1057
1058         dockerCmd(c, "network", "connect", "mybridge1", id)
1059         dockerCmd(c, "network", "connect", "mybridge2", id)
1060
1061         body := getInspectBody(c, "v1.20", id)
1062         var inspect120 v1p20.ContainerJSON
1063         err := json.Unmarshal(body, &inspect120)
1064         c.Assert(err, checker.IsNil)
1065
1066         versionedIP := inspect120.NetworkSettings.IPAddress
1067
1068         body = getInspectBody(c, "v1.21", id)
1069         var inspect121 types.ContainerJSON
1070         err = json.Unmarshal(body, &inspect121)
1071         c.Assert(err, checker.IsNil)
1072         c.Assert(inspect121.NetworkSettings.Networks, checker.HasLen, 3)
1073
1074         bridge := inspect121.NetworkSettings.Networks["bridge"]
1075         c.Assert(bridge.IPAddress, checker.Equals, versionedIP)
1076         c.Assert(bridge.IPAddress, checker.Equals, inspect121.NetworkSettings.IPAddress)
1077 }
1078
1079 func connectContainerToNetworks(c *check.C, d *daemon.Daemon, cName string, nws []string) {
1080         // Run a container on the default network
1081         out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
1082         c.Assert(err, checker.IsNil, check.Commentf(out))
1083
1084         // Attach the container to other networks
1085         for _, nw := range nws {
1086                 out, err = d.Cmd("network", "create", nw)
1087                 c.Assert(err, checker.IsNil, check.Commentf(out))
1088                 out, err = d.Cmd("network", "connect", nw, cName)
1089                 c.Assert(err, checker.IsNil, check.Commentf(out))
1090         }
1091 }
1092
1093 func verifyContainerIsConnectedToNetworks(c *check.C, d *daemon.Daemon, cName string, nws []string) {
1094         // Verify container is connected to all the networks
1095         for _, nw := range nws {
1096                 out, err := d.Cmd("inspect", "-f", fmt.Sprintf("{{.NetworkSettings.Networks.%s}}", nw), cName)
1097                 c.Assert(err, checker.IsNil, check.Commentf(out))
1098                 c.Assert(out, checker.Not(checker.Equals), "<no value>\n")
1099         }
1100 }
1101
1102 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRestart(c *check.C) {
1103         cName := "bb"
1104         nwList := []string{"nw1", "nw2", "nw3"}
1105
1106         s.d.StartWithBusybox(c)
1107
1108         connectContainerToNetworks(c, s.d, cName, nwList)
1109         verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
1110
1111         // Reload daemon
1112         s.d.Restart(c)
1113
1114         _, err := s.d.Cmd("start", cName)
1115         c.Assert(err, checker.IsNil)
1116
1117         verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
1118 }
1119
1120 func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *check.C) {
1121         cName := "cc"
1122         nwList := []string{"nw1", "nw2", "nw3"}
1123
1124         s.d.StartWithBusybox(c)
1125
1126         connectContainerToNetworks(c, s.d, cName, nwList)
1127         verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
1128
1129         // Kill daemon and restart
1130         c.Assert(s.d.Kill(), checker.IsNil)
1131         s.d.Restart(c)
1132
1133         // Restart container
1134         _, err := s.d.Cmd("start", cName)
1135         c.Assert(err, checker.IsNil)
1136
1137         verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
1138 }
1139
1140 func (s *DockerNetworkSuite) TestDockerNetworkRunNetByID(c *check.C) {
1141         out, _ := dockerCmd(c, "network", "create", "one")
1142         containerOut, _, err := dockerCmdWithError("run", "-d", "--net", strings.TrimSpace(out), "busybox", "top")
1143         c.Assert(err, checker.IsNil, check.Commentf(containerOut))
1144 }
1145
1146 func (s *DockerNetworkSuite) TestDockerNetworkHostModeUngracefulDaemonRestart(c *check.C) {
1147         testRequires(c, DaemonIsLinux, NotUserNamespace)
1148         s.d.StartWithBusybox(c)
1149
1150         // Run a few containers on host network
1151         for i := 0; i < 10; i++ {
1152                 cName := fmt.Sprintf("hostc-%d", i)
1153                 out, err := s.d.Cmd("run", "-d", "--name", cName, "--net=host", "--restart=always", "busybox", "top")
1154                 c.Assert(err, checker.IsNil, check.Commentf(out))
1155
1156                 // verfiy container has finished starting before killing daemon
1157                 err = s.d.WaitRun(cName)
1158                 c.Assert(err, checker.IsNil)
1159         }
1160
1161         // Kill daemon ungracefully and restart
1162         c.Assert(s.d.Kill(), checker.IsNil)
1163         s.d.Restart(c)
1164
1165         // make sure all the containers are up and running
1166         for i := 0; i < 10; i++ {
1167                 err := s.d.WaitRun(fmt.Sprintf("hostc-%d", i))
1168                 c.Assert(err, checker.IsNil)
1169         }
1170 }
1171
1172 func (s *DockerNetworkSuite) TestDockerNetworkConnectToHostFromOtherNetwork(c *check.C) {
1173         dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
1174         c.Assert(waitRun("container1"), check.IsNil)
1175         dockerCmd(c, "network", "disconnect", "bridge", "container1")
1176         out, _, err := dockerCmdWithError("network", "connect", "host", "container1")
1177         c.Assert(err, checker.NotNil, check.Commentf(out))
1178         c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error())
1179 }
1180
1181 func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromHost(c *check.C) {
1182         dockerCmd(c, "run", "-d", "--name", "container1", "--net=host", "busybox", "top")
1183         c.Assert(waitRun("container1"), check.IsNil)
1184         out, _, err := dockerCmdWithError("network", "disconnect", "host", "container1")
1185         c.Assert(err, checker.NotNil, check.Commentf("Should err out disconnect from host"))
1186         c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error())
1187 }
1188
1189 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C) {
1190         testRequires(c, NotArm)
1191         dockerCmd(c, "network", "create", "test1")
1192         dockerCmd(c, "run", "-d", "--name", "c1", "-p", "5000:5000", "busybox", "top")
1193         c.Assert(waitRun("c1"), check.IsNil)
1194         dockerCmd(c, "network", "connect", "test1", "c1")
1195 }
1196
1197 func verifyPortMap(c *check.C, container, port, originalMapping string, mustBeEqual bool) {
1198         chk := checker.Equals
1199         if !mustBeEqual {
1200                 chk = checker.Not(checker.Equals)
1201         }
1202         currentMapping, _ := dockerCmd(c, "port", container, port)
1203         c.Assert(currentMapping, chk, originalMapping)
1204 }
1205
1206 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectWithPortMapping(c *check.C) {
1207         // Connect and disconnect a container with explicit and non-explicit
1208         // host port mapping to/from networks which do cause and do not cause
1209         // the container default gateway to change, and verify docker port cmd
1210         // returns congruent information
1211         testRequires(c, NotArm)
1212         cnt := "c1"
1213         dockerCmd(c, "network", "create", "aaa")
1214         dockerCmd(c, "network", "create", "ccc")
1215
1216         dockerCmd(c, "run", "-d", "--name", cnt, "-p", "9000:90", "-p", "70", "busybox", "top")
1217         c.Assert(waitRun(cnt), check.IsNil)
1218         curPortMap, _ := dockerCmd(c, "port", cnt, "70")
1219         curExplPortMap, _ := dockerCmd(c, "port", cnt, "90")
1220
1221         // Connect to a network which causes the container's default gw switch
1222         dockerCmd(c, "network", "connect", "aaa", cnt)
1223         verifyPortMap(c, cnt, "70", curPortMap, false)
1224         verifyPortMap(c, cnt, "90", curExplPortMap, true)
1225
1226         // Read current mapping
1227         curPortMap, _ = dockerCmd(c, "port", cnt, "70")
1228
1229         // Disconnect from a network which causes the container's default gw switch
1230         dockerCmd(c, "network", "disconnect", "aaa", cnt)
1231         verifyPortMap(c, cnt, "70", curPortMap, false)
1232         verifyPortMap(c, cnt, "90", curExplPortMap, true)
1233
1234         // Read current mapping
1235         curPortMap, _ = dockerCmd(c, "port", cnt, "70")
1236
1237         // Connect to a network which does not cause the container's default gw switch
1238         dockerCmd(c, "network", "connect", "ccc", cnt)
1239         verifyPortMap(c, cnt, "70", curPortMap, true)
1240         verifyPortMap(c, cnt, "90", curExplPortMap, true)
1241 }
1242
1243 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) {
1244         macAddress := "02:42:ac:11:00:02"
1245         dockerCmd(c, "network", "create", "mynetwork")
1246         dockerCmd(c, "run", "--name=test", "-d", "--mac-address", macAddress, "busybox", "top")
1247         c.Assert(waitRun("test"), check.IsNil)
1248         mac1 := inspectField(c, "test", "NetworkSettings.Networks.bridge.MacAddress")
1249         c.Assert(strings.TrimSpace(mac1), checker.Equals, macAddress)
1250         dockerCmd(c, "network", "connect", "mynetwork", "test")
1251         mac2 := inspectField(c, "test", "NetworkSettings.Networks.mynetwork.MacAddress")
1252         c.Assert(strings.TrimSpace(mac2), checker.Not(checker.Equals), strings.TrimSpace(mac1))
1253 }
1254
1255 func (s *DockerNetworkSuite) TestDockerNetworkInspectCreatedContainer(c *check.C) {
1256         dockerCmd(c, "create", "--name", "test", "busybox")
1257         networks := inspectField(c, "test", "NetworkSettings.Networks")
1258         c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should return 'bridge' network"))
1259 }
1260
1261 func (s *DockerNetworkSuite) TestDockerNetworkRestartWithMultipleNetworks(c *check.C) {
1262         dockerCmd(c, "network", "create", "test")
1263         dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top")
1264         c.Assert(waitRun("foo"), checker.IsNil)
1265         dockerCmd(c, "network", "connect", "test", "foo")
1266         dockerCmd(c, "restart", "foo")
1267         networks := inspectField(c, "foo", "NetworkSettings.Networks")
1268         c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should contain 'bridge' network"))
1269         c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
1270 }
1271
1272 func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContainer(c *check.C) {
1273         dockerCmd(c, "network", "create", "test")
1274         dockerCmd(c, "create", "--name=foo", "busybox", "top")
1275         dockerCmd(c, "network", "connect", "test", "foo")
1276         networks := inspectField(c, "foo", "NetworkSettings.Networks")
1277         c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
1278
1279         // Restart docker daemon to test the config has persisted to disk
1280         s.d.Restart(c)
1281         networks = inspectField(c, "foo", "NetworkSettings.Networks")
1282         c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
1283
1284         // start the container and test if we can ping it from another container in the same network
1285         dockerCmd(c, "start", "foo")
1286         c.Assert(waitRun("foo"), checker.IsNil)
1287         ip := inspectField(c, "foo", "NetworkSettings.Networks.test.IPAddress")
1288         ip = strings.TrimSpace(ip)
1289         dockerCmd(c, "run", "--net=test", "busybox", "sh", "-c", fmt.Sprintf("ping -c 1 %s", ip))
1290
1291         dockerCmd(c, "stop", "foo")
1292
1293         // Test disconnect
1294         dockerCmd(c, "network", "disconnect", "test", "foo")
1295         networks = inspectField(c, "foo", "NetworkSettings.Networks")
1296         c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
1297
1298         // Restart docker daemon to test the config has persisted to disk
1299         s.d.Restart(c)
1300         networks = inspectField(c, "foo", "NetworkSettings.Networks")
1301         c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
1302
1303 }
1304
1305 func (s *DockerNetworkSuite) TestDockerNetworkDisconnectContainerNonexistingNetwork(c *check.C) {
1306         dockerCmd(c, "network", "create", "test")
1307         dockerCmd(c, "run", "--net=test", "-d", "--name=foo", "busybox", "top")
1308         networks := inspectField(c, "foo", "NetworkSettings.Networks")
1309         c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
1310
1311         // Stop container and remove network
1312         dockerCmd(c, "stop", "foo")
1313         dockerCmd(c, "network", "rm", "test")
1314
1315         // Test disconnecting stopped container from nonexisting network
1316         dockerCmd(c, "network", "disconnect", "-f", "test", "foo")
1317         networks = inspectField(c, "foo", "NetworkSettings.Networks")
1318         c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
1319 }
1320
1321 func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) {
1322         // create two networks
1323         dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0")
1324         assertNwIsAvailable(c, "n0")
1325
1326         dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--ip-range=172.30.5.0/24", "--subnet=2001:db8:abcd::/64", "--ip-range=2001:db8:abcd::/80", "n1")
1327         assertNwIsAvailable(c, "n1")
1328
1329         // run a container on first network specifying the ip addresses
1330         dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
1331         c.Assert(waitRun("c0"), check.IsNil)
1332         verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
1333         verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
1334
1335         // connect the container to the second network specifying an ip addresses
1336         dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n1", "c0")
1337         verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
1338         verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
1339
1340         // Stop and restart the container
1341         dockerCmd(c, "stop", "c0")
1342         dockerCmd(c, "start", "c0")
1343
1344         // verify requested addresses are applied and configs are still there
1345         verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
1346         verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
1347         verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
1348         verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
1349
1350         // Still it should fail to connect to the default network with a specified IP (whatever ip)
1351         out, _, err := dockerCmdWithError("network", "connect", "--ip", "172.21.55.44", "bridge", "c0")
1352         c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
1353         c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error())
1354
1355 }
1356
1357 func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIPStoppedContainer(c *check.C) {
1358         // create a container
1359         dockerCmd(c, "create", "--name", "c0", "busybox", "top")
1360
1361         // create a network
1362         dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0")
1363         assertNwIsAvailable(c, "n0")
1364
1365         // connect the container to the network specifying an ip addresses
1366         dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n0", "c0")
1367         verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
1368
1369         // start the container, verify config has not changed and ip addresses are assigned
1370         dockerCmd(c, "start", "c0")
1371         c.Assert(waitRun("c0"), check.IsNil)
1372         verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
1373         verifyIPAddresses(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
1374
1375         // stop the container and check ip config has not changed
1376         dockerCmd(c, "stop", "c0")
1377         verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
1378 }
1379
1380 func (s *DockerNetworkSuite) TestDockerNetworkUnsupportedRequiredIP(c *check.C) {
1381         // requested IP is not supported on predefined networks
1382         for _, mode := range []string{"none", "host", "bridge", "default"} {
1383                 checkUnsupportedNetworkAndIP(c, mode)
1384         }
1385
1386         // requested IP is not supported on networks with no user defined subnets
1387         dockerCmd(c, "network", "create", "n0")
1388         assertNwIsAvailable(c, "n0")
1389
1390         out, _, err := dockerCmdWithError("run", "-d", "--ip", "172.28.99.88", "--net", "n0", "busybox", "top")
1391         c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
1392         c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error())
1393
1394         out, _, err = dockerCmdWithError("run", "-d", "--ip6", "2001:db8:1234::9988", "--net", "n0", "busybox", "top")
1395         c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
1396         c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error())
1397
1398         dockerCmd(c, "network", "rm", "n0")
1399         assertNwNotAvailable(c, "n0")
1400 }
1401
1402 func checkUnsupportedNetworkAndIP(c *check.C, nwMode string) {
1403         out, _, err := dockerCmdWithError("run", "-d", "--net", nwMode, "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
1404         c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
1405         c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error())
1406 }
1407
1408 func verifyIPAddressConfig(c *check.C, cName, nwname, ipv4, ipv6 string) {
1409         if ipv4 != "" {
1410                 out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv4Address", nwname))
1411                 c.Assert(strings.TrimSpace(out), check.Equals, ipv4)
1412         }
1413
1414         if ipv6 != "" {
1415                 out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv6Address", nwname))
1416                 c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
1417         }
1418 }
1419
1420 func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) {
1421         out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAddress", nwname))
1422         c.Assert(strings.TrimSpace(out), check.Equals, ipv4)
1423
1424         out = inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.GlobalIPv6Address", nwname))
1425         c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
1426 }
1427
1428 func (s *DockerNetworkSuite) TestDockerNetworkConnectLinkLocalIP(c *check.C) {
1429         // create one test network
1430         dockerCmd(c, "network", "create", "--ipv6", "--subnet=2001:db8:1234::/64", "n0")
1431         assertNwIsAvailable(c, "n0")
1432
1433         // run a container with incorrect link-local address
1434         _, _, err := dockerCmdWithError("run", "--link-local-ip", "169.253.5.5", "busybox", "top")
1435         c.Assert(err, check.NotNil)
1436         _, _, err = dockerCmdWithError("run", "--link-local-ip", "2001:db8::89", "busybox", "top")
1437         c.Assert(err, check.NotNil)
1438
1439         // run two containers with link-local ip on the test network
1440         dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--link-local-ip", "169.254.7.7", "--link-local-ip", "fe80::254:77", "busybox", "top")
1441         c.Assert(waitRun("c0"), check.IsNil)
1442         dockerCmd(c, "run", "-d", "--name", "c1", "--net=n0", "--link-local-ip", "169.254.8.8", "--link-local-ip", "fe80::254:88", "busybox", "top")
1443         c.Assert(waitRun("c1"), check.IsNil)
1444
1445         // run a container on the default network and connect it to the test network specifying a link-local address
1446         dockerCmd(c, "run", "-d", "--name", "c2", "busybox", "top")
1447         c.Assert(waitRun("c2"), check.IsNil)
1448         dockerCmd(c, "network", "connect", "--link-local-ip", "169.254.9.9", "n0", "c2")
1449
1450         // verify the three containers can ping each other via the link-local addresses
1451         _, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
1452         c.Assert(err, check.IsNil)
1453         _, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
1454         c.Assert(err, check.IsNil)
1455         _, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
1456         c.Assert(err, check.IsNil)
1457
1458         // Stop and restart the three containers
1459         dockerCmd(c, "stop", "c0")
1460         dockerCmd(c, "stop", "c1")
1461         dockerCmd(c, "stop", "c2")
1462         dockerCmd(c, "start", "c0")
1463         dockerCmd(c, "start", "c1")
1464         dockerCmd(c, "start", "c2")
1465
1466         // verify the ping again
1467         _, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
1468         c.Assert(err, check.IsNil)
1469         _, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
1470         c.Assert(err, check.IsNil)
1471         _, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
1472         c.Assert(err, check.IsNil)
1473 }
1474
1475 func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
1476         testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
1477         dockerCmd(c, "network", "create", "-d", "bridge", "foo1")
1478         dockerCmd(c, "network", "create", "-d", "bridge", "foo2")
1479
1480         dockerCmd(c, "run", "-d", "--net=foo1", "--name=first", "busybox", "top")
1481         c.Assert(waitRun("first"), check.IsNil)
1482
1483         // run a container in a user-defined network with a link for an existing container
1484         // and a link for a container that doesn't exist
1485         dockerCmd(c, "run", "-d", "--net=foo1", "--name=second", "--link=first:FirstInFoo1",
1486                 "--link=third:bar", "busybox", "top")
1487         c.Assert(waitRun("second"), check.IsNil)
1488
1489         // ping to first and its alias FirstInFoo1 must succeed
1490         _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
1491         c.Assert(err, check.IsNil)
1492         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
1493         c.Assert(err, check.IsNil)
1494
1495         // connect first container to foo2 network
1496         dockerCmd(c, "network", "connect", "foo2", "first")
1497         // connect second container to foo2 network with a different alias for first container
1498         dockerCmd(c, "network", "connect", "--link=first:FirstInFoo2", "foo2", "second")
1499
1500         // ping the new alias in network foo2
1501         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
1502         c.Assert(err, check.IsNil)
1503
1504         // disconnect first container from foo1 network
1505         dockerCmd(c, "network", "disconnect", "foo1", "first")
1506
1507         // link in foo1 network must fail
1508         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
1509         c.Assert(err, check.NotNil)
1510
1511         // link in foo2 network must succeed
1512         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
1513         c.Assert(err, check.IsNil)
1514 }
1515
1516 func (s *DockerNetworkSuite) TestDockerNetworkDisconnectDefault(c *check.C) {
1517         netWorkName1 := "test1"
1518         netWorkName2 := "test2"
1519         containerName := "foo"
1520
1521         dockerCmd(c, "network", "create", netWorkName1)
1522         dockerCmd(c, "network", "create", netWorkName2)
1523         dockerCmd(c, "create", "--name", containerName, "busybox", "top")
1524         dockerCmd(c, "network", "connect", netWorkName1, containerName)
1525         dockerCmd(c, "network", "connect", netWorkName2, containerName)
1526         dockerCmd(c, "network", "disconnect", "bridge", containerName)
1527
1528         dockerCmd(c, "start", containerName)
1529         c.Assert(waitRun(containerName), checker.IsNil)
1530         networks := inspectField(c, containerName, "NetworkSettings.Networks")
1531         c.Assert(networks, checker.Contains, netWorkName1, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName1)))
1532         c.Assert(networks, checker.Contains, netWorkName2, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName2)))
1533         c.Assert(networks, checker.Not(checker.Contains), "bridge", check.Commentf("Should not contain 'bridge' network"))
1534 }
1535
1536 func (s *DockerNetworkSuite) TestDockerNetworkConnectWithAliasOnDefaultNetworks(c *check.C) {
1537         testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
1538
1539         defaults := []string{"bridge", "host", "none"}
1540         out, _ := dockerCmd(c, "run", "-d", "--net=none", "busybox", "top")
1541         containerID := strings.TrimSpace(out)
1542         for _, net := range defaults {
1543                 res, _, err := dockerCmdWithError("network", "connect", "--alias", "alias"+net, net, containerID)
1544                 c.Assert(err, checker.NotNil)
1545                 c.Assert(res, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
1546         }
1547 }
1548
1549 func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectAlias(c *check.C) {
1550         testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
1551         dockerCmd(c, "network", "create", "-d", "bridge", "net1")
1552         dockerCmd(c, "network", "create", "-d", "bridge", "net2")
1553
1554         cid, _ := dockerCmd(c, "run", "-d", "--net=net1", "--name=first", "--net-alias=foo", "busybox", "top")
1555         c.Assert(waitRun("first"), check.IsNil)
1556
1557         dockerCmd(c, "run", "-d", "--net=net1", "--name=second", "busybox", "top")
1558         c.Assert(waitRun("second"), check.IsNil)
1559
1560         // ping first container and its alias
1561         _, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
1562         c.Assert(err, check.IsNil)
1563         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
1564         c.Assert(err, check.IsNil)
1565
1566         // ping first container's short-id alias
1567         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid))
1568         c.Assert(err, check.IsNil)
1569
1570         // connect first container to net2 network
1571         dockerCmd(c, "network", "connect", "--alias=bar", "net2", "first")
1572         // connect second container to foo2 network with a different alias for first container
1573         dockerCmd(c, "network", "connect", "net2", "second")
1574
1575         // ping the new alias in network foo2
1576         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
1577         c.Assert(err, check.IsNil)
1578
1579         // disconnect first container from net1 network
1580         dockerCmd(c, "network", "disconnect", "net1", "first")
1581
1582         // ping to net1 scoped alias "foo" must fail
1583         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
1584         c.Assert(err, check.NotNil)
1585
1586         // ping to net2 scoped alias "bar" must still succeed
1587         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
1588         c.Assert(err, check.IsNil)
1589         // ping to net2 scoped alias short-id must still succeed
1590         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid))
1591         c.Assert(err, check.IsNil)
1592
1593         // verify the alias option is rejected when running on predefined network
1594         out, _, err := dockerCmdWithError("run", "--rm", "--name=any", "--net-alias=any", "busybox", "top")
1595         c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
1596         c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
1597
1598         // verify the alias option is rejected when connecting to predefined network
1599         out, _, err = dockerCmdWithError("network", "connect", "--alias=any", "bridge", "first")
1600         c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
1601         c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
1602 }
1603
1604 func (s *DockerSuite) TestUserDefinedNetworkConnectivity(c *check.C) {
1605         testRequires(c, DaemonIsLinux, NotUserNamespace)
1606         dockerCmd(c, "network", "create", "-d", "bridge", "br.net1")
1607
1608         dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c1.net1", "busybox", "top")
1609         c.Assert(waitRun("c1.net1"), check.IsNil)
1610
1611         dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c2.net1", "busybox", "top")
1612         c.Assert(waitRun("c2.net1"), check.IsNil)
1613
1614         // ping first container by its unqualified name
1615         _, _, err := dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1")
1616         c.Assert(err, check.IsNil)
1617
1618         // ping first container by its qualified name
1619         _, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1")
1620         c.Assert(err, check.IsNil)
1621
1622         // ping with first qualified name masked by an additional domain. should fail
1623         _, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1.google.com")
1624         c.Assert(err, check.NotNil)
1625 }
1626
1627 func (s *DockerSuite) TestEmbeddedDNSInvalidInput(c *check.C) {
1628         testRequires(c, DaemonIsLinux, NotUserNamespace)
1629         dockerCmd(c, "network", "create", "-d", "bridge", "nw1")
1630
1631         // Sending garbage to embedded DNS shouldn't crash the daemon
1632         dockerCmd(c, "run", "-i", "--net=nw1", "--name=c1", "debian:jessie", "bash", "-c", "echo InvalidQuery > /dev/udp/127.0.0.11/53")
1633 }
1634
1635 func (s *DockerSuite) TestDockerNetworkConnectFailsNoInspectChange(c *check.C) {
1636         dockerCmd(c, "run", "-d", "--name=bb", "busybox", "top")
1637         c.Assert(waitRun("bb"), check.IsNil)
1638
1639         ns0 := inspectField(c, "bb", "NetworkSettings.Networks.bridge")
1640
1641         // A failing redundant network connect should not alter current container's endpoint settings
1642         _, _, err := dockerCmdWithError("network", "connect", "bridge", "bb")
1643         c.Assert(err, check.NotNil)
1644
1645         ns1 := inspectField(c, "bb", "NetworkSettings.Networks.bridge")
1646         c.Assert(ns1, check.Equals, ns0)
1647 }
1648
1649 func (s *DockerSuite) TestDockerNetworkInternalMode(c *check.C) {
1650         dockerCmd(c, "network", "create", "--driver=bridge", "--internal", "internal")
1651         assertNwIsAvailable(c, "internal")
1652         nr := getNetworkResource(c, "internal")
1653         c.Assert(nr.Internal, checker.True)
1654
1655         dockerCmd(c, "run", "-d", "--net=internal", "--name=first", "busybox", "top")
1656         c.Assert(waitRun("first"), check.IsNil)
1657         dockerCmd(c, "run", "-d", "--net=internal", "--name=second", "busybox", "top")
1658         c.Assert(waitRun("second"), check.IsNil)
1659         out, _, err := dockerCmdWithError("exec", "first", "ping", "-W", "4", "-c", "1", "www.google.com")
1660         c.Assert(err, check.NotNil)
1661         c.Assert(out, checker.Contains, "ping: bad address")
1662         _, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
1663         c.Assert(err, check.IsNil)
1664 }
1665
1666 // Test for #21401
1667 func (s *DockerNetworkSuite) TestDockerNetworkCreateDeleteSpecialCharacters(c *check.C) {
1668         dockerCmd(c, "network", "create", "test@#$")
1669         assertNwIsAvailable(c, "test@#$")
1670         dockerCmd(c, "network", "rm", "test@#$")
1671         assertNwNotAvailable(c, "test@#$")
1672
1673         dockerCmd(c, "network", "create", "kiwl$%^")
1674         assertNwIsAvailable(c, "kiwl$%^")
1675         dockerCmd(c, "network", "rm", "kiwl$%^")
1676         assertNwNotAvailable(c, "kiwl$%^")
1677 }
1678
1679 func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *check.C) {
1680         testRequires(t, DaemonIsLinux)
1681         s.d.StartWithBusybox(t, "--live-restore")
1682         defer s.d.Stop(t)
1683         oldCon := "old"
1684
1685         _, err := s.d.Cmd("run", "-d", "--name", oldCon, "-p", "80:80", "busybox", "top")
1686         if err != nil {
1687                 t.Fatal(err)
1688         }
1689         oldContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", oldCon)
1690         if err != nil {
1691                 t.Fatal(err)
1692         }
1693         // Kill the daemon
1694         if err := s.d.Kill(); err != nil {
1695                 t.Fatal(err)
1696         }
1697
1698         // restart the daemon
1699         s.d.Start(t, "--live-restore")
1700
1701         // start a new container, the new container's ip should not be the same with
1702         // old running container.
1703         newCon := "new"
1704         _, err = s.d.Cmd("run", "-d", "--name", newCon, "busybox", "top")
1705         if err != nil {
1706                 t.Fatal(err)
1707         }
1708         newContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", newCon)
1709         if err != nil {
1710                 t.Fatal(err)
1711         }
1712         if strings.Compare(strings.TrimSpace(oldContainerIP), strings.TrimSpace(newContainerIP)) == 0 {
1713                 t.Fatalf("new container ip should not equal to old running container  ip")
1714         }
1715
1716         // start a new container, the new container should ping old running container
1717         _, err = s.d.Cmd("run", "-t", "busybox", "ping", "-c", "1", oldContainerIP)
1718         if err != nil {
1719                 t.Fatal(err)
1720         }
1721
1722         // start a new container, trying to publish port 80:80 should fail
1723         out, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
1724         if err == nil || !strings.Contains(out, "Bind for 0.0.0.0:80 failed: port is already allocated") {
1725                 t.Fatalf("80 port is allocated to old running container, it should failed on allocating to new container")
1726         }
1727
1728         // kill old running container and try to allocate again
1729         _, err = s.d.Cmd("kill", oldCon)
1730         if err != nil {
1731                 t.Fatal(err)
1732         }
1733         id, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
1734         if err != nil {
1735                 t.Fatal(err)
1736         }
1737
1738         // Cleanup because these containers will not be shut down by daemon
1739         out, err = s.d.Cmd("stop", newCon)
1740         if err != nil {
1741                 t.Fatalf("err: %v %v", err, string(out))
1742         }
1743         _, err = s.d.Cmd("stop", strings.TrimSpace(id))
1744         if err != nil {
1745                 t.Fatal(err)
1746         }
1747 }
1748
1749 func (s *DockerNetworkSuite) TestDockerNetworkFlagAlias(c *check.C) {
1750         dockerCmd(c, "network", "create", "user")
1751         output, status := dockerCmd(c, "run", "--rm", "--network=user", "--network-alias=foo", "busybox", "true")
1752         c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
1753
1754         output, status, _ = dockerCmdWithError("run", "--rm", "--net=user", "--network=user", "busybox", "true")
1755         c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
1756
1757         output, status, _ = dockerCmdWithError("run", "--rm", "--network=user", "--net-alias=foo", "--network-alias=bar", "busybox", "true")
1758         c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
1759 }
1760
1761 func (s *DockerNetworkSuite) TestDockerNetworkValidateIP(c *check.C) {
1762         _, _, err := dockerCmdWithError("network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "mynet")
1763         c.Assert(err, check.IsNil)
1764         assertNwIsAvailable(c, "mynet")
1765
1766         _, _, err = dockerCmdWithError("run", "-d", "--name", "mynet0", "--net=mynet", "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
1767         c.Assert(err, check.IsNil)
1768         c.Assert(waitRun("mynet0"), check.IsNil)
1769         verifyIPAddressConfig(c, "mynet0", "mynet", "172.28.99.88", "2001:db8:1234::9988")
1770         verifyIPAddresses(c, "mynet0", "mynet", "172.28.99.88", "2001:db8:1234::9988")
1771
1772         _, _, err = dockerCmdWithError("run", "--net=mynet", "--ip", "mynet_ip", "--ip6", "2001:db8:1234::9999", "busybox", "top")
1773         c.Assert(err.Error(), checker.Contains, "invalid IPv4 address")
1774         _, _, err = dockerCmdWithError("run", "--net=mynet", "--ip", "172.28.99.99", "--ip6", "mynet_ip6", "busybox", "top")
1775         c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
1776         // This is a case of IPv4 address to `--ip6`
1777         _, _, err = dockerCmdWithError("run", "--net=mynet", "--ip6", "172.28.99.99", "busybox", "top")
1778         c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
1779         // This is a special case of an IPv4-mapped IPv6 address
1780         _, _, err = dockerCmdWithError("run", "--net=mynet", "--ip6", "::ffff:172.28.99.99", "busybox", "top")
1781         c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
1782 }
1783
1784 // Test case for 26220
1785 func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromBridge(c *check.C) {
1786         out, _ := dockerCmd(c, "network", "inspect", "--format", "{{.Id}}", "bridge")
1787
1788         network := strings.TrimSpace(out)
1789
1790         name := "test"
1791         dockerCmd(c, "create", "--name", name, "busybox", "top")
1792
1793         _, _, err := dockerCmdWithError("network", "disconnect", network, name)
1794         c.Assert(err, check.IsNil)
1795 }
1796
1797 // TestConntrackFlowsLeak covers the failure scenario of ticket: https://github.com/docker/docker/issues/8795
1798 // Validates that conntrack is correctly cleaned once a container is destroyed
1799 func (s *DockerNetworkSuite) TestConntrackFlowsLeak(c *check.C) {
1800         testRequires(c, IsAmd64, DaemonIsLinux, Network)
1801
1802         // Create a new network
1803         cli.DockerCmd(c, "network", "create", "--subnet=192.168.10.0/24", "--gateway=192.168.10.1", "-o", "com.docker.network.bridge.host_binding_ipv4=192.168.10.1", "testbind")
1804         assertNwIsAvailable(c, "testbind")
1805
1806         // Launch the server, this will remain listening on an exposed port and reply to any request in a ping/pong fashion
1807         cmd := "while true; do echo hello | nc -w 1 -lu 8080; done"
1808         cli.DockerCmd(c, "run", "-d", "--name", "server", "--net", "testbind", "-p", "8080:8080/udp", "appropriate/nc", "sh", "-c", cmd)
1809
1810         // Launch a container client, here the objective is to create a flow that is natted in order to expose the bug
1811         cmd = "echo world | nc -q 1 -u 192.168.10.1 8080"
1812         cli.DockerCmd(c, "run", "-d", "--name", "client", "--net=host", "appropriate/nc", "sh", "-c", cmd)
1813
1814         // Get all the flows using netlink
1815         flows, err := netlink.ConntrackTableList(netlink.ConntrackTable, syscall.AF_INET)
1816         c.Assert(err, check.IsNil)
1817         var flowMatch int
1818         for _, flow := range flows {
1819                 // count only the flows that we are interested in, skipping others that can be laying around the host
1820                 if flow.Forward.Protocol == syscall.IPPROTO_UDP &&
1821                         flow.Forward.DstIP.Equal(net.ParseIP("192.168.10.1")) &&
1822                         flow.Forward.DstPort == 8080 {
1823                         flowMatch++
1824                 }
1825         }
1826         // The client should have created only 1 flow
1827         c.Assert(flowMatch, checker.Equals, 1)
1828
1829         // Now delete the server, this will trigger the conntrack cleanup
1830         cli.DockerCmd(c, "rm", "-fv", "server")
1831
1832         // Fetch again all the flows and validate that there is no server flow in the conntrack laying around
1833         flows, err = netlink.ConntrackTableList(netlink.ConntrackTable, syscall.AF_INET)
1834         c.Assert(err, check.IsNil)
1835         flowMatch = 0
1836         for _, flow := range flows {
1837                 if flow.Forward.Protocol == syscall.IPPROTO_UDP &&
1838                         flow.Forward.DstIP.Equal(net.ParseIP("192.168.10.1")) &&
1839                         flow.Forward.DstPort == 8080 {
1840                         flowMatch++
1841                 }
1842         }
1843         // All the flows have to be gone
1844         c.Assert(flowMatch, checker.Equals, 0)
1845 }