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