github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/libnetwork/libnetwork_linux_test.go (about)

     1  package libnetwork_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"flag"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"net"
    10  	"os"
    11  	"os/exec"
    12  	"runtime"
    13  	"strconv"
    14  	"strings"
    15  	"testing"
    16  
    17  	"github.com/docker/docker/pkg/reexec"
    18  	"github.com/docker/libnetwork"
    19  	"github.com/docker/libnetwork/ipamapi"
    20  	"github.com/docker/libnetwork/netlabel"
    21  	"github.com/docker/libnetwork/options"
    22  	"github.com/docker/libnetwork/osl"
    23  	"github.com/docker/libnetwork/testutils"
    24  	"github.com/docker/libnetwork/types"
    25  	"github.com/sirupsen/logrus"
    26  	"github.com/vishvananda/netlink"
    27  	"github.com/vishvananda/netns"
    28  )
    29  
    30  func TestHost(t *testing.T) {
    31  	sbx1, err := controller.NewSandbox("host_c1",
    32  		libnetwork.OptionHostname("test1"),
    33  		libnetwork.OptionDomainname("docker.io"),
    34  		libnetwork.OptionExtraHost("web", "192.168.0.1"),
    35  		libnetwork.OptionUseDefaultSandbox())
    36  	if err != nil {
    37  		t.Fatal(err)
    38  	}
    39  	defer func() {
    40  		if err := sbx1.Delete(); err != nil {
    41  			t.Fatal(err)
    42  		}
    43  	}()
    44  
    45  	sbx2, err := controller.NewSandbox("host_c2",
    46  		libnetwork.OptionHostname("test2"),
    47  		libnetwork.OptionDomainname("docker.io"),
    48  		libnetwork.OptionExtraHost("web", "192.168.0.1"),
    49  		libnetwork.OptionUseDefaultSandbox())
    50  	if err != nil {
    51  		t.Fatal(err)
    52  	}
    53  	defer func() {
    54  		if err := sbx2.Delete(); err != nil {
    55  			t.Fatal(err)
    56  		}
    57  	}()
    58  
    59  	network, err := createTestNetwork("host", "testhost", options.Generic{}, nil, nil)
    60  	if err != nil {
    61  		t.Fatal(err)
    62  	}
    63  
    64  	ep1, err := network.CreateEndpoint("testep1")
    65  	if err != nil {
    66  		t.Fatal(err)
    67  	}
    68  
    69  	if err := ep1.Join(sbx1); err != nil {
    70  		t.Fatal(err)
    71  	}
    72  
    73  	ep2, err := network.CreateEndpoint("testep2")
    74  	if err != nil {
    75  		t.Fatal(err)
    76  	}
    77  
    78  	if err := ep2.Join(sbx2); err != nil {
    79  		t.Fatal(err)
    80  	}
    81  
    82  	if err := ep1.Leave(sbx1); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	if err := ep2.Leave(sbx2); err != nil {
    87  		t.Fatal(err)
    88  	}
    89  
    90  	if err := ep1.Delete(false); err != nil {
    91  		t.Fatal(err)
    92  	}
    93  
    94  	if err := ep2.Delete(false); err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	// Try to create another host endpoint and join/leave that.
    99  	cnt3, err := controller.NewSandbox("host_c3",
   100  		libnetwork.OptionHostname("test3"),
   101  		libnetwork.OptionDomainname("docker.io"),
   102  		libnetwork.OptionExtraHost("web", "192.168.0.1"),
   103  		libnetwork.OptionUseDefaultSandbox())
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  	defer func() {
   108  		if err := cnt3.Delete(); err != nil {
   109  			t.Fatal(err)
   110  		}
   111  	}()
   112  
   113  	ep3, err := network.CreateEndpoint("testep3")
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	if err := ep3.Join(sbx2); err != nil {
   119  		t.Fatal(err)
   120  	}
   121  
   122  	if err := ep3.Leave(sbx2); err != nil {
   123  		t.Fatal(err)
   124  	}
   125  
   126  	if err := ep3.Delete(false); err != nil {
   127  		t.Fatal(err)
   128  	}
   129  }
   130  
   131  // Testing IPV6 from MAC address
   132  func TestBridgeIpv6FromMac(t *testing.T) {
   133  	if !testutils.IsRunningInContainer() {
   134  		defer testutils.SetupTestOSContext(t)()
   135  	}
   136  
   137  	netOption := options.Generic{
   138  		netlabel.GenericData: options.Generic{
   139  			"BridgeName":         "testipv6mac",
   140  			"EnableICC":          true,
   141  			"EnableIPMasquerade": true,
   142  		},
   143  	}
   144  	ipamV4ConfList := []*libnetwork.IpamConf{{PreferredPool: "192.168.100.0/24", Gateway: "192.168.100.1"}}
   145  	ipamV6ConfList := []*libnetwork.IpamConf{{PreferredPool: "fe90::/64", Gateway: "fe90::22"}}
   146  
   147  	network, err := controller.NewNetwork(bridgeNetType, "testipv6mac", "",
   148  		libnetwork.NetworkOptionGeneric(netOption),
   149  		libnetwork.NetworkOptionEnableIPv6(true),
   150  		libnetwork.NetworkOptionIpam(ipamapi.DefaultIPAM, "", ipamV4ConfList, ipamV6ConfList, nil),
   151  		libnetwork.NetworkOptionDeferIPv6Alloc(true))
   152  	if err != nil {
   153  		t.Fatal(err)
   154  	}
   155  
   156  	mac := net.HardwareAddr{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}
   157  	epOption := options.Generic{netlabel.MacAddress: mac}
   158  
   159  	ep, err := network.CreateEndpoint("testep", libnetwork.EndpointOptionGeneric(epOption))
   160  	if err != nil {
   161  		t.Fatal(err)
   162  	}
   163  
   164  	iface := ep.Info().Iface()
   165  	if !bytes.Equal(iface.MacAddress(), mac) {
   166  		t.Fatalf("Unexpected mac address: %v", iface.MacAddress())
   167  	}
   168  
   169  	ip, expIP, _ := net.ParseCIDR("fe90::aabb:ccdd:eeff/64")
   170  	expIP.IP = ip
   171  	if !types.CompareIPNet(expIP, iface.AddressIPv6()) {
   172  		t.Fatalf("Expected %v. Got: %v", expIP, iface.AddressIPv6())
   173  	}
   174  
   175  	if err := ep.Delete(false); err != nil {
   176  		t.Fatal(err)
   177  	}
   178  
   179  	if err := network.Delete(); err != nil {
   180  		t.Fatal(err)
   181  	}
   182  }
   183  
   184  func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) {
   185  	key := info.Sandbox().Key()
   186  	sbNs, err := netns.GetFromPath(key)
   187  	if err != nil {
   188  		t.Fatalf("Failed to get network namespace path %q: %v", key, err)
   189  	}
   190  	defer sbNs.Close()
   191  
   192  	nh, err := netlink.NewHandleAt(sbNs)
   193  	if err != nil {
   194  		t.Fatal(err)
   195  	}
   196  
   197  	_, err = nh.LinkByName("eth0")
   198  	if err != nil {
   199  		t.Fatalf("Could not find the interface eth0 inside the sandbox: %v", err)
   200  	}
   201  
   202  	_, err = nh.LinkByName("eth1")
   203  	if err != nil {
   204  		t.Fatalf("Could not find the interface eth1 inside the sandbox: %v", err)
   205  	}
   206  }
   207  
   208  func TestEndpointJoin(t *testing.T) {
   209  	if !testutils.IsRunningInContainer() {
   210  		defer testutils.SetupTestOSContext(t)()
   211  	}
   212  
   213  	// Create network 1 and add 2 endpoint: ep11, ep12
   214  	netOption := options.Generic{
   215  		netlabel.GenericData: options.Generic{
   216  			"BridgeName":         "testnetwork1",
   217  			"EnableICC":          true,
   218  			"EnableIPMasquerade": true,
   219  		},
   220  	}
   221  	ipamV6ConfList := []*libnetwork.IpamConf{{PreferredPool: "fe90::/64", Gateway: "fe90::22"}}
   222  	n1, err := controller.NewNetwork(bridgeNetType, "testnetwork1", "",
   223  		libnetwork.NetworkOptionGeneric(netOption),
   224  		libnetwork.NetworkOptionEnableIPv6(true),
   225  		libnetwork.NetworkOptionIpam(ipamapi.DefaultIPAM, "", nil, ipamV6ConfList, nil),
   226  		libnetwork.NetworkOptionDeferIPv6Alloc(true))
   227  	if err != nil {
   228  		t.Fatal(err)
   229  	}
   230  	defer func() {
   231  		if err := n1.Delete(); err != nil {
   232  			t.Fatal(err)
   233  		}
   234  	}()
   235  
   236  	ep1, err := n1.CreateEndpoint("ep1")
   237  	if err != nil {
   238  		t.Fatal(err)
   239  	}
   240  	defer func() {
   241  		if err := ep1.Delete(false); err != nil {
   242  			t.Fatal(err)
   243  		}
   244  	}()
   245  
   246  	// Validate if ep.Info() only gives me IP address info and not names and gateway during CreateEndpoint()
   247  	info := ep1.Info()
   248  	iface := info.Iface()
   249  	if iface.Address() != nil && iface.Address().IP.To4() == nil {
   250  		t.Fatalf("Invalid IP address returned: %v", iface.Address())
   251  	}
   252  	if iface.AddressIPv6() != nil && iface.AddressIPv6().IP == nil {
   253  		t.Fatalf("Invalid IPv6 address returned: %v", iface.Address())
   254  	}
   255  
   256  	if len(info.Gateway()) != 0 {
   257  		t.Fatalf("Expected empty gateway for an empty endpoint. Instead found a gateway: %v", info.Gateway())
   258  	}
   259  	if len(info.GatewayIPv6()) != 0 {
   260  		t.Fatalf("Expected empty gateway for an empty ipv6 endpoint. Instead found a gateway: %v", info.GatewayIPv6())
   261  	}
   262  
   263  	if info.Sandbox() != nil {
   264  		t.Fatalf("Expected an empty sandbox key for an empty endpoint. Instead found a non-empty sandbox key: %s", info.Sandbox().Key())
   265  	}
   266  
   267  	// test invalid joins
   268  	err = ep1.Join(nil)
   269  	if err == nil {
   270  		t.Fatalf("Expected to fail join with nil Sandbox")
   271  	}
   272  	if _, ok := err.(types.BadRequestError); !ok {
   273  		t.Fatalf("Unexpected error type returned: %T", err)
   274  	}
   275  
   276  	fsbx := &fakeSandbox{}
   277  	if err = ep1.Join(fsbx); err == nil {
   278  		t.Fatalf("Expected to fail join with invalid Sandbox")
   279  	}
   280  	if _, ok := err.(types.BadRequestError); !ok {
   281  		t.Fatalf("Unexpected error type returned: %T", err)
   282  	}
   283  
   284  	sb, err := controller.NewSandbox(containerID,
   285  		libnetwork.OptionHostname("test"),
   286  		libnetwork.OptionDomainname("docker.io"),
   287  		libnetwork.OptionExtraHost("web", "192.168.0.1"))
   288  	if err != nil {
   289  		t.Fatal(err)
   290  	}
   291  
   292  	defer func() {
   293  		if err := sb.Delete(); err != nil {
   294  			t.Fatal(err)
   295  		}
   296  	}()
   297  
   298  	err = ep1.Join(sb)
   299  	if err != nil {
   300  		t.Fatal(err)
   301  	}
   302  	defer func() {
   303  		err = ep1.Leave(sb)
   304  		if err != nil {
   305  			t.Fatal(err)
   306  		}
   307  	}()
   308  
   309  	// Validate if ep.Info() only gives valid gateway and sandbox key after has container has joined.
   310  	info = ep1.Info()
   311  	if len(info.Gateway()) == 0 {
   312  		t.Fatalf("Expected a valid gateway for a joined endpoint. Instead found an invalid gateway: %v", info.Gateway())
   313  	}
   314  	if len(info.GatewayIPv6()) == 0 {
   315  		t.Fatalf("Expected a valid ipv6 gateway for a joined endpoint. Instead found an invalid gateway: %v", info.GatewayIPv6())
   316  	}
   317  
   318  	if info.Sandbox() == nil {
   319  		t.Fatalf("Expected an non-empty sandbox key for a joined endpoint. Instead found an empty sandbox key")
   320  	}
   321  
   322  	// Check endpoint provided container information
   323  	if ep1.Info().Sandbox().Key() != sb.Key() {
   324  		t.Fatalf("Endpoint Info returned unexpected sandbox key: %s", sb.Key())
   325  	}
   326  
   327  	// Attempt retrieval of endpoint interfaces statistics
   328  	stats, err := sb.Statistics()
   329  	if err != nil {
   330  		t.Fatal(err)
   331  	}
   332  	if _, ok := stats["eth0"]; !ok {
   333  		t.Fatalf("Did not find eth0 statistics")
   334  	}
   335  
   336  	// Now test the container joining another network
   337  	n2, err := createTestNetwork(bridgeNetType, "testnetwork2",
   338  		options.Generic{
   339  			netlabel.GenericData: options.Generic{
   340  				"BridgeName": "testnetwork2",
   341  			},
   342  		}, nil, nil)
   343  	if err != nil {
   344  		t.Fatal(err)
   345  	}
   346  	defer func() {
   347  		if err := n2.Delete(); err != nil {
   348  			t.Fatal(err)
   349  		}
   350  	}()
   351  
   352  	ep2, err := n2.CreateEndpoint("ep2")
   353  	if err != nil {
   354  		t.Fatal(err)
   355  	}
   356  	defer func() {
   357  		if err := ep2.Delete(false); err != nil {
   358  			t.Fatal(err)
   359  		}
   360  	}()
   361  
   362  	err = ep2.Join(sb)
   363  	if err != nil {
   364  		t.Fatal(err)
   365  	}
   366  	defer func() {
   367  		err = ep2.Leave(sb)
   368  		if err != nil {
   369  			t.Fatal(err)
   370  		}
   371  	}()
   372  
   373  	if ep1.Info().Sandbox().Key() != ep2.Info().Sandbox().Key() {
   374  		t.Fatalf("ep1 and ep2 returned different container sandbox key")
   375  	}
   376  
   377  	checkSandbox(t, info)
   378  }
   379  
   380  func TestExternalKey(t *testing.T) {
   381  	externalKeyTest(t, false)
   382  }
   383  
   384  func externalKeyTest(t *testing.T, reexec bool) {
   385  	if !testutils.IsRunningInContainer() {
   386  		defer testutils.SetupTestOSContext(t)()
   387  	}
   388  
   389  	n, err := createTestNetwork(bridgeNetType, "testnetwork", options.Generic{
   390  		netlabel.GenericData: options.Generic{
   391  			"BridgeName": "testnetwork",
   392  		},
   393  	}, nil, nil)
   394  	if err != nil {
   395  		t.Fatal(err)
   396  	}
   397  	defer func() {
   398  		if err := n.Delete(); err != nil {
   399  			t.Fatal(err)
   400  		}
   401  	}()
   402  
   403  	n2, err := createTestNetwork(bridgeNetType, "testnetwork2", options.Generic{
   404  		netlabel.GenericData: options.Generic{
   405  			"BridgeName": "testnetwork2",
   406  		},
   407  	}, nil, nil)
   408  	if err != nil {
   409  		t.Fatal(err)
   410  	}
   411  	defer func() {
   412  		if err := n2.Delete(); err != nil {
   413  			t.Fatal(err)
   414  		}
   415  	}()
   416  
   417  	ep, err := n.CreateEndpoint("ep1")
   418  	if err != nil {
   419  		t.Fatal(err)
   420  	}
   421  	defer func() {
   422  		err = ep.Delete(false)
   423  		if err != nil {
   424  			t.Fatal(err)
   425  		}
   426  	}()
   427  
   428  	ep2, err := n2.CreateEndpoint("ep2")
   429  	if err != nil {
   430  		t.Fatal(err)
   431  	}
   432  	defer func() {
   433  		err = ep2.Delete(false)
   434  		if err != nil {
   435  			t.Fatal(err)
   436  		}
   437  	}()
   438  
   439  	cnt, err := controller.NewSandbox(containerID,
   440  		libnetwork.OptionHostname("test"),
   441  		libnetwork.OptionDomainname("docker.io"),
   442  		libnetwork.OptionUseExternalKey(),
   443  		libnetwork.OptionExtraHost("web", "192.168.0.1"))
   444  	defer func() {
   445  		if err := cnt.Delete(); err != nil {
   446  			t.Fatal(err)
   447  		}
   448  		osl.GC()
   449  	}()
   450  
   451  	// Join endpoint to sandbox before SetKey
   452  	err = ep.Join(cnt)
   453  	if err != nil {
   454  		t.Fatal(err)
   455  	}
   456  	defer func() {
   457  		err = ep.Leave(cnt)
   458  		if err != nil {
   459  			t.Fatal(err)
   460  		}
   461  	}()
   462  
   463  	sbox := ep.Info().Sandbox()
   464  	if sbox == nil {
   465  		t.Fatalf("Expected to have a valid Sandbox")
   466  	}
   467  
   468  	if reexec {
   469  		err := reexecSetKey("this-must-fail", containerID, controller.ID())
   470  		if err == nil {
   471  			t.Fatalf("SetExternalKey must fail if the corresponding namespace is not created")
   472  		}
   473  	} else {
   474  		// Setting an non-existing key (namespace) must fail
   475  		if err := sbox.SetKey("this-must-fail"); err == nil {
   476  			t.Fatalf("Setkey must fail if the corresponding namespace is not created")
   477  		}
   478  	}
   479  
   480  	// Create a new OS sandbox using the osl API before using it in SetKey
   481  	if extOsBox, err := osl.NewSandbox("ValidKey", true, false); err != nil {
   482  		t.Fatalf("Failed to create new osl sandbox")
   483  	} else {
   484  		defer func() {
   485  			if err := extOsBox.Destroy(); err != nil {
   486  				logrus.Warnf("Failed to remove os sandbox: %v", err)
   487  			}
   488  		}()
   489  	}
   490  
   491  	if reexec {
   492  		err := reexecSetKey("ValidKey", containerID, controller.ID())
   493  		if err != nil {
   494  			t.Fatalf("SetExternalKey failed with %v", err)
   495  		}
   496  	} else {
   497  		if err := sbox.SetKey("ValidKey"); err != nil {
   498  			t.Fatalf("Setkey failed with %v", err)
   499  		}
   500  	}
   501  
   502  	// Join endpoint to sandbox after SetKey
   503  	err = ep2.Join(sbox)
   504  	if err != nil {
   505  		t.Fatal(err)
   506  	}
   507  	defer func() {
   508  		err = ep2.Leave(sbox)
   509  		if err != nil {
   510  			t.Fatal(err)
   511  		}
   512  	}()
   513  
   514  	if ep.Info().Sandbox().Key() != ep2.Info().Sandbox().Key() {
   515  		t.Fatalf("ep1 and ep2 returned different container sandbox key")
   516  	}
   517  
   518  	checkSandbox(t, ep.Info())
   519  }
   520  
   521  func reexecSetKey(key string, containerID string, controllerID string) error {
   522  	type libcontainerState struct {
   523  		NamespacePaths map[string]string
   524  	}
   525  	var (
   526  		state libcontainerState
   527  		b     []byte
   528  		err   error
   529  	)
   530  
   531  	state.NamespacePaths = make(map[string]string)
   532  	state.NamespacePaths["NEWNET"] = key
   533  	if b, err = json.Marshal(state); err != nil {
   534  		return err
   535  	}
   536  	cmd := &exec.Cmd{
   537  		Path:   reexec.Self(),
   538  		Args:   append([]string{"libnetwork-setkey"}, containerID, controllerID),
   539  		Stdin:  strings.NewReader(string(b)),
   540  		Stdout: os.Stdout,
   541  		Stderr: os.Stderr,
   542  	}
   543  	return cmd.Run()
   544  }
   545  
   546  func TestEnableIPv6(t *testing.T) {
   547  	if !testutils.IsRunningInContainer() {
   548  		defer testutils.SetupTestOSContext(t)()
   549  	}
   550  
   551  	tmpResolvConf := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n")
   552  	expectedResolvConf := []byte("search pommesfrites.fr\nnameserver 127.0.0.11\nnameserver 2001:4860:4860::8888\noptions ndots:0\n")
   553  	//take a copy of resolv.conf for restoring after test completes
   554  	resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf")
   555  	if err != nil {
   556  		t.Fatal(err)
   557  	}
   558  	//cleanup
   559  	defer func() {
   560  		if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
   561  			t.Fatal(err)
   562  		}
   563  	}()
   564  
   565  	netOption := options.Generic{
   566  		netlabel.EnableIPv6: true,
   567  		netlabel.GenericData: options.Generic{
   568  			"BridgeName": "testnetwork",
   569  		},
   570  	}
   571  	ipamV6ConfList := []*libnetwork.IpamConf{{PreferredPool: "fe99::/64", Gateway: "fe99::9"}}
   572  
   573  	n, err := createTestNetwork("bridge", "testnetwork", netOption, nil, ipamV6ConfList)
   574  	if err != nil {
   575  		t.Fatal(err)
   576  	}
   577  	defer func() {
   578  		if err := n.Delete(); err != nil {
   579  			t.Fatal(err)
   580  		}
   581  	}()
   582  
   583  	ep1, err := n.CreateEndpoint("ep1")
   584  	if err != nil {
   585  		t.Fatal(err)
   586  	}
   587  
   588  	if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil {
   589  		t.Fatal(err)
   590  	}
   591  
   592  	resolvConfPath := "/tmp/libnetwork_test/resolv.conf"
   593  	defer os.Remove(resolvConfPath)
   594  
   595  	sb, err := controller.NewSandbox(containerID, libnetwork.OptionResolvConfPath(resolvConfPath))
   596  	if err != nil {
   597  		t.Fatal(err)
   598  	}
   599  	defer func() {
   600  		if err := sb.Delete(); err != nil {
   601  			t.Fatal(err)
   602  		}
   603  	}()
   604  
   605  	err = ep1.Join(sb)
   606  	if err != nil {
   607  		t.Fatal(err)
   608  	}
   609  
   610  	content, err := ioutil.ReadFile(resolvConfPath)
   611  	if err != nil {
   612  		t.Fatal(err)
   613  	}
   614  
   615  	if !bytes.Equal(content, expectedResolvConf) {
   616  		t.Fatalf("Expected:\n%s\nGot:\n%s", string(expectedResolvConf), string(content))
   617  	}
   618  
   619  	if err != nil {
   620  		t.Fatal(err)
   621  	}
   622  }
   623  
   624  func TestResolvConfHost(t *testing.T) {
   625  	if !testutils.IsRunningInContainer() {
   626  		defer testutils.SetupTestOSContext(t)()
   627  	}
   628  
   629  	tmpResolvConf := []byte("search localhost.net\nnameserver 127.0.0.1\nnameserver 2001:4860:4860::8888\n")
   630  
   631  	//take a copy of resolv.conf for restoring after test completes
   632  	resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf")
   633  	if err != nil {
   634  		t.Fatal(err)
   635  	}
   636  	//cleanup
   637  	defer func() {
   638  		if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
   639  			t.Fatal(err)
   640  		}
   641  	}()
   642  
   643  	n, err := controller.NetworkByName("testhost")
   644  	if err != nil {
   645  		t.Fatal(err)
   646  	}
   647  
   648  	ep1, err := n.CreateEndpoint("ep1", libnetwork.CreateOptionDisableResolution())
   649  	if err != nil {
   650  		t.Fatal(err)
   651  	}
   652  
   653  	if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf, 0644); err != nil {
   654  		t.Fatal(err)
   655  	}
   656  
   657  	resolvConfPath := "/tmp/libnetwork_test/resolv.conf"
   658  	defer os.Remove(resolvConfPath)
   659  
   660  	sb, err := controller.NewSandbox(containerID,
   661  		libnetwork.OptionUseDefaultSandbox(),
   662  		libnetwork.OptionResolvConfPath(resolvConfPath),
   663  		libnetwork.OptionOriginResolvConfPath("/etc/resolv.conf"))
   664  	if err != nil {
   665  		t.Fatal(err)
   666  	}
   667  	defer func() {
   668  		if err := sb.Delete(); err != nil {
   669  			t.Fatal(err)
   670  		}
   671  	}()
   672  
   673  	err = ep1.Join(sb)
   674  	if err != nil {
   675  		t.Fatal(err)
   676  	}
   677  	defer func() {
   678  		err = ep1.Leave(sb)
   679  		if err != nil {
   680  			t.Fatal(err)
   681  		}
   682  	}()
   683  
   684  	finfo, err := os.Stat(resolvConfPath)
   685  	if err != nil {
   686  		t.Fatal(err)
   687  	}
   688  
   689  	fmode := (os.FileMode)(0644)
   690  	if finfo.Mode() != fmode {
   691  		t.Fatalf("Expected file mode %s, got %s", fmode.String(), finfo.Mode().String())
   692  	}
   693  
   694  	content, err := ioutil.ReadFile(resolvConfPath)
   695  	if err != nil {
   696  		t.Fatal(err)
   697  	}
   698  
   699  	if !bytes.Equal(content, tmpResolvConf) {
   700  		t.Fatalf("Expected:\n%s\nGot:\n%s", string(tmpResolvConf), string(content))
   701  	}
   702  }
   703  
   704  func TestResolvConf(t *testing.T) {
   705  	if !testutils.IsRunningInContainer() {
   706  		defer testutils.SetupTestOSContext(t)()
   707  	}
   708  
   709  	tmpResolvConf1 := []byte("search pommesfrites.fr\nnameserver 12.34.56.78\nnameserver 2001:4860:4860::8888\n")
   710  	tmpResolvConf2 := []byte("search pommesfrites.fr\nnameserver 112.34.56.78\nnameserver 2001:4860:4860::8888\n")
   711  	expectedResolvConf1 := []byte("search pommesfrites.fr\nnameserver 127.0.0.11\noptions ndots:0\n")
   712  	tmpResolvConf3 := []byte("search pommesfrites.fr\nnameserver 113.34.56.78\n")
   713  
   714  	//take a copy of resolv.conf for restoring after test completes
   715  	resolvConfSystem, err := ioutil.ReadFile("/etc/resolv.conf")
   716  	if err != nil {
   717  		t.Fatal(err)
   718  	}
   719  	//cleanup
   720  	defer func() {
   721  		if err := ioutil.WriteFile("/etc/resolv.conf", resolvConfSystem, 0644); err != nil {
   722  			t.Fatal(err)
   723  		}
   724  	}()
   725  
   726  	netOption := options.Generic{
   727  		netlabel.GenericData: options.Generic{
   728  			"BridgeName": "testnetwork",
   729  		},
   730  	}
   731  	n, err := createTestNetwork("bridge", "testnetwork", netOption, nil, nil)
   732  	if err != nil {
   733  		t.Fatal(err)
   734  	}
   735  	defer func() {
   736  		if err := n.Delete(); err != nil {
   737  			t.Fatal(err)
   738  		}
   739  	}()
   740  
   741  	ep, err := n.CreateEndpoint("ep")
   742  	if err != nil {
   743  		t.Fatal(err)
   744  	}
   745  
   746  	if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf1, 0644); err != nil {
   747  		t.Fatal(err)
   748  	}
   749  
   750  	resolvConfPath := "/tmp/libnetwork_test/resolv.conf"
   751  	defer os.Remove(resolvConfPath)
   752  
   753  	sb1, err := controller.NewSandbox(containerID, libnetwork.OptionResolvConfPath(resolvConfPath))
   754  	if err != nil {
   755  		t.Fatal(err)
   756  	}
   757  	defer func() {
   758  		if err := sb1.Delete(); err != nil {
   759  			t.Fatal(err)
   760  		}
   761  	}()
   762  
   763  	err = ep.Join(sb1)
   764  	if err != nil {
   765  		t.Fatal(err)
   766  	}
   767  
   768  	finfo, err := os.Stat(resolvConfPath)
   769  	if err != nil {
   770  		t.Fatal(err)
   771  	}
   772  
   773  	fmode := (os.FileMode)(0644)
   774  	if finfo.Mode() != fmode {
   775  		t.Fatalf("Expected file mode %s, got %s", fmode.String(), finfo.Mode().String())
   776  	}
   777  
   778  	content, err := ioutil.ReadFile(resolvConfPath)
   779  	if err != nil {
   780  		t.Fatal(err)
   781  	}
   782  
   783  	if !bytes.Equal(content, expectedResolvConf1) {
   784  		fmt.Printf("\n%v\n%v\n", expectedResolvConf1, content)
   785  		t.Fatalf("Expected:\n%s\nGot:\n%s", string(expectedResolvConf1), string(content))
   786  	}
   787  
   788  	err = ep.Leave(sb1)
   789  	if err != nil {
   790  		t.Fatal(err)
   791  	}
   792  
   793  	if err := ioutil.WriteFile("/etc/resolv.conf", tmpResolvConf2, 0644); err != nil {
   794  		t.Fatal(err)
   795  	}
   796  
   797  	sb2, err := controller.NewSandbox(containerID+"_2", libnetwork.OptionResolvConfPath(resolvConfPath))
   798  	if err != nil {
   799  		t.Fatal(err)
   800  	}
   801  	defer func() {
   802  		if err := sb2.Delete(); err != nil {
   803  			t.Fatal(err)
   804  		}
   805  	}()
   806  
   807  	err = ep.Join(sb2)
   808  	if err != nil {
   809  		t.Fatal(err)
   810  	}
   811  
   812  	content, err = ioutil.ReadFile(resolvConfPath)
   813  	if err != nil {
   814  		t.Fatal(err)
   815  	}
   816  
   817  	if !bytes.Equal(content, expectedResolvConf1) {
   818  		t.Fatalf("Expected:\n%s\nGot:\n%s", string(expectedResolvConf1), string(content))
   819  	}
   820  
   821  	if err := ioutil.WriteFile(resolvConfPath, tmpResolvConf3, 0644); err != nil {
   822  		t.Fatal(err)
   823  	}
   824  
   825  	err = ep.Leave(sb2)
   826  	if err != nil {
   827  		t.Fatal(err)
   828  	}
   829  
   830  	err = ep.Join(sb2)
   831  	if err != nil {
   832  		t.Fatal(err)
   833  	}
   834  
   835  	content, err = ioutil.ReadFile(resolvConfPath)
   836  	if err != nil {
   837  		t.Fatal(err)
   838  	}
   839  
   840  	if !bytes.Equal(content, tmpResolvConf3) {
   841  		t.Fatalf("Expected:\n%s\nGot:\n%s", string(tmpResolvConf3), string(content))
   842  	}
   843  }
   844  
   845  func parallelJoin(t *testing.T, rc libnetwork.Sandbox, ep libnetwork.Endpoint, thrNumber int) {
   846  	debugf("J%d.", thrNumber)
   847  	var err error
   848  
   849  	sb := sboxes[thrNumber-1]
   850  	err = ep.Join(sb)
   851  
   852  	runtime.LockOSThread()
   853  	if err != nil {
   854  		if _, ok := err.(types.ForbiddenError); !ok {
   855  			t.Fatalf("thread %d: %v", thrNumber, err)
   856  		}
   857  		debugf("JE%d(%v).", thrNumber, err)
   858  	}
   859  	debugf("JD%d.", thrNumber)
   860  }
   861  
   862  func parallelLeave(t *testing.T, rc libnetwork.Sandbox, ep libnetwork.Endpoint, thrNumber int) {
   863  	debugf("L%d.", thrNumber)
   864  	var err error
   865  
   866  	sb := sboxes[thrNumber-1]
   867  
   868  	err = ep.Leave(sb)
   869  	runtime.LockOSThread()
   870  	if err != nil {
   871  		if _, ok := err.(types.ForbiddenError); !ok {
   872  			t.Fatalf("thread %d: %v", thrNumber, err)
   873  		}
   874  		debugf("LE%d(%v).", thrNumber, err)
   875  	}
   876  	debugf("LD%d.", thrNumber)
   877  }
   878  
   879  func runParallelTests(t *testing.T, thrNumber int) {
   880  	var (
   881  		ep  libnetwork.Endpoint
   882  		sb  libnetwork.Sandbox
   883  		err error
   884  	)
   885  
   886  	t.Parallel()
   887  
   888  	pTest := flag.Lookup("test.parallel")
   889  	if pTest == nil {
   890  		t.Skip("Skipped because test.parallel flag not set;")
   891  	}
   892  	numParallel, err := strconv.Atoi(pTest.Value.String())
   893  	if err != nil {
   894  		t.Fatal(err)
   895  	}
   896  	if numParallel < numThreads {
   897  		t.Skip("Skipped because t.parallel was less than ", numThreads)
   898  	}
   899  
   900  	runtime.LockOSThread()
   901  	defer runtime.UnlockOSThread()
   902  
   903  	if thrNumber == first {
   904  		createGlobalInstance(t)
   905  	}
   906  
   907  	if thrNumber != first {
   908  		<-start
   909  
   910  		thrdone := make(chan struct{})
   911  		done <- thrdone
   912  		defer close(thrdone)
   913  
   914  		if thrNumber == last {
   915  			defer close(done)
   916  		}
   917  
   918  		err = netns.Set(testns)
   919  		if err != nil {
   920  			t.Fatal(err)
   921  		}
   922  	}
   923  	defer netns.Set(origins)
   924  
   925  	net1, err := controller.NetworkByName("testhost")
   926  	if err != nil {
   927  		t.Fatal(err)
   928  	}
   929  	if net1 == nil {
   930  		t.Fatal("Could not find testhost")
   931  	}
   932  
   933  	net2, err := controller.NetworkByName("network2")
   934  	if err != nil {
   935  		t.Fatal(err)
   936  	}
   937  	if net2 == nil {
   938  		t.Fatal("Could not find network2")
   939  	}
   940  
   941  	epName := fmt.Sprintf("pep%d", thrNumber)
   942  
   943  	if thrNumber == first {
   944  		ep, err = net1.EndpointByName(epName)
   945  	} else {
   946  		ep, err = net2.EndpointByName(epName)
   947  	}
   948  
   949  	if err != nil {
   950  		t.Fatal(err)
   951  	}
   952  	if ep == nil {
   953  		t.Fatal("Got nil ep with no error")
   954  	}
   955  
   956  	cid := fmt.Sprintf("%drace", thrNumber)
   957  	controller.WalkSandboxes(libnetwork.SandboxContainerWalker(&sb, cid))
   958  	if sb == nil {
   959  		t.Fatalf("Got nil sandbox for container: %s", cid)
   960  	}
   961  
   962  	for i := 0; i < iterCnt; i++ {
   963  		parallelJoin(t, sb, ep, thrNumber)
   964  		parallelLeave(t, sb, ep, thrNumber)
   965  	}
   966  
   967  	debugf("\n")
   968  
   969  	err = sb.Delete()
   970  	if err != nil {
   971  		t.Fatal(err)
   972  	}
   973  	if thrNumber == first {
   974  		for thrdone := range done {
   975  			<-thrdone
   976  		}
   977  
   978  		testns.Close()
   979  		if err := net2.Delete(); err != nil {
   980  			t.Fatal(err)
   981  		}
   982  	} else {
   983  		err = ep.Delete(false)
   984  		if err != nil {
   985  			t.Fatal(err)
   986  		}
   987  	}
   988  }
   989  
   990  func TestParallel1(t *testing.T) {
   991  	runParallelTests(t, 1)
   992  }
   993  
   994  func TestParallel2(t *testing.T) {
   995  	runParallelTests(t, 2)
   996  }
   997  
   998  func TestParallel3(t *testing.T) {
   999  	runParallelTests(t, 3)
  1000  }
  1001  
  1002  func TestNullIpam(t *testing.T) {
  1003  	_, err := controller.NewNetwork(bridgeNetType, "testnetworkinternal", "", libnetwork.NetworkOptionIpam(ipamapi.NullIPAM, "", nil, nil, nil))
  1004  	if err == nil || err.Error() != "ipv4 pool is empty" {
  1005  		t.Fatal("bridge network should complain empty pool")
  1006  	}
  1007  }