github.com/jiasir/docker@v1.3.3-0.20170609024000-252e610103e7/integration-cli/docker_cli_network_unix_test.go (about)

     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  	testRequires(c, DaemonIsLinux, IsAmd64, Network)
   799  
   800  	var (
   801  		npName        = "tiborvass/test-docker-netplugin"
   802  		npTag         = "latest"
   803  		npNameWithTag = npName + ":" + npTag
   804  	)
   805  	_, _, err := dockerCmdWithError("plugin", "install", "--grant-all-permissions", npNameWithTag)
   806  	c.Assert(err, checker.IsNil)
   807  
   808  	out, _, err := dockerCmdWithError("plugin", "ls")
   809  	c.Assert(err, checker.IsNil)
   810  	c.Assert(out, checker.Contains, npName)
   811  	c.Assert(out, checker.Contains, npTag)
   812  	c.Assert(out, checker.Contains, "true")
   813  
   814  	dockerCmd(c, "network", "create", "-d", npNameWithTag, "v2net")
   815  	assertNwIsAvailable(c, "v2net")
   816  	dockerCmd(c, "network", "rm", "v2net")
   817  	assertNwNotAvailable(c, "v2net")
   818  
   819  }
   820  
   821  func (s *DockerDaemonSuite) TestDockerNetworkNoDiscoveryDefaultBridgeNetwork(c *check.C) {
   822  	testRequires(c, ExecSupport)
   823  	// On default bridge network built-in service discovery should not happen
   824  	hostsFile := "/etc/hosts"
   825  	bridgeName := "external-bridge"
   826  	bridgeIP := "192.169.255.254/24"
   827  	createInterface(c, "bridge", bridgeName, bridgeIP)
   828  	defer deleteInterface(c, bridgeName)
   829  
   830  	s.d.StartWithBusybox(c, "--bridge", bridgeName)
   831  	defer s.d.Restart(c)
   832  
   833  	// run two containers and store first container's etc/hosts content
   834  	out, err := s.d.Cmd("run", "-d", "busybox", "top")
   835  	c.Assert(err, check.IsNil)
   836  	cid1 := strings.TrimSpace(out)
   837  	defer s.d.Cmd("stop", cid1)
   838  
   839  	hosts, err := s.d.Cmd("exec", cid1, "cat", hostsFile)
   840  	c.Assert(err, checker.IsNil)
   841  
   842  	out, err = s.d.Cmd("run", "-d", "--name", "container2", "busybox", "top")
   843  	c.Assert(err, check.IsNil)
   844  	cid2 := strings.TrimSpace(out)
   845  
   846  	// verify first container's etc/hosts file has not changed after spawning the second named container
   847  	hostsPost, err := s.d.Cmd("exec", cid1, "cat", hostsFile)
   848  	c.Assert(err, checker.IsNil)
   849  	c.Assert(string(hosts), checker.Equals, string(hostsPost),
   850  		check.Commentf("Unexpected %s change on second container creation", hostsFile))
   851  
   852  	// stop container 2 and verify first container's etc/hosts has not changed
   853  	_, err = s.d.Cmd("stop", cid2)
   854  	c.Assert(err, check.IsNil)
   855  
   856  	hostsPost, err = s.d.Cmd("exec", cid1, "cat", hostsFile)
   857  	c.Assert(err, checker.IsNil)
   858  	c.Assert(string(hosts), checker.Equals, string(hostsPost),
   859  		check.Commentf("Unexpected %s change on second container creation", hostsFile))
   860  
   861  	// but discovery is on when connecting to non default bridge network
   862  	network := "anotherbridge"
   863  	out, err = s.d.Cmd("network", "create", network)
   864  	c.Assert(err, check.IsNil, check.Commentf(out))
   865  	defer s.d.Cmd("network", "rm", network)
   866  
   867  	out, err = s.d.Cmd("network", "connect", network, cid1)
   868  	c.Assert(err, check.IsNil, check.Commentf(out))
   869  
   870  	hosts, err = s.d.Cmd("exec", cid1, "cat", hostsFile)
   871  	c.Assert(err, checker.IsNil)
   872  
   873  	hostsPost, err = s.d.Cmd("exec", cid1, "cat", hostsFile)
   874  	c.Assert(err, checker.IsNil)
   875  	c.Assert(string(hosts), checker.Equals, string(hostsPost),
   876  		check.Commentf("Unexpected %s change on second network connection", hostsFile))
   877  }
   878  
   879  func (s *DockerNetworkSuite) TestDockerNetworkAnonymousEndpoint(c *check.C) {
   880  	testRequires(c, ExecSupport, NotArm)
   881  	hostsFile := "/etc/hosts"
   882  	cstmBridgeNw := "custom-bridge-nw"
   883  	cstmBridgeNw1 := "custom-bridge-nw1"
   884  
   885  	dockerCmd(c, "network", "create", "-d", "bridge", cstmBridgeNw)
   886  	assertNwIsAvailable(c, cstmBridgeNw)
   887  
   888  	// run two anonymous containers and store their etc/hosts content
   889  	out, _ := dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "busybox", "top")
   890  	cid1 := strings.TrimSpace(out)
   891  
   892  	hosts1 := readContainerFileWithExec(c, cid1, hostsFile)
   893  
   894  	out, _ = dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "busybox", "top")
   895  	cid2 := strings.TrimSpace(out)
   896  
   897  	hosts2 := readContainerFileWithExec(c, cid2, hostsFile)
   898  
   899  	// verify first container etc/hosts file has not changed
   900  	hosts1post := readContainerFileWithExec(c, cid1, hostsFile)
   901  	c.Assert(string(hosts1), checker.Equals, string(hosts1post),
   902  		check.Commentf("Unexpected %s change on anonymous container creation", hostsFile))
   903  
   904  	// Connect the 2nd container to a new network and verify the
   905  	// first container /etc/hosts file still hasn't changed.
   906  	dockerCmd(c, "network", "create", "-d", "bridge", cstmBridgeNw1)
   907  	assertNwIsAvailable(c, cstmBridgeNw1)
   908  
   909  	dockerCmd(c, "network", "connect", cstmBridgeNw1, cid2)
   910  
   911  	hosts2 = readContainerFileWithExec(c, cid2, hostsFile)
   912  	hosts1post = readContainerFileWithExec(c, cid1, hostsFile)
   913  	c.Assert(string(hosts1), checker.Equals, string(hosts1post),
   914  		check.Commentf("Unexpected %s change on container connect", hostsFile))
   915  
   916  	// start a named container
   917  	cName := "AnyName"
   918  	out, _ = dockerCmd(c, "run", "-d", "--net", cstmBridgeNw, "--name", cName, "busybox", "top")
   919  	cid3 := strings.TrimSpace(out)
   920  
   921  	// verify that container 1 and 2 can ping the named container
   922  	dockerCmd(c, "exec", cid1, "ping", "-c", "1", cName)
   923  	dockerCmd(c, "exec", cid2, "ping", "-c", "1", cName)
   924  
   925  	// Stop named container and verify first two containers' etc/hosts file hasn't changed
   926  	dockerCmd(c, "stop", cid3)
   927  	hosts1post = readContainerFileWithExec(c, cid1, hostsFile)
   928  	c.Assert(string(hosts1), checker.Equals, string(hosts1post),
   929  		check.Commentf("Unexpected %s change on name container creation", hostsFile))
   930  
   931  	hosts2post := readContainerFileWithExec(c, cid2, hostsFile)
   932  	c.Assert(string(hosts2), checker.Equals, string(hosts2post),
   933  		check.Commentf("Unexpected %s change on name container creation", hostsFile))
   934  
   935  	// verify that container 1 and 2 can't ping the named container now
   936  	_, _, err := dockerCmdWithError("exec", cid1, "ping", "-c", "1", cName)
   937  	c.Assert(err, check.NotNil)
   938  	_, _, err = dockerCmdWithError("exec", cid2, "ping", "-c", "1", cName)
   939  	c.Assert(err, check.NotNil)
   940  }
   941  
   942  func (s *DockerNetworkSuite) TestDockerNetworkLinkOnDefaultNetworkOnly(c *check.C) {
   943  	// Legacy Link feature must work only on default network, and not across networks
   944  	cnt1 := "container1"
   945  	cnt2 := "container2"
   946  	network := "anotherbridge"
   947  
   948  	// Run first container on default network
   949  	dockerCmd(c, "run", "-d", "--name", cnt1, "busybox", "top")
   950  
   951  	// Create another network and run the second container on it
   952  	dockerCmd(c, "network", "create", network)
   953  	assertNwIsAvailable(c, network)
   954  	dockerCmd(c, "run", "-d", "--net", network, "--name", cnt2, "busybox", "top")
   955  
   956  	// Try launching a container on default network, linking to the first container. Must succeed
   957  	dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt1, cnt1), "busybox", "top")
   958  
   959  	// Try launching a container on default network, linking to the second container. Must fail
   960  	_, _, err := dockerCmdWithError("run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top")
   961  	c.Assert(err, checker.NotNil)
   962  
   963  	// Connect second container to default network. Now a container on default network can link to it
   964  	dockerCmd(c, "network", "connect", "bridge", cnt2)
   965  	dockerCmd(c, "run", "-d", "--link", fmt.Sprintf("%s:%s", cnt2, cnt2), "busybox", "top")
   966  }
   967  
   968  func (s *DockerNetworkSuite) TestDockerNetworkOverlayPortMapping(c *check.C) {
   969  	// Verify exposed ports are present in ps output when running a container on
   970  	// a network managed by a driver which does not provide the default gateway
   971  	// for the container
   972  	nwn := "ov"
   973  	ctn := "bb"
   974  	port1 := 80
   975  	port2 := 443
   976  	expose1 := fmt.Sprintf("--expose=%d", port1)
   977  	expose2 := fmt.Sprintf("--expose=%d", port2)
   978  
   979  	dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn)
   980  	assertNwIsAvailable(c, nwn)
   981  
   982  	dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, expose1, expose2, "busybox", "top")
   983  
   984  	// Check docker ps o/p for last created container reports the unpublished ports
   985  	unpPort1 := fmt.Sprintf("%d/tcp", port1)
   986  	unpPort2 := fmt.Sprintf("%d/tcp", port2)
   987  	out, _ := dockerCmd(c, "ps", "-n=1")
   988  	// Missing unpublished ports in docker ps output
   989  	c.Assert(out, checker.Contains, unpPort1)
   990  	// Missing unpublished ports in docker ps output
   991  	c.Assert(out, checker.Contains, unpPort2)
   992  }
   993  
   994  func (s *DockerNetworkSuite) TestDockerNetworkDriverUngracefulRestart(c *check.C) {
   995  	testRequires(c, DaemonIsLinux, NotUserNamespace)
   996  	dnd := "dnd"
   997  	did := "did"
   998  
   999  	mux := http.NewServeMux()
  1000  	server := httptest.NewServer(mux)
  1001  	setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did)
  1002  
  1003  	s.d.StartWithBusybox(c)
  1004  	_, err := s.d.Cmd("network", "create", "-d", dnd, "--subnet", "1.1.1.0/24", "net1")
  1005  	c.Assert(err, checker.IsNil)
  1006  
  1007  	_, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "foo", "--ip", "1.1.1.10", "busybox", "sh")
  1008  	c.Assert(err, checker.IsNil)
  1009  
  1010  	// Kill daemon and restart
  1011  	c.Assert(s.d.Kill(), checker.IsNil)
  1012  
  1013  	server.Close()
  1014  
  1015  	startTime := time.Now().Unix()
  1016  	s.d.Restart(c)
  1017  	lapse := time.Now().Unix() - startTime
  1018  	if lapse > 60 {
  1019  		// In normal scenarios, daemon restart takes ~1 second.
  1020  		// Plugin retry mechanism can delay the daemon start. systemd may not like it.
  1021  		// Avoid accessing plugins during daemon bootup
  1022  		c.Logf("daemon restart took too long : %d seconds", lapse)
  1023  	}
  1024  
  1025  	// Restart the custom dummy plugin
  1026  	mux = http.NewServeMux()
  1027  	server = httptest.NewServer(mux)
  1028  	setupRemoteNetworkDrivers(c, mux, server.URL, dnd, did)
  1029  
  1030  	// trying to reuse the same ip must succeed
  1031  	_, err = s.d.Cmd("run", "-itd", "--net", "net1", "--name", "bar", "--ip", "1.1.1.10", "busybox", "sh")
  1032  	c.Assert(err, checker.IsNil)
  1033  }
  1034  
  1035  func (s *DockerNetworkSuite) TestDockerNetworkMacInspect(c *check.C) {
  1036  	// Verify endpoint MAC address is correctly populated in container's network settings
  1037  	nwn := "ov"
  1038  	ctn := "bb"
  1039  
  1040  	dockerCmd(c, "network", "create", "-d", dummyNetworkDriver, nwn)
  1041  	assertNwIsAvailable(c, nwn)
  1042  
  1043  	dockerCmd(c, "run", "-d", "--net", nwn, "--name", ctn, "busybox", "top")
  1044  
  1045  	mac := inspectField(c, ctn, "NetworkSettings.Networks."+nwn+".MacAddress")
  1046  	c.Assert(mac, checker.Equals, "a0:b1:c2:d3:e4:f5")
  1047  }
  1048  
  1049  func (s *DockerSuite) TestInspectAPIMultipleNetworks(c *check.C) {
  1050  	dockerCmd(c, "network", "create", "mybridge1")
  1051  	dockerCmd(c, "network", "create", "mybridge2")
  1052  	out, _ := dockerCmd(c, "run", "-d", "busybox", "top")
  1053  	id := strings.TrimSpace(out)
  1054  	c.Assert(waitRun(id), check.IsNil)
  1055  
  1056  	dockerCmd(c, "network", "connect", "mybridge1", id)
  1057  	dockerCmd(c, "network", "connect", "mybridge2", id)
  1058  
  1059  	body := getInspectBody(c, "v1.20", id)
  1060  	var inspect120 v1p20.ContainerJSON
  1061  	err := json.Unmarshal(body, &inspect120)
  1062  	c.Assert(err, checker.IsNil)
  1063  
  1064  	versionedIP := inspect120.NetworkSettings.IPAddress
  1065  
  1066  	body = getInspectBody(c, "v1.21", id)
  1067  	var inspect121 types.ContainerJSON
  1068  	err = json.Unmarshal(body, &inspect121)
  1069  	c.Assert(err, checker.IsNil)
  1070  	c.Assert(inspect121.NetworkSettings.Networks, checker.HasLen, 3)
  1071  
  1072  	bridge := inspect121.NetworkSettings.Networks["bridge"]
  1073  	c.Assert(bridge.IPAddress, checker.Equals, versionedIP)
  1074  	c.Assert(bridge.IPAddress, checker.Equals, inspect121.NetworkSettings.IPAddress)
  1075  }
  1076  
  1077  func connectContainerToNetworks(c *check.C, d *daemon.Daemon, cName string, nws []string) {
  1078  	// Run a container on the default network
  1079  	out, err := d.Cmd("run", "-d", "--name", cName, "busybox", "top")
  1080  	c.Assert(err, checker.IsNil, check.Commentf(out))
  1081  
  1082  	// Attach the container to other networks
  1083  	for _, nw := range nws {
  1084  		out, err = d.Cmd("network", "create", nw)
  1085  		c.Assert(err, checker.IsNil, check.Commentf(out))
  1086  		out, err = d.Cmd("network", "connect", nw, cName)
  1087  		c.Assert(err, checker.IsNil, check.Commentf(out))
  1088  	}
  1089  }
  1090  
  1091  func verifyContainerIsConnectedToNetworks(c *check.C, d *daemon.Daemon, cName string, nws []string) {
  1092  	// Verify container is connected to all the networks
  1093  	for _, nw := range nws {
  1094  		out, err := d.Cmd("inspect", "-f", fmt.Sprintf("{{.NetworkSettings.Networks.%s}}", nw), cName)
  1095  		c.Assert(err, checker.IsNil, check.Commentf(out))
  1096  		c.Assert(out, checker.Not(checker.Equals), "<no value>\n")
  1097  	}
  1098  }
  1099  
  1100  func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksGracefulDaemonRestart(c *check.C) {
  1101  	cName := "bb"
  1102  	nwList := []string{"nw1", "nw2", "nw3"}
  1103  
  1104  	s.d.StartWithBusybox(c)
  1105  
  1106  	connectContainerToNetworks(c, s.d, cName, nwList)
  1107  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1108  
  1109  	// Reload daemon
  1110  	s.d.Restart(c)
  1111  
  1112  	_, err := s.d.Cmd("start", cName)
  1113  	c.Assert(err, checker.IsNil)
  1114  
  1115  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1116  }
  1117  
  1118  func (s *DockerNetworkSuite) TestDockerNetworkMultipleNetworksUngracefulDaemonRestart(c *check.C) {
  1119  	cName := "cc"
  1120  	nwList := []string{"nw1", "nw2", "nw3"}
  1121  
  1122  	s.d.StartWithBusybox(c)
  1123  
  1124  	connectContainerToNetworks(c, s.d, cName, nwList)
  1125  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1126  
  1127  	// Kill daemon and restart
  1128  	c.Assert(s.d.Kill(), checker.IsNil)
  1129  	s.d.Restart(c)
  1130  
  1131  	// Restart container
  1132  	_, err := s.d.Cmd("start", cName)
  1133  	c.Assert(err, checker.IsNil)
  1134  
  1135  	verifyContainerIsConnectedToNetworks(c, s.d, cName, nwList)
  1136  }
  1137  
  1138  func (s *DockerNetworkSuite) TestDockerNetworkRunNetByID(c *check.C) {
  1139  	out, _ := dockerCmd(c, "network", "create", "one")
  1140  	containerOut, _, err := dockerCmdWithError("run", "-d", "--net", strings.TrimSpace(out), "busybox", "top")
  1141  	c.Assert(err, checker.IsNil, check.Commentf(containerOut))
  1142  }
  1143  
  1144  func (s *DockerNetworkSuite) TestDockerNetworkHostModeUngracefulDaemonRestart(c *check.C) {
  1145  	testRequires(c, DaemonIsLinux, NotUserNamespace)
  1146  	s.d.StartWithBusybox(c)
  1147  
  1148  	// Run a few containers on host network
  1149  	for i := 0; i < 10; i++ {
  1150  		cName := fmt.Sprintf("hostc-%d", i)
  1151  		out, err := s.d.Cmd("run", "-d", "--name", cName, "--net=host", "--restart=always", "busybox", "top")
  1152  		c.Assert(err, checker.IsNil, check.Commentf(out))
  1153  
  1154  		// verfiy container has finished starting before killing daemon
  1155  		err = s.d.WaitRun(cName)
  1156  		c.Assert(err, checker.IsNil)
  1157  	}
  1158  
  1159  	// Kill daemon ungracefully and restart
  1160  	c.Assert(s.d.Kill(), checker.IsNil)
  1161  	s.d.Restart(c)
  1162  
  1163  	// make sure all the containers are up and running
  1164  	for i := 0; i < 10; i++ {
  1165  		err := s.d.WaitRun(fmt.Sprintf("hostc-%d", i))
  1166  		c.Assert(err, checker.IsNil)
  1167  	}
  1168  }
  1169  
  1170  func (s *DockerNetworkSuite) TestDockerNetworkConnectToHostFromOtherNetwork(c *check.C) {
  1171  	dockerCmd(c, "run", "-d", "--name", "container1", "busybox", "top")
  1172  	c.Assert(waitRun("container1"), check.IsNil)
  1173  	dockerCmd(c, "network", "disconnect", "bridge", "container1")
  1174  	out, _, err := dockerCmdWithError("network", "connect", "host", "container1")
  1175  	c.Assert(err, checker.NotNil, check.Commentf(out))
  1176  	c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error())
  1177  }
  1178  
  1179  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromHost(c *check.C) {
  1180  	dockerCmd(c, "run", "-d", "--name", "container1", "--net=host", "busybox", "top")
  1181  	c.Assert(waitRun("container1"), check.IsNil)
  1182  	out, _, err := dockerCmdWithError("network", "disconnect", "host", "container1")
  1183  	c.Assert(err, checker.NotNil, check.Commentf("Should err out disconnect from host"))
  1184  	c.Assert(out, checker.Contains, runconfig.ErrConflictHostNetwork.Error())
  1185  }
  1186  
  1187  func (s *DockerNetworkSuite) TestDockerNetworkConnectWithPortMapping(c *check.C) {
  1188  	testRequires(c, NotArm)
  1189  	dockerCmd(c, "network", "create", "test1")
  1190  	dockerCmd(c, "run", "-d", "--name", "c1", "-p", "5000:5000", "busybox", "top")
  1191  	c.Assert(waitRun("c1"), check.IsNil)
  1192  	dockerCmd(c, "network", "connect", "test1", "c1")
  1193  }
  1194  
  1195  func verifyPortMap(c *check.C, container, port, originalMapping string, mustBeEqual bool) {
  1196  	chk := checker.Equals
  1197  	if !mustBeEqual {
  1198  		chk = checker.Not(checker.Equals)
  1199  	}
  1200  	currentMapping, _ := dockerCmd(c, "port", container, port)
  1201  	c.Assert(currentMapping, chk, originalMapping)
  1202  }
  1203  
  1204  func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectWithPortMapping(c *check.C) {
  1205  	// Connect and disconnect a container with explicit and non-explicit
  1206  	// host port mapping to/from networks which do cause and do not cause
  1207  	// the container default gateway to change, and verify docker port cmd
  1208  	// returns congruent information
  1209  	testRequires(c, NotArm)
  1210  	cnt := "c1"
  1211  	dockerCmd(c, "network", "create", "aaa")
  1212  	dockerCmd(c, "network", "create", "ccc")
  1213  
  1214  	dockerCmd(c, "run", "-d", "--name", cnt, "-p", "9000:90", "-p", "70", "busybox", "top")
  1215  	c.Assert(waitRun(cnt), check.IsNil)
  1216  	curPortMap, _ := dockerCmd(c, "port", cnt, "70")
  1217  	curExplPortMap, _ := dockerCmd(c, "port", cnt, "90")
  1218  
  1219  	// Connect to a network which causes the container's default gw switch
  1220  	dockerCmd(c, "network", "connect", "aaa", cnt)
  1221  	verifyPortMap(c, cnt, "70", curPortMap, false)
  1222  	verifyPortMap(c, cnt, "90", curExplPortMap, true)
  1223  
  1224  	// Read current mapping
  1225  	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
  1226  
  1227  	// Disconnect from a network which causes the container's default gw switch
  1228  	dockerCmd(c, "network", "disconnect", "aaa", cnt)
  1229  	verifyPortMap(c, cnt, "70", curPortMap, false)
  1230  	verifyPortMap(c, cnt, "90", curExplPortMap, true)
  1231  
  1232  	// Read current mapping
  1233  	curPortMap, _ = dockerCmd(c, "port", cnt, "70")
  1234  
  1235  	// Connect to a network which does not cause the container's default gw switch
  1236  	dockerCmd(c, "network", "connect", "ccc", cnt)
  1237  	verifyPortMap(c, cnt, "70", curPortMap, true)
  1238  	verifyPortMap(c, cnt, "90", curExplPortMap, true)
  1239  }
  1240  
  1241  func (s *DockerNetworkSuite) TestDockerNetworkConnectWithMac(c *check.C) {
  1242  	macAddress := "02:42:ac:11:00:02"
  1243  	dockerCmd(c, "network", "create", "mynetwork")
  1244  	dockerCmd(c, "run", "--name=test", "-d", "--mac-address", macAddress, "busybox", "top")
  1245  	c.Assert(waitRun("test"), check.IsNil)
  1246  	mac1 := inspectField(c, "test", "NetworkSettings.Networks.bridge.MacAddress")
  1247  	c.Assert(strings.TrimSpace(mac1), checker.Equals, macAddress)
  1248  	dockerCmd(c, "network", "connect", "mynetwork", "test")
  1249  	mac2 := inspectField(c, "test", "NetworkSettings.Networks.mynetwork.MacAddress")
  1250  	c.Assert(strings.TrimSpace(mac2), checker.Not(checker.Equals), strings.TrimSpace(mac1))
  1251  }
  1252  
  1253  func (s *DockerNetworkSuite) TestDockerNetworkInspectCreatedContainer(c *check.C) {
  1254  	dockerCmd(c, "create", "--name", "test", "busybox")
  1255  	networks := inspectField(c, "test", "NetworkSettings.Networks")
  1256  	c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should return 'bridge' network"))
  1257  }
  1258  
  1259  func (s *DockerNetworkSuite) TestDockerNetworkRestartWithMultipleNetworks(c *check.C) {
  1260  	dockerCmd(c, "network", "create", "test")
  1261  	dockerCmd(c, "run", "--name=foo", "-d", "busybox", "top")
  1262  	c.Assert(waitRun("foo"), checker.IsNil)
  1263  	dockerCmd(c, "network", "connect", "test", "foo")
  1264  	dockerCmd(c, "restart", "foo")
  1265  	networks := inspectField(c, "foo", "NetworkSettings.Networks")
  1266  	c.Assert(networks, checker.Contains, "bridge", check.Commentf("Should contain 'bridge' network"))
  1267  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1268  }
  1269  
  1270  func (s *DockerNetworkSuite) TestDockerNetworkConnectDisconnectToStoppedContainer(c *check.C) {
  1271  	dockerCmd(c, "network", "create", "test")
  1272  	dockerCmd(c, "create", "--name=foo", "busybox", "top")
  1273  	dockerCmd(c, "network", "connect", "test", "foo")
  1274  	networks := inspectField(c, "foo", "NetworkSettings.Networks")
  1275  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1276  
  1277  	// Restart docker daemon to test the config has persisted to disk
  1278  	s.d.Restart(c)
  1279  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1280  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1281  
  1282  	// start the container and test if we can ping it from another container in the same network
  1283  	dockerCmd(c, "start", "foo")
  1284  	c.Assert(waitRun("foo"), checker.IsNil)
  1285  	ip := inspectField(c, "foo", "NetworkSettings.Networks.test.IPAddress")
  1286  	ip = strings.TrimSpace(ip)
  1287  	dockerCmd(c, "run", "--net=test", "busybox", "sh", "-c", fmt.Sprintf("ping -c 1 %s", ip))
  1288  
  1289  	dockerCmd(c, "stop", "foo")
  1290  
  1291  	// Test disconnect
  1292  	dockerCmd(c, "network", "disconnect", "test", "foo")
  1293  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1294  	c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
  1295  
  1296  	// Restart docker daemon to test the config has persisted to disk
  1297  	s.d.Restart(c)
  1298  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1299  	c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
  1300  
  1301  }
  1302  
  1303  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectContainerNonexistingNetwork(c *check.C) {
  1304  	dockerCmd(c, "network", "create", "test")
  1305  	dockerCmd(c, "run", "--net=test", "-d", "--name=foo", "busybox", "top")
  1306  	networks := inspectField(c, "foo", "NetworkSettings.Networks")
  1307  	c.Assert(networks, checker.Contains, "test", check.Commentf("Should contain 'test' network"))
  1308  
  1309  	// Stop container and remove network
  1310  	dockerCmd(c, "stop", "foo")
  1311  	dockerCmd(c, "network", "rm", "test")
  1312  
  1313  	// Test disconnecting stopped container from nonexisting network
  1314  	dockerCmd(c, "network", "disconnect", "-f", "test", "foo")
  1315  	networks = inspectField(c, "foo", "NetworkSettings.Networks")
  1316  	c.Assert(networks, checker.Not(checker.Contains), "test", check.Commentf("Should not contain 'test' network"))
  1317  }
  1318  
  1319  func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIP(c *check.C) {
  1320  	// create two networks
  1321  	dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "n0")
  1322  	assertNwIsAvailable(c, "n0")
  1323  
  1324  	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")
  1325  	assertNwIsAvailable(c, "n1")
  1326  
  1327  	// run a container on first network specifying the ip addresses
  1328  	dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
  1329  	c.Assert(waitRun("c0"), check.IsNil)
  1330  	verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1331  	verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1332  
  1333  	// connect the container to the second network specifying an ip addresses
  1334  	dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n1", "c0")
  1335  	verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1336  	verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1337  
  1338  	// Stop and restart the container
  1339  	dockerCmd(c, "stop", "c0")
  1340  	dockerCmd(c, "start", "c0")
  1341  
  1342  	// verify requested addresses are applied and configs are still there
  1343  	verifyIPAddressConfig(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1344  	verifyIPAddresses(c, "c0", "n0", "172.28.99.88", "2001:db8:1234::9988")
  1345  	verifyIPAddressConfig(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1346  	verifyIPAddresses(c, "c0", "n1", "172.30.55.44", "2001:db8:abcd::5544")
  1347  
  1348  	// Still it should fail to connect to the default network with a specified IP (whatever ip)
  1349  	out, _, err := dockerCmdWithError("network", "connect", "--ip", "172.21.55.44", "bridge", "c0")
  1350  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1351  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error())
  1352  
  1353  }
  1354  
  1355  func (s *DockerNetworkSuite) TestDockerNetworkConnectPreferredIPStoppedContainer(c *check.C) {
  1356  	// create a container
  1357  	dockerCmd(c, "create", "--name", "c0", "busybox", "top")
  1358  
  1359  	// create a network
  1360  	dockerCmd(c, "network", "create", "--ipv6", "--subnet=172.30.0.0/16", "--subnet=2001:db8:abcd::/64", "n0")
  1361  	assertNwIsAvailable(c, "n0")
  1362  
  1363  	// connect the container to the network specifying an ip addresses
  1364  	dockerCmd(c, "network", "connect", "--ip", "172.30.55.44", "--ip6", "2001:db8:abcd::5544", "n0", "c0")
  1365  	verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1366  
  1367  	// start the container, verify config has not changed and ip addresses are assigned
  1368  	dockerCmd(c, "start", "c0")
  1369  	c.Assert(waitRun("c0"), check.IsNil)
  1370  	verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1371  	verifyIPAddresses(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1372  
  1373  	// stop the container and check ip config has not changed
  1374  	dockerCmd(c, "stop", "c0")
  1375  	verifyIPAddressConfig(c, "c0", "n0", "172.30.55.44", "2001:db8:abcd::5544")
  1376  }
  1377  
  1378  func (s *DockerNetworkSuite) TestDockerNetworkUnsupportedRequiredIP(c *check.C) {
  1379  	// requested IP is not supported on predefined networks
  1380  	for _, mode := range []string{"none", "host", "bridge", "default"} {
  1381  		checkUnsupportedNetworkAndIP(c, mode)
  1382  	}
  1383  
  1384  	// requested IP is not supported on networks with no user defined subnets
  1385  	dockerCmd(c, "network", "create", "n0")
  1386  	assertNwIsAvailable(c, "n0")
  1387  
  1388  	out, _, err := dockerCmdWithError("run", "-d", "--ip", "172.28.99.88", "--net", "n0", "busybox", "top")
  1389  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1390  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error())
  1391  
  1392  	out, _, err = dockerCmdWithError("run", "-d", "--ip6", "2001:db8:1234::9988", "--net", "n0", "busybox", "top")
  1393  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1394  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkNoSubnetAndIP.Error())
  1395  
  1396  	dockerCmd(c, "network", "rm", "n0")
  1397  	assertNwNotAvailable(c, "n0")
  1398  }
  1399  
  1400  func checkUnsupportedNetworkAndIP(c *check.C, nwMode string) {
  1401  	out, _, err := dockerCmdWithError("run", "-d", "--net", nwMode, "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
  1402  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1403  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndIP.Error())
  1404  }
  1405  
  1406  func verifyIPAddressConfig(c *check.C, cName, nwname, ipv4, ipv6 string) {
  1407  	if ipv4 != "" {
  1408  		out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv4Address", nwname))
  1409  		c.Assert(strings.TrimSpace(out), check.Equals, ipv4)
  1410  	}
  1411  
  1412  	if ipv6 != "" {
  1413  		out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAMConfig.IPv6Address", nwname))
  1414  		c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
  1415  	}
  1416  }
  1417  
  1418  func verifyIPAddresses(c *check.C, cName, nwname, ipv4, ipv6 string) {
  1419  	out := inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.IPAddress", nwname))
  1420  	c.Assert(strings.TrimSpace(out), check.Equals, ipv4)
  1421  
  1422  	out = inspectField(c, cName, fmt.Sprintf("NetworkSettings.Networks.%s.GlobalIPv6Address", nwname))
  1423  	c.Assert(strings.TrimSpace(out), check.Equals, ipv6)
  1424  }
  1425  
  1426  func (s *DockerNetworkSuite) TestDockerNetworkConnectLinkLocalIP(c *check.C) {
  1427  	// create one test network
  1428  	dockerCmd(c, "network", "create", "--ipv6", "--subnet=2001:db8:1234::/64", "n0")
  1429  	assertNwIsAvailable(c, "n0")
  1430  
  1431  	// run a container with incorrect link-local address
  1432  	_, _, err := dockerCmdWithError("run", "--link-local-ip", "169.253.5.5", "busybox", "top")
  1433  	c.Assert(err, check.NotNil)
  1434  	_, _, err = dockerCmdWithError("run", "--link-local-ip", "2001:db8::89", "busybox", "top")
  1435  	c.Assert(err, check.NotNil)
  1436  
  1437  	// run two containers with link-local ip on the test network
  1438  	dockerCmd(c, "run", "-d", "--name", "c0", "--net=n0", "--link-local-ip", "169.254.7.7", "--link-local-ip", "fe80::254:77", "busybox", "top")
  1439  	c.Assert(waitRun("c0"), check.IsNil)
  1440  	dockerCmd(c, "run", "-d", "--name", "c1", "--net=n0", "--link-local-ip", "169.254.8.8", "--link-local-ip", "fe80::254:88", "busybox", "top")
  1441  	c.Assert(waitRun("c1"), check.IsNil)
  1442  
  1443  	// run a container on the default network and connect it to the test network specifying a link-local address
  1444  	dockerCmd(c, "run", "-d", "--name", "c2", "busybox", "top")
  1445  	c.Assert(waitRun("c2"), check.IsNil)
  1446  	dockerCmd(c, "network", "connect", "--link-local-ip", "169.254.9.9", "n0", "c2")
  1447  
  1448  	// verify the three containers can ping each other via the link-local addresses
  1449  	_, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
  1450  	c.Assert(err, check.IsNil)
  1451  	_, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
  1452  	c.Assert(err, check.IsNil)
  1453  	_, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
  1454  	c.Assert(err, check.IsNil)
  1455  
  1456  	// Stop and restart the three containers
  1457  	dockerCmd(c, "stop", "c0")
  1458  	dockerCmd(c, "stop", "c1")
  1459  	dockerCmd(c, "stop", "c2")
  1460  	dockerCmd(c, "start", "c0")
  1461  	dockerCmd(c, "start", "c1")
  1462  	dockerCmd(c, "start", "c2")
  1463  
  1464  	// verify the ping again
  1465  	_, _, err = dockerCmdWithError("exec", "c0", "ping", "-c", "1", "169.254.8.8")
  1466  	c.Assert(err, check.IsNil)
  1467  	_, _, err = dockerCmdWithError("exec", "c1", "ping", "-c", "1", "169.254.9.9")
  1468  	c.Assert(err, check.IsNil)
  1469  	_, _, err = dockerCmdWithError("exec", "c2", "ping", "-c", "1", "169.254.7.7")
  1470  	c.Assert(err, check.IsNil)
  1471  }
  1472  
  1473  func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectLink(c *check.C) {
  1474  	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
  1475  	dockerCmd(c, "network", "create", "-d", "bridge", "foo1")
  1476  	dockerCmd(c, "network", "create", "-d", "bridge", "foo2")
  1477  
  1478  	dockerCmd(c, "run", "-d", "--net=foo1", "--name=first", "busybox", "top")
  1479  	c.Assert(waitRun("first"), check.IsNil)
  1480  
  1481  	// run a container in a user-defined network with a link for an existing container
  1482  	// and a link for a container that doesn't exist
  1483  	dockerCmd(c, "run", "-d", "--net=foo1", "--name=second", "--link=first:FirstInFoo1",
  1484  		"--link=third:bar", "busybox", "top")
  1485  	c.Assert(waitRun("second"), check.IsNil)
  1486  
  1487  	// ping to first and its alias FirstInFoo1 must succeed
  1488  	_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
  1489  	c.Assert(err, check.IsNil)
  1490  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
  1491  	c.Assert(err, check.IsNil)
  1492  
  1493  	// connect first container to foo2 network
  1494  	dockerCmd(c, "network", "connect", "foo2", "first")
  1495  	// connect second container to foo2 network with a different alias for first container
  1496  	dockerCmd(c, "network", "connect", "--link=first:FirstInFoo2", "foo2", "second")
  1497  
  1498  	// ping the new alias in network foo2
  1499  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
  1500  	c.Assert(err, check.IsNil)
  1501  
  1502  	// disconnect first container from foo1 network
  1503  	dockerCmd(c, "network", "disconnect", "foo1", "first")
  1504  
  1505  	// link in foo1 network must fail
  1506  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo1")
  1507  	c.Assert(err, check.NotNil)
  1508  
  1509  	// link in foo2 network must succeed
  1510  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "FirstInFoo2")
  1511  	c.Assert(err, check.IsNil)
  1512  }
  1513  
  1514  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectDefault(c *check.C) {
  1515  	netWorkName1 := "test1"
  1516  	netWorkName2 := "test2"
  1517  	containerName := "foo"
  1518  
  1519  	dockerCmd(c, "network", "create", netWorkName1)
  1520  	dockerCmd(c, "network", "create", netWorkName2)
  1521  	dockerCmd(c, "create", "--name", containerName, "busybox", "top")
  1522  	dockerCmd(c, "network", "connect", netWorkName1, containerName)
  1523  	dockerCmd(c, "network", "connect", netWorkName2, containerName)
  1524  	dockerCmd(c, "network", "disconnect", "bridge", containerName)
  1525  
  1526  	dockerCmd(c, "start", containerName)
  1527  	c.Assert(waitRun(containerName), checker.IsNil)
  1528  	networks := inspectField(c, containerName, "NetworkSettings.Networks")
  1529  	c.Assert(networks, checker.Contains, netWorkName1, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName1)))
  1530  	c.Assert(networks, checker.Contains, netWorkName2, check.Commentf(fmt.Sprintf("Should contain '%s' network", netWorkName2)))
  1531  	c.Assert(networks, checker.Not(checker.Contains), "bridge", check.Commentf("Should not contain 'bridge' network"))
  1532  }
  1533  
  1534  func (s *DockerNetworkSuite) TestDockerNetworkConnectWithAliasOnDefaultNetworks(c *check.C) {
  1535  	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
  1536  
  1537  	defaults := []string{"bridge", "host", "none"}
  1538  	out, _ := dockerCmd(c, "run", "-d", "--net=none", "busybox", "top")
  1539  	containerID := strings.TrimSpace(out)
  1540  	for _, net := range defaults {
  1541  		res, _, err := dockerCmdWithError("network", "connect", "--alias", "alias"+net, net, containerID)
  1542  		c.Assert(err, checker.NotNil)
  1543  		c.Assert(res, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
  1544  	}
  1545  }
  1546  
  1547  func (s *DockerSuite) TestUserDefinedNetworkConnectDisconnectAlias(c *check.C) {
  1548  	testRequires(c, DaemonIsLinux, NotUserNamespace, NotArm)
  1549  	dockerCmd(c, "network", "create", "-d", "bridge", "net1")
  1550  	dockerCmd(c, "network", "create", "-d", "bridge", "net2")
  1551  
  1552  	cid, _ := dockerCmd(c, "run", "-d", "--net=net1", "--name=first", "--net-alias=foo", "busybox", "top")
  1553  	c.Assert(waitRun("first"), check.IsNil)
  1554  
  1555  	dockerCmd(c, "run", "-d", "--net=net1", "--name=second", "busybox", "top")
  1556  	c.Assert(waitRun("second"), check.IsNil)
  1557  
  1558  	// ping first container and its alias
  1559  	_, _, err := dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
  1560  	c.Assert(err, check.IsNil)
  1561  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
  1562  	c.Assert(err, check.IsNil)
  1563  
  1564  	// ping first container's short-id alias
  1565  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid))
  1566  	c.Assert(err, check.IsNil)
  1567  
  1568  	// connect first container to net2 network
  1569  	dockerCmd(c, "network", "connect", "--alias=bar", "net2", "first")
  1570  	// connect second container to foo2 network with a different alias for first container
  1571  	dockerCmd(c, "network", "connect", "net2", "second")
  1572  
  1573  	// ping the new alias in network foo2
  1574  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
  1575  	c.Assert(err, check.IsNil)
  1576  
  1577  	// disconnect first container from net1 network
  1578  	dockerCmd(c, "network", "disconnect", "net1", "first")
  1579  
  1580  	// ping to net1 scoped alias "foo" must fail
  1581  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "foo")
  1582  	c.Assert(err, check.NotNil)
  1583  
  1584  	// ping to net2 scoped alias "bar" must still succeed
  1585  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "bar")
  1586  	c.Assert(err, check.IsNil)
  1587  	// ping to net2 scoped alias short-id must still succeed
  1588  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", stringid.TruncateID(cid))
  1589  	c.Assert(err, check.IsNil)
  1590  
  1591  	// verify the alias option is rejected when running on predefined network
  1592  	out, _, err := dockerCmdWithError("run", "--rm", "--name=any", "--net-alias=any", "busybox", "top")
  1593  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1594  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
  1595  
  1596  	// verify the alias option is rejected when connecting to predefined network
  1597  	out, _, err = dockerCmdWithError("network", "connect", "--alias=any", "bridge", "first")
  1598  	c.Assert(err, checker.NotNil, check.Commentf("out: %s", out))
  1599  	c.Assert(out, checker.Contains, runconfig.ErrUnsupportedNetworkAndAlias.Error())
  1600  }
  1601  
  1602  func (s *DockerSuite) TestUserDefinedNetworkConnectivity(c *check.C) {
  1603  	testRequires(c, DaemonIsLinux, NotUserNamespace)
  1604  	dockerCmd(c, "network", "create", "-d", "bridge", "br.net1")
  1605  
  1606  	dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c1.net1", "busybox", "top")
  1607  	c.Assert(waitRun("c1.net1"), check.IsNil)
  1608  
  1609  	dockerCmd(c, "run", "-d", "--net=br.net1", "--name=c2.net1", "busybox", "top")
  1610  	c.Assert(waitRun("c2.net1"), check.IsNil)
  1611  
  1612  	// ping first container by its unqualified name
  1613  	_, _, err := dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1")
  1614  	c.Assert(err, check.IsNil)
  1615  
  1616  	// ping first container by its qualified name
  1617  	_, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1")
  1618  	c.Assert(err, check.IsNil)
  1619  
  1620  	// ping with first qualified name masked by an additional domain. should fail
  1621  	_, _, err = dockerCmdWithError("exec", "c2.net1", "ping", "-c", "1", "c1.net1.br.net1.google.com")
  1622  	c.Assert(err, check.NotNil)
  1623  }
  1624  
  1625  func (s *DockerSuite) TestEmbeddedDNSInvalidInput(c *check.C) {
  1626  	testRequires(c, DaemonIsLinux, NotUserNamespace)
  1627  	dockerCmd(c, "network", "create", "-d", "bridge", "nw1")
  1628  
  1629  	// Sending garbage to embedded DNS shouldn't crash the daemon
  1630  	dockerCmd(c, "run", "-i", "--net=nw1", "--name=c1", "debian:jessie", "bash", "-c", "echo InvalidQuery > /dev/udp/127.0.0.11/53")
  1631  }
  1632  
  1633  func (s *DockerSuite) TestDockerNetworkConnectFailsNoInspectChange(c *check.C) {
  1634  	dockerCmd(c, "run", "-d", "--name=bb", "busybox", "top")
  1635  	c.Assert(waitRun("bb"), check.IsNil)
  1636  
  1637  	ns0 := inspectField(c, "bb", "NetworkSettings.Networks.bridge")
  1638  
  1639  	// A failing redundant network connect should not alter current container's endpoint settings
  1640  	_, _, err := dockerCmdWithError("network", "connect", "bridge", "bb")
  1641  	c.Assert(err, check.NotNil)
  1642  
  1643  	ns1 := inspectField(c, "bb", "NetworkSettings.Networks.bridge")
  1644  	c.Assert(ns1, check.Equals, ns0)
  1645  }
  1646  
  1647  func (s *DockerSuite) TestDockerNetworkInternalMode(c *check.C) {
  1648  	dockerCmd(c, "network", "create", "--driver=bridge", "--internal", "internal")
  1649  	assertNwIsAvailable(c, "internal")
  1650  	nr := getNetworkResource(c, "internal")
  1651  	c.Assert(nr.Internal, checker.True)
  1652  
  1653  	dockerCmd(c, "run", "-d", "--net=internal", "--name=first", "busybox", "top")
  1654  	c.Assert(waitRun("first"), check.IsNil)
  1655  	dockerCmd(c, "run", "-d", "--net=internal", "--name=second", "busybox", "top")
  1656  	c.Assert(waitRun("second"), check.IsNil)
  1657  	out, _, err := dockerCmdWithError("exec", "first", "ping", "-W", "4", "-c", "1", "www.google.com")
  1658  	c.Assert(err, check.NotNil)
  1659  	c.Assert(out, checker.Contains, "ping: bad address")
  1660  	_, _, err = dockerCmdWithError("exec", "second", "ping", "-c", "1", "first")
  1661  	c.Assert(err, check.IsNil)
  1662  }
  1663  
  1664  // Test for #21401
  1665  func (s *DockerNetworkSuite) TestDockerNetworkCreateDeleteSpecialCharacters(c *check.C) {
  1666  	dockerCmd(c, "network", "create", "test@#$")
  1667  	assertNwIsAvailable(c, "test@#$")
  1668  	dockerCmd(c, "network", "rm", "test@#$")
  1669  	assertNwNotAvailable(c, "test@#$")
  1670  
  1671  	dockerCmd(c, "network", "create", "kiwl$%^")
  1672  	assertNwIsAvailable(c, "kiwl$%^")
  1673  	dockerCmd(c, "network", "rm", "kiwl$%^")
  1674  	assertNwNotAvailable(c, "kiwl$%^")
  1675  }
  1676  
  1677  func (s *DockerDaemonSuite) TestDaemonRestartRestoreBridgeNetwork(t *check.C) {
  1678  	testRequires(t, DaemonIsLinux)
  1679  	s.d.StartWithBusybox(t, "--live-restore")
  1680  	defer s.d.Stop(t)
  1681  	oldCon := "old"
  1682  
  1683  	_, err := s.d.Cmd("run", "-d", "--name", oldCon, "-p", "80:80", "busybox", "top")
  1684  	if err != nil {
  1685  		t.Fatal(err)
  1686  	}
  1687  	oldContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", oldCon)
  1688  	if err != nil {
  1689  		t.Fatal(err)
  1690  	}
  1691  	// Kill the daemon
  1692  	if err := s.d.Kill(); err != nil {
  1693  		t.Fatal(err)
  1694  	}
  1695  
  1696  	// restart the daemon
  1697  	s.d.Start(t, "--live-restore")
  1698  
  1699  	// start a new container, the new container's ip should not be the same with
  1700  	// old running container.
  1701  	newCon := "new"
  1702  	_, err = s.d.Cmd("run", "-d", "--name", newCon, "busybox", "top")
  1703  	if err != nil {
  1704  		t.Fatal(err)
  1705  	}
  1706  	newContainerIP, err := s.d.Cmd("inspect", "-f", "{{ .NetworkSettings.Networks.bridge.IPAddress }}", newCon)
  1707  	if err != nil {
  1708  		t.Fatal(err)
  1709  	}
  1710  	if strings.Compare(strings.TrimSpace(oldContainerIP), strings.TrimSpace(newContainerIP)) == 0 {
  1711  		t.Fatalf("new container ip should not equal to old running container  ip")
  1712  	}
  1713  
  1714  	// start a new container, the new container should ping old running container
  1715  	_, err = s.d.Cmd("run", "-t", "busybox", "ping", "-c", "1", oldContainerIP)
  1716  	if err != nil {
  1717  		t.Fatal(err)
  1718  	}
  1719  
  1720  	// start a new container, trying to publish port 80:80 should fail
  1721  	out, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
  1722  	if err == nil || !strings.Contains(out, "Bind for 0.0.0.0:80 failed: port is already allocated") {
  1723  		t.Fatalf("80 port is allocated to old running container, it should failed on allocating to new container")
  1724  	}
  1725  
  1726  	// kill old running container and try to allocate again
  1727  	_, err = s.d.Cmd("kill", oldCon)
  1728  	if err != nil {
  1729  		t.Fatal(err)
  1730  	}
  1731  	id, err := s.d.Cmd("run", "-p", "80:80", "-d", "busybox", "top")
  1732  	if err != nil {
  1733  		t.Fatal(err)
  1734  	}
  1735  
  1736  	// Cleanup because these containers will not be shut down by daemon
  1737  	out, err = s.d.Cmd("stop", newCon)
  1738  	if err != nil {
  1739  		t.Fatalf("err: %v %v", err, string(out))
  1740  	}
  1741  	_, err = s.d.Cmd("stop", strings.TrimSpace(id))
  1742  	if err != nil {
  1743  		t.Fatal(err)
  1744  	}
  1745  }
  1746  
  1747  func (s *DockerNetworkSuite) TestDockerNetworkFlagAlias(c *check.C) {
  1748  	dockerCmd(c, "network", "create", "user")
  1749  	output, status := dockerCmd(c, "run", "--rm", "--network=user", "--network-alias=foo", "busybox", "true")
  1750  	c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
  1751  
  1752  	output, status, _ = dockerCmdWithError("run", "--rm", "--net=user", "--network=user", "busybox", "true")
  1753  	c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
  1754  
  1755  	output, status, _ = dockerCmdWithError("run", "--rm", "--network=user", "--net-alias=foo", "--network-alias=bar", "busybox", "true")
  1756  	c.Assert(status, checker.Equals, 0, check.Commentf("unexpected status code %d (%s)", status, output))
  1757  }
  1758  
  1759  func (s *DockerNetworkSuite) TestDockerNetworkValidateIP(c *check.C) {
  1760  	_, _, err := dockerCmdWithError("network", "create", "--ipv6", "--subnet=172.28.0.0/16", "--subnet=2001:db8:1234::/64", "mynet")
  1761  	c.Assert(err, check.IsNil)
  1762  	assertNwIsAvailable(c, "mynet")
  1763  
  1764  	_, _, err = dockerCmdWithError("run", "-d", "--name", "mynet0", "--net=mynet", "--ip", "172.28.99.88", "--ip6", "2001:db8:1234::9988", "busybox", "top")
  1765  	c.Assert(err, check.IsNil)
  1766  	c.Assert(waitRun("mynet0"), check.IsNil)
  1767  	verifyIPAddressConfig(c, "mynet0", "mynet", "172.28.99.88", "2001:db8:1234::9988")
  1768  	verifyIPAddresses(c, "mynet0", "mynet", "172.28.99.88", "2001:db8:1234::9988")
  1769  
  1770  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip", "mynet_ip", "--ip6", "2001:db8:1234::9999", "busybox", "top")
  1771  	c.Assert(err.Error(), checker.Contains, "invalid IPv4 address")
  1772  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip", "172.28.99.99", "--ip6", "mynet_ip6", "busybox", "top")
  1773  	c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
  1774  	// This is a case of IPv4 address to `--ip6`
  1775  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip6", "172.28.99.99", "busybox", "top")
  1776  	c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
  1777  	// This is a special case of an IPv4-mapped IPv6 address
  1778  	_, _, err = dockerCmdWithError("run", "--net=mynet", "--ip6", "::ffff:172.28.99.99", "busybox", "top")
  1779  	c.Assert(err.Error(), checker.Contains, "invalid IPv6 address")
  1780  }
  1781  
  1782  // Test case for 26220
  1783  func (s *DockerNetworkSuite) TestDockerNetworkDisconnectFromBridge(c *check.C) {
  1784  	out, _ := dockerCmd(c, "network", "inspect", "--format", "{{.Id}}", "bridge")
  1785  
  1786  	network := strings.TrimSpace(out)
  1787  
  1788  	name := "test"
  1789  	dockerCmd(c, "create", "--name", name, "busybox", "top")
  1790  
  1791  	_, _, err := dockerCmdWithError("network", "disconnect", network, name)
  1792  	c.Assert(err, check.IsNil)
  1793  }
  1794  
  1795  // TestConntrackFlowsLeak covers the failure scenario of ticket: https://github.com/docker/docker/issues/8795
  1796  // Validates that conntrack is correctly cleaned once a container is destroyed
  1797  func (s *DockerNetworkSuite) TestConntrackFlowsLeak(c *check.C) {
  1798  	testRequires(c, IsAmd64, DaemonIsLinux, Network)
  1799  
  1800  	// Create a new network
  1801  	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")
  1802  	assertNwIsAvailable(c, "testbind")
  1803  
  1804  	// Launch the server, this will remain listening on an exposed port and reply to any request in a ping/pong fashion
  1805  	cmd := "while true; do echo hello | nc -w 1 -lu 8080; done"
  1806  	cli.DockerCmd(c, "run", "-d", "--name", "server", "--net", "testbind", "-p", "8080:8080/udp", "appropriate/nc", "sh", "-c", cmd)
  1807  
  1808  	// Launch a container client, here the objective is to create a flow that is natted in order to expose the bug
  1809  	cmd = "echo world | nc -q 1 -u 192.168.10.1 8080"
  1810  	cli.DockerCmd(c, "run", "-d", "--name", "client", "--net=host", "appropriate/nc", "sh", "-c", cmd)
  1811  
  1812  	// Get all the flows using netlink
  1813  	flows, err := netlink.ConntrackTableList(netlink.ConntrackTable, syscall.AF_INET)
  1814  	c.Assert(err, check.IsNil)
  1815  	var flowMatch int
  1816  	for _, flow := range flows {
  1817  		// count only the flows that we are interested in, skipping others that can be laying around the host
  1818  		if flow.Forward.Protocol == syscall.IPPROTO_UDP &&
  1819  			flow.Forward.DstIP.Equal(net.ParseIP("192.168.10.1")) &&
  1820  			flow.Forward.DstPort == 8080 {
  1821  			flowMatch++
  1822  		}
  1823  	}
  1824  	// The client should have created only 1 flow
  1825  	c.Assert(flowMatch, checker.Equals, 1)
  1826  
  1827  	// Now delete the server, this will trigger the conntrack cleanup
  1828  	cli.DockerCmd(c, "rm", "-fv", "server")
  1829  
  1830  	// Fetch again all the flows and validate that there is no server flow in the conntrack laying around
  1831  	flows, err = netlink.ConntrackTableList(netlink.ConntrackTable, syscall.AF_INET)
  1832  	c.Assert(err, check.IsNil)
  1833  	flowMatch = 0
  1834  	for _, flow := range flows {
  1835  		if flow.Forward.Protocol == syscall.IPPROTO_UDP &&
  1836  			flow.Forward.DstIP.Equal(net.ParseIP("192.168.10.1")) &&
  1837  			flow.Forward.DstPort == 8080 {
  1838  			flowMatch++
  1839  		}
  1840  	}
  1841  	// All the flows have to be gone
  1842  	c.Assert(flowMatch, checker.Equals, 0)
  1843  }