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