Skip to content

Commit 4986e71

Browse files
authored
Contiv network is not deleted when docker network is deleted (#1029)
* Contiv network is not deleted when docker network is deleted Steps to reproduce: 1. Create a docker network with docker network CLI 2. Ensure docker network and contiv network are created (docker network ls and netctl network ls) 3. Remove docker network. 4. Check docker network ls, docker network is deleted 5. Check netctl networ ls, contiv network is still test. The root cause is due to the dockernetworkstate mapping is planned to delete after contiv network is delete. However, the determination of contiv network deletion is determined by the existance of the dockernetworkstate. Thefore, if the state is still there, the contiv network will be unable to delete. The fix is to delete the dockernetworkstate before proceed to contiv network deletion Signed-off-by: Kahou Lei [email protected] * Print out error * Add unit test and also refactor some code to make the code more testable. * Add more unit test and fix typos * Add more testing * Add key value pair in fake state * Refactor base on comments * Add more check in unit test. Take out return statement when docker network is not there.
1 parent 56fb48a commit 4986e71

File tree

5 files changed

+136
-22
lines changed

5 files changed

+136
-22
lines changed

mgmtfn/dockplugin/netDriver.go

+23-13
Original file line numberDiff line numberDiff line change
@@ -742,10 +742,27 @@ func createNetworkHelper(networkID string, tag string, IPv4Data, IPv6Data []driv
742742
return nil
743743
}
744744

745-
// deleteNetworkHelper removes the association between docker network and contiv network
745+
// deleteNetworkHelper removes the association between docker network
746+
// and contiv network. We have to remove docker network state before
747+
// remove network in contiv.
746748
func deleteNetworkHelper(networkID string) error {
749+
dnet, err := docknet.FindDocknetByUUID(networkID)
750+
if err == nil {
751+
// delete the dnet oper state
752+
err = docknet.DeleteDockNetState(dnet.TenantName, dnet.NetworkName, dnet.ServiceName)
753+
if err != nil {
754+
msg := fmt.Sprintf("Could not delete docknet for nwID %s: %s", networkID, err.Error())
755+
log.Errorf(msg)
756+
return errors.New(msg)
757+
}
758+
log.Infof("Deleted docker network mapping for %v", networkID)
759+
} else {
760+
msg := fmt.Sprintf("Could not find Docker network %s: %s", networkID, err.Error())
761+
log.Errorf(msg)
762+
}
763+
747764
netID := networkID + ".default"
748-
_, err := utils.GetNetwork(netID)
765+
_, err = utils.GetNetwork(netID)
749766
if err == nil {
750767
// if we find a contiv network with the ID hash, then it must be
751768
// a docker created network (from the libnetwork create api).
@@ -755,21 +772,14 @@ func deleteNetworkHelper(networkID string) error {
755772

756773
err = cluster.MasterDelReq(url)
757774
if err != nil {
758-
log.Errorf("Failed to delete network: %s", err.Error())
759-
return errors.New("Failed to delete network")
775+
msg := fmt.Sprintf("Failed to delete network: %s", err.Error())
776+
log.Errorf(msg)
777+
return errors.New(msg)
760778
}
761779
log.Infof("Deleted contiv network %v", networkID)
762780
} else {
763781
log.Infof("Could not find contiv network %v", networkID)
764782
}
765-
dnet, err := docknet.FindDocknetByUUID(networkID)
766-
if err == nil {
767-
// delete the dnet oper state
768-
err = docknet.DeleteDockNetState(dnet.TenantName, dnet.NetworkName, dnet.ServiceName)
769-
if err != nil {
770-
log.Errorf("Couldn't delete docknet for nwID %s", networkID)
771-
}
772-
log.Infof("Deleted docker network mapping for %v", networkID)
773-
}
783+
774784
return nil
775785
}

mgmtfn/dockplugin/netDriver_test.go

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package dockplugin
2+
3+
import (
4+
"fmt"
5+
"github.com/contiv/netplugin/core"
6+
"github.com/contiv/netplugin/netmaster/docknet"
7+
"github.com/contiv/netplugin/netmaster/mastercfg"
8+
"github.com/contiv/netplugin/state"
9+
"github.com/contiv/netplugin/utils"
10+
"testing"
11+
)
12+
13+
var stateDriver *state.FakeStateDriver
14+
15+
// initStateDriver initialize etcd state driver
16+
func initFakeStateDriver(t *testing.T) {
17+
instInfo := core.InstanceInfo{}
18+
d, err := utils.NewStateDriver("fakedriver", &instInfo)
19+
if err != nil {
20+
t.Fatalf("failed to init statedriver. Error: %s", err)
21+
t.Fail()
22+
}
23+
stateDriver = d.(*state.FakeStateDriver)
24+
}
25+
26+
func deinitStateDriver() {
27+
utils.ReleaseStateDriver()
28+
}
29+
30+
// Ensure deleteNetworkHelper can delete docker network without issue
31+
func TestCreateAndDeleteNetwork(t *testing.T) {
32+
// Update plugin driver for unit test
33+
docknet.UpdateDockerV2PluginName("bridge", "default")
34+
35+
initFakeStateDriver(t)
36+
defer deinitStateDriver()
37+
38+
tenantName := "t1"
39+
networkName := "net1"
40+
serviceName := ""
41+
nwcfg := mastercfg.CfgNetworkState{
42+
Tenant: tenantName,
43+
NetworkName: networkName,
44+
PktTagType: "vlan",
45+
PktTag: 1,
46+
ExtPktTag: 1,
47+
SubnetIP: "10.0.0.0",
48+
SubnetLen: 24,
49+
Gateway: "10.0.0.1",
50+
}
51+
52+
err := docknet.CreateDockNet(tenantName, networkName, "", &nwcfg)
53+
if err != nil {
54+
t.Fatalf("Error creating docker network. Error: %v", err)
55+
t.Fail()
56+
}
57+
58+
// Get Docker network UUID
59+
dnetOper := docknet.DnetOperState{}
60+
dnetOper.StateDriver = stateDriver
61+
62+
err = dnetOper.Read(fmt.Sprintf("%s.%s.%s", tenantName, networkName, serviceName))
63+
if err != nil {
64+
t.Fatalf("Unable to read network state. Error: %v", err)
65+
t.Fail()
66+
}
67+
68+
testData := make([]byte, 3)
69+
networkID := mastercfg.StateConfigPath + "nets/" + dnetOper.DocknetUUID + ".default"
70+
dnetOper.StateDriver.Write(networkID, testData)
71+
72+
// Delete Docker network by using helper
73+
err = deleteNetworkHelper(dnetOper.DocknetUUID)
74+
75+
if err != nil {
76+
t.Fatalf("Unable to delete docker network. Error: %v", err)
77+
t.Fail()
78+
}
79+
80+
// ensure network is not in the oper state
81+
err = dnetOper.Read(fmt.Sprintf("%s.%s.%s", tenantName, networkName, serviceName))
82+
if err == nil {
83+
t.Fatalf("Fail to delete docket network")
84+
t.Fail()
85+
}
86+
}

netmaster/docknet/docknet.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@ func GetDocknetName(tenantName, networkName, epgName string) string {
101101
return netName
102102
}
103103

104-
// UpdatePluginName update the docker v2 plugin name
105-
func UpdatePluginName(pluginName string) {
106-
log.Infof("docker v2plugin name (%s) updated to %s", netDriverName, pluginName)
107-
netDriverName = pluginName
108-
ipamDriverName = pluginName
104+
// UpdateDockerV2PluginName update the docker v2 plugin name
105+
func UpdateDockerV2PluginName(netDriver string, ipamDriver string) {
106+
log.Infof("docker v2plugin (%s) updated to %s and ipam (%s) updated to %s",
107+
netDriverName, netDriver, ipamDriverName, ipamDriver)
108+
netDriverName = netDriver
109+
ipamDriverName = ipamDriver
109110
}
110111

111112
// CreateDockNet Creates a network in docker daemon

netmaster/docknet/docknet_test.go

+20-3
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func checkDocknetCreate(t *testing.T, tenantName, networkName, serviceName, subn
7676
// create a docker network
7777
err := CreateDockNet(tenantName, networkName, serviceName, &nwcfg)
7878
if err != nil {
79-
t.Fatalf("Error creating docker ntework. Err: %v", err)
79+
t.Fatalf("Error creating docker network. Err: %v", err)
8080
}
8181

8282
// verify docknet state is created
@@ -204,8 +204,7 @@ func checkDocknetDelete(t *testing.T, tenantName, networkName, serviceName strin
204204

205205
func TestMain(m *testing.M) {
206206
// change driver names for unit-testing
207-
netDriverName = "bridge"
208-
ipamDriverName = "default"
207+
UpdateDockerV2PluginName("bridge", "default")
209208

210209
initStateDriver()
211210

@@ -225,3 +224,21 @@ func TestDocknetCreateDelete(t *testing.T) {
225224
checkDocknetCreate(t, "unit-test", "net1", "srv1", "10.1.1.1/24", "10.1.1.254")
226225
checkDocknetDelete(t, "unit-test", "net1", "srv1")
227226
}
227+
228+
func TestUpdateDockerV2PluginName(t *testing.T) {
229+
expectNetDriver := "bridge"
230+
expectIPAMDriver := "default"
231+
UpdateDockerV2PluginName("bridge", "default")
232+
233+
if expectNetDriver != netDriverName {
234+
t.Fatalf("Unexpected netdriver name. Expected: %s. Actual: %s",
235+
expectNetDriver, netDriverName)
236+
t.Fail()
237+
}
238+
239+
if expectIPAMDriver != ipamDriverName {
240+
t.Fatalf("Unexpected ipamdriver name. Expected: %s. Actual: %s",
241+
expectIPAMDriver, ipamDriverName)
242+
t.Fail()
243+
}
244+
}

netmaster/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ func execOpts(opts *cliOpts) {
155155
log.Infof("Control IP:Port %s:%s", controlIP, controlURL[1])
156156

157157
if opts.clusterMode == master.Docker || opts.clusterMode == master.SwarmMode {
158-
docknet.UpdatePluginName(opts.pluginName)
158+
docknet.UpdateDockerV2PluginName(opts.pluginName, opts.pluginName)
159159
}
160160
}
161161

0 commit comments

Comments
 (0)