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