From e0f1ac4b2ed87a45d5177b2ffc4adc58acda6bdf Mon Sep 17 00:00:00 2001 From: Alessandro Boch Date: Thu, 15 Oct 2015 14:41:07 -0700 Subject: [PATCH] Fix ipam state cleanup logic - Got accidentally broken by another commit Signed-off-by: Alessandro Boch --- libnetwork/controller.go | 2 +- libnetwork/libnetwork_internal_test.go | 103 +++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/libnetwork/controller.go b/libnetwork/controller.go index 18fa883bf3..c7f0cd2c6b 100644 --- a/libnetwork/controller.go +++ b/libnetwork/controller.go @@ -356,7 +356,7 @@ func (c *controller) NewNetwork(networkType, name string, options ...NetworkOpti } }() - if err := c.addNetwork(network); err != nil { + if err = c.addNetwork(network); err != nil { return nil, err } defer func() { diff --git a/libnetwork/libnetwork_internal_test.go b/libnetwork/libnetwork_internal_test.go index 2847a5b3fc..33104d573c 100644 --- a/libnetwork/libnetwork_internal_test.go +++ b/libnetwork/libnetwork_internal_test.go @@ -6,9 +6,11 @@ import ( "net" "testing" + "github.com/docker/libnetwork/datastore" "github.com/docker/libnetwork/driverapi" "github.com/docker/libnetwork/ipamapi" "github.com/docker/libnetwork/netlabel" + "github.com/docker/libnetwork/testutils" "github.com/docker/libnetwork/types" ) @@ -328,3 +330,104 @@ func TestAuxAddresses(t *testing.T) { n.ipamRelease() } } + +func TestIpamReleaseOnNetDriverFailures(t *testing.T) { + if !testutils.IsRunningInContainer() { + defer testutils.SetupTestOSContext(t)() + } + + cfgOptions, err := OptionBoltdbWithRandomDBFile() + c, err := New(cfgOptions...) + if err != nil { + t.Fatal(err) + } + defer c.Stop() + + cc := c.(*controller) + bd := badDriver{failNetworkCreation: true} + cc.drivers[badDriverName] = &driverData{driver: &bd, capability: driverapi.Capability{DataScope: datastore.LocalScope}} + + // Test whether ipam state release is invoked on network create failure from net driver + // by checking whether subsequent network creation requesting same gateway IP succeeds + ipamOpt := NetworkOptionIpam(ipamapi.DefaultIPAM, "", []*IpamConf{&IpamConf{PreferredPool: "10.34.0.0/16", Gateway: "10.34.255.254"}}, nil) + if _, err := c.NewNetwork(badDriverName, "badnet1", ipamOpt); err == nil { + t.Fatalf("bad network driver should have failed network creation") + } + + gnw, err := c.NewNetwork("bridge", "goodnet1", ipamOpt) + if err != nil { + t.Fatal(err) + } + gnw.Delete() + + // Now check whether ipam release works on endpoint creation failure + bd.failNetworkCreation = false + bnw, err := c.NewNetwork(badDriverName, "badnet2", ipamOpt) + if err != nil { + t.Fatal(err) + } + defer bnw.Delete() + + if _, err := bnw.CreateEndpoint("ep0"); err == nil { + t.Fatalf("bad network driver should have failed endpoint creation") + } + + // Now create good bridge network with different gateway + ipamOpt2 := NetworkOptionIpam(ipamapi.DefaultIPAM, "", []*IpamConf{&IpamConf{PreferredPool: "10.34.0.0/16", Gateway: "10.34.255.253"}}, nil) + gnw, err = c.NewNetwork("bridge", "goodnet2", ipamOpt2) + if err != nil { + t.Fatal(err) + } + defer gnw.Delete() + + ep, err := gnw.CreateEndpoint("ep1") + if err != nil { + t.Fatal(err) + } + defer ep.Delete() + + expectedIP, _ := types.ParseCIDR("10.34.0.1/16") + if !types.CompareIPNet(ep.Info().Iface().Address(), expectedIP) { + t.Fatalf("Ipam release must have failed, endpoint has unexpected address: %v", ep.Info().Iface().Address()) + } +} + +var badDriverName = "bad network driver" + +type badDriver struct { + failNetworkCreation bool +} + +func (b *badDriver) CreateNetwork(nid string, options map[string]interface{}, ipV4Data, ipV6Data []driverapi.IPAMData) error { + if b.failNetworkCreation { + return fmt.Errorf("I will not create any network") + } + return nil +} +func (b *badDriver) DeleteNetwork(nid string) error { + return nil +} +func (b *badDriver) CreateEndpoint(nid, eid string, ifInfo driverapi.InterfaceInfo, options map[string]interface{}) error { + return fmt.Errorf("I will not create any endpoint") +} +func (b *badDriver) DeleteEndpoint(nid, eid string) error { + return nil +} +func (b *badDriver) EndpointOperInfo(nid, eid string) (map[string]interface{}, error) { + return nil, nil +} +func (b *badDriver) Join(nid, eid string, sboxKey string, jinfo driverapi.JoinInfo, options map[string]interface{}) error { + return fmt.Errorf("I will not allow any join") +} +func (b *badDriver) Leave(nid, eid string) error { + return nil +} +func (b *badDriver) DiscoverNew(dType driverapi.DiscoveryType, data interface{}) error { + return nil +} +func (b *badDriver) DiscoverDelete(dType driverapi.DiscoveryType, data interface{}) error { + return nil +} +func (b *badDriver) Type() string { + return badDriverName +}