Skip to content

Contiv network is not deleted when docker network is deleted #1029

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Oct 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions mgmtfn/dockplugin/netDriver.go
Original file line number Diff line number Diff line change
Expand Up @@ -742,10 +742,27 @@ func createNetworkHelper(networkID string, tag string, IPv4Data, IPv6Data []driv
return nil
}

// deleteNetworkHelper removes the association between docker network and contiv network
// deleteNetworkHelper removes the association between docker network
// and contiv network. We have to remove docker network state before
// remove network in contiv.
func deleteNetworkHelper(networkID string) error {
dnet, err := docknet.FindDocknetByUUID(networkID)
if err == nil {
// delete the dnet oper state
err = docknet.DeleteDockNetState(dnet.TenantName, dnet.NetworkName, dnet.ServiceName)
if err != nil {
msg := fmt.Sprintf("Could not delete docknet for nwID %s: %s", networkID, err.Error())
log.Errorf(msg)
return errors.New(msg)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another way to simplify,

err := fmt.Errorf()
log.Error(err)
return err

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to stick with the current implementation

}
log.Infof("Deleted docker network mapping for %v", networkID)
} else {
msg := fmt.Sprintf("Could not find Docker network %s: %s", networkID, err.Error())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fmt package takes care of calling Error()
fmt.Sprintf("xxx %s", err)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to stick with the current implementation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i understand now that due to other bad behavior (not erroring in v2plugin mode when requesting to create the network) that we can get out of sync, I'm just looking for a ticket to block the netctl when in v2plugin mode, then we can clean up this lax behavior here

log.Errorf(msg)
}

netID := networkID + ".default"
_, err := utils.GetNetwork(netID)
_, err = utils.GetNetwork(netID)
if err == nil {
// if we find a contiv network with the ID hash, then it must be
// a docker created network (from the libnetwork create api).
Expand All @@ -755,21 +772,14 @@ func deleteNetworkHelper(networkID string) error {

err = cluster.MasterDelReq(url)
if err != nil {
log.Errorf("Failed to delete network: %s", err.Error())
return errors.New("Failed to delete network")
msg := fmt.Sprintf("Failed to delete network: %s", err.Error())
log.Errorf(msg)
return errors.New(msg)
}
log.Infof("Deleted contiv network %v", networkID)
} else {
log.Infof("Could not find contiv network %v", networkID)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should still be bubbling up an error here (like bad request to user for deleting a network that didn't exist), but happy to see this as a new ticket

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, I don't think return error here will bubbling up to the docker network create command. We have to have another ticket to investigate it.

}
dnet, err := docknet.FindDocknetByUUID(networkID)
if err == nil {
// delete the dnet oper state
err = docknet.DeleteDockNetState(dnet.TenantName, dnet.NetworkName, dnet.ServiceName)
if err != nil {
log.Errorf("Couldn't delete docknet for nwID %s", networkID)
}
log.Infof("Deleted docker network mapping for %v", networkID)
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we deleted docker network, found a contiv netowrk, but failed to delete the contiv netowrk, should we restore the docker network? (i dunno, just asking) . . L771

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no hook for me to do that at the moment to restore the network.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't think we must secretly revert what the user does (docker network rm in this case). If contiv network deletion fails, I think an error to the user is good instead of reverting what the user did.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

return nil
}
86 changes: 86 additions & 0 deletions mgmtfn/dockplugin/netDriver_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package dockplugin

import (
"fmt"
"github.com/contiv/netplugin/core"
"github.com/contiv/netplugin/netmaster/docknet"
"github.com/contiv/netplugin/netmaster/mastercfg"
"github.com/contiv/netplugin/state"
"github.com/contiv/netplugin/utils"
"testing"
)

var stateDriver *state.FakeStateDriver

// initStateDriver initialize etcd state driver
func initFakeStateDriver(t *testing.T) {
instInfo := core.InstanceInfo{}
d, err := utils.NewStateDriver("fakedriver", &instInfo)
if err != nil {
t.Fatalf("failed to init statedriver. Error: %s", err)
t.Fail()
}
stateDriver = d.(*state.FakeStateDriver)
}

func deinitStateDriver() {
utils.ReleaseStateDriver()
}

// Ensure deleteNetworkHelper can delete docker network without issue
func TestCreateAndDeleteNetwork(t *testing.T) {
// Update plugin driver for unit test
docknet.UpdateDockerV2PluginName("bridge", "default")

initFakeStateDriver(t)
defer deinitStateDriver()

tenantName := "t1"
networkName := "net1"
serviceName := ""
nwcfg := mastercfg.CfgNetworkState{
Tenant: tenantName,
NetworkName: networkName,
PktTagType: "vlan",
PktTag: 1,
ExtPktTag: 1,
SubnetIP: "10.0.0.0",
SubnetLen: 24,
Gateway: "10.0.0.1",
}

err := docknet.CreateDockNet(tenantName, networkName, "", &nwcfg)
if err != nil {
t.Fatalf("Error creating docker network. Error: %v", err)
t.Fail()
}

// Get Docker network UUID
dnetOper := docknet.DnetOperState{}
dnetOper.StateDriver = stateDriver

err = dnetOper.Read(fmt.Sprintf("%s.%s.%s", tenantName, networkName, serviceName))
if err != nil {
t.Fatalf("Unable to read network state. Error: %v", err)
t.Fail()
}

testData := make([]byte, 3)
networkID := mastercfg.StateConfigPath + "nets/" + dnetOper.DocknetUUID + ".default"
dnetOper.StateDriver.Write(networkID, testData)

// Delete Docker network by using helper
err = deleteNetworkHelper(dnetOper.DocknetUUID)

if err != nil {
t.Fatalf("Unable to delete docker network. Error: %v", err)
t.Fail()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checking the return is non-error is good, but that didn't actually test that the network was deleted, can you check w/ docker/netctl for current status?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


// ensure network is not in the oper state
err = dnetOper.Read(fmt.Sprintf("%s.%s.%s", tenantName, networkName, serviceName))
if err == nil {
t.Fatalf("Fail to delete docket network")
t.Fail()
}
}
11 changes: 6 additions & 5 deletions netmaster/docknet/docknet.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,12 @@ func GetDocknetName(tenantName, networkName, epgName string) string {
return netName
}

// UpdatePluginName update the docker v2 plugin name
func UpdatePluginName(pluginName string) {
log.Infof("docker v2plugin name (%s) updated to %s", netDriverName, pluginName)
netDriverName = pluginName
ipamDriverName = pluginName
// UpdateDockerV2PluginName update the docker v2 plugin name
func UpdateDockerV2PluginName(netDriver string, ipamDriver string) {
log.Infof("docker v2plugin (%s) updated to %s and ipam (%s) updated to %s",
netDriverName, netDriver, ipamDriverName, ipamDriver)
netDriverName = netDriver
ipamDriverName = ipamDriver
}

// CreateDockNet Creates a network in docker daemon
Expand Down
23 changes: 20 additions & 3 deletions netmaster/docknet/docknet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func checkDocknetCreate(t *testing.T, tenantName, networkName, serviceName, subn
// create a docker network
err := CreateDockNet(tenantName, networkName, serviceName, &nwcfg)
if err != nil {
t.Fatalf("Error creating docker ntework. Err: %v", err)
t.Fatalf("Error creating docker network. Err: %v", err)
}

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

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

initStateDriver()

Expand All @@ -225,3 +224,21 @@ func TestDocknetCreateDelete(t *testing.T) {
checkDocknetCreate(t, "unit-test", "net1", "srv1", "10.1.1.1/24", "10.1.1.254")
checkDocknetDelete(t, "unit-test", "net1", "srv1")
}

func TestUpdateDockerV2PluginName(t *testing.T) {
expectNetDriver := "bridge"
expectIPAMDriver := "default"
UpdateDockerV2PluginName("bridge", "default")

if expectNetDriver != netDriverName {
t.Fatalf("Unexpected netdriver name. Expected: %s. Actual: %s",
expectNetDriver, netDriverName)
t.Fail()
}

if expectIPAMDriver != ipamDriverName {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

t.Fatalf("Unexpected ipamdriver name. Expected: %s. Actual: %s",
expectIPAMDriver, ipamDriverName)
t.Fail()
}
}
2 changes: 1 addition & 1 deletion netmaster/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func execOpts(opts *cliOpts) {
log.Infof("Control IP:Port %s:%s", controlIP, controlURL[1])

if opts.clusterMode == master.Docker || opts.clusterMode == master.SwarmMode {
docknet.UpdatePluginName(opts.pluginName)
docknet.UpdateDockerV2PluginName(opts.pluginName, opts.pluginName)
}
}

Expand Down