Improve cleanup on network failure paths

This commit is contained in:
Onur Filiz 2017-08-16 14:13:46 -07:00
Родитель 879d9e04f9
Коммит b9a2193b3a
4 изменённых файлов: 80 добавлений и 72 удалений

Просмотреть файл

@ -45,16 +45,21 @@ func (nw *network) newEndpoint(epInfo *EndpointInfo) (*endpoint, error) {
var err error
log.Printf("[net] Creating endpoint %+v in network %v.", epInfo, nw.Id)
defer func() {
if err != nil {
log.Printf("[net] Failed to create endpoint %v, err:%v.", epInfo.Id, err)
}
}()
if nw.Endpoints[epInfo.Id] != nil {
err = errEndpointExists
goto fail
return nil, err
}
// Call the platform implementation.
ep, err = nw.newEndpointImpl(epInfo)
if err != nil {
goto fail
return nil, err
}
nw.Endpoints[epInfo.Id] = ep
@ -62,27 +67,29 @@ func (nw *network) newEndpoint(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Created endpoint %+v.", ep)
return ep, nil
fail:
log.Printf("[net] Creating endpoint %v failed, err:%v.", epInfo.Id, err)
return nil, err
}
// DeleteEndpoint deletes an existing endpoint from the network.
func (nw *network) deleteEndpoint(endpointId string) error {
var err error
log.Printf("[net] Deleting endpoint %v from network %v.", endpointId, nw.Id)
defer func() {
if err != nil {
log.Printf("[net] Failed to delete endpoint %v, err:%v.", endpointId, err)
}
}()
// Look up the endpoint.
ep, err := nw.getEndpoint(endpointId)
if err != nil {
goto fail
return err
}
// Call the platform implementation.
err = nw.deleteEndpointImpl(ep)
if err != nil {
goto fail
return err
}
// Remove the endpoint object.
@ -91,11 +98,6 @@ func (nw *network) deleteEndpoint(endpointId string) error {
log.Printf("[net] Deleted endpoint %+v.", ep)
return nil
fail:
log.Printf("[net] Deleting endpoint %v failed, err:%v.", endpointId, err)
return err
}
// GetEndpoint returns the endpoint with the given ID.

Просмотреть файл

@ -52,6 +52,13 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
return nil, err
}
// On failure, delete the veth pair.
defer func() {
if err != nil {
netlink.DeleteLink(contIfName)
}
}()
//
// Host network interface setup.
//
@ -60,14 +67,14 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Setting link %v state up.", hostIfName)
err = netlink.SetLinkState(hostIfName, true)
if err != nil {
goto cleanup
return nil, err
}
// Connect host interface to the bridge.
log.Printf("[net] Setting link %v master %v.", hostIfName, nw.extIf.BridgeName)
err = netlink.SetLinkMaster(hostIfName, nw.extIf.BridgeName)
if err != nil {
goto cleanup
return nil, err
}
//
@ -77,7 +84,7 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
// Query container network interface info.
containerIf, err = net.InterfaceByName(contIfName)
if err != nil {
goto cleanup
return nil, err
}
// Setup rules for IP addresses on the container interface.
@ -86,14 +93,14 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Adding ARP reply rule for IP address %v on %v.", ipAddr.String(), contIfName)
err = ebtables.SetArpReply(ipAddr.IP, nw.getArpReplyAddress(containerIf.HardwareAddr), ebtables.Append)
if err != nil {
goto cleanup
return nil, err
}
// Add MAC address translation rule.
log.Printf("[net] Adding MAC DNAT rule for IP address %v on %v.", ipAddr.String(), contIfName)
err = ebtables.SetDnatForIPAddress(nw.extIf.Name, ipAddr.IP, containerIf.HardwareAddr, ebtables.Append)
if err != nil {
goto cleanup
return nil, err
}
}
@ -103,7 +110,7 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Opening netns %v.", epInfo.NetNsPath)
ns, err = OpenNamespace(epInfo.NetNsPath)
if err != nil {
goto cleanup
return nil, err
}
defer ns.Close()
@ -111,15 +118,24 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Setting link %v netns %v.", contIfName, epInfo.NetNsPath)
err = netlink.SetLinkNetNs(contIfName, ns.GetFd())
if err != nil {
goto cleanup
return nil, err
}
// Enter the container network namespace.
log.Printf("[net] Entering netns %v.", epInfo.NetNsPath)
err = ns.Enter()
if err != nil {
goto cleanup
return nil, err
}
// Return to host network namespace.
defer func() {
log.Printf("[net] Exiting netns %v.", epInfo.NetNsPath)
err = ns.Exit()
if err != nil {
log.Printf("[net] Failed to exit netns, err:%v.", err)
}
}()
}
// If a name for the container interface is specified...
@ -128,14 +144,14 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Setting link %v state down.", contIfName)
err = netlink.SetLinkState(contIfName, false)
if err != nil {
goto cleanup
return nil, err
}
// Rename the container interface.
log.Printf("[net] Setting link %v name %v.", contIfName, epInfo.IfName)
err = netlink.SetLinkName(contIfName, epInfo.IfName)
if err != nil {
goto cleanup
return nil, err
}
contIfName = epInfo.IfName
@ -143,7 +159,7 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Setting link %v state up.", contIfName)
err = netlink.SetLinkState(contIfName, true)
if err != nil {
goto cleanup
return nil, err
}
}
@ -152,7 +168,7 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
log.Printf("[net] Adding IP address %v to link %v.", ipAddr.String(), contIfName)
err = netlink.AddIpAddress(contIfName, ipAddr.IP, &ipAddr)
if err != nil {
goto cleanup
return nil, err
}
}
@ -169,17 +185,7 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
err = netlink.AddIpRoute(nlRoute)
if err != nil {
goto cleanup
}
}
// If inside the container network namespace...
if ns != nil {
// Return to host network namespace.
log.Printf("[net] Exiting netns %v.", epInfo.NetNsPath)
err = ns.Exit()
if err != nil {
goto cleanup
return nil, err
}
}
@ -194,12 +200,6 @@ func (nw *network) newEndpointImpl(epInfo *EndpointInfo) (*endpoint, error) {
}
return ep, nil
cleanup:
// Roll back the changes for the endpoint.
netlink.DeleteLink(contIfName)
return nil, err
}
// deleteEndpointImpl deletes an existing endpoint from the network.

Просмотреть файл

@ -121,6 +121,11 @@ func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) {
var err error
log.Printf("[net] Creating network %+v.", nwInfo)
defer func() {
if err != nil {
log.Printf("[net] Failed to create network %v, err:%v.", nwInfo.Id, err)
}
}()
// Set defaults.
if nwInfo.Mode == "" {
@ -131,19 +136,19 @@ func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) {
extIf := nm.findExternalInterfaceBySubnet(nwInfo.Subnets[0].Prefix.String())
if extIf == nil {
err = errSubnetNotFound
goto fail
return nil, err
}
// Make sure this network does not already exist.
if extIf.Networks[nwInfo.Id] != nil {
err = errNetworkExists
goto fail
return nil, err
}
// Call the OS-specific implementation.
nw, err = nm.newNetworkImpl(nwInfo, extIf)
if err != nil {
goto fail
return nil, err
}
// Add the network object.
@ -152,26 +157,29 @@ func (nm *networkManager) newNetwork(nwInfo *NetworkInfo) (*network, error) {
log.Printf("[net] Created network %v on interface %v.", nwInfo.Id, extIf.Name)
return nw, nil
fail:
log.Printf("[net] Failed to create network %v, err:%v.", nwInfo.Id, err)
return nil, err
}
// DeleteNetwork deletes an existing container network.
func (nm *networkManager) deleteNetwork(networkId string) error {
var err error
log.Printf("[net] Deleting network %v.", networkId)
defer func() {
if err != nil {
log.Printf("[net] Failed to delete network %v, err:%v.", networkId, err)
}
}()
// Find the network.
nw, err := nm.getNetwork(networkId)
if err != nil {
goto fail
return err
}
// Call the OS-specific implementation.
err = nm.deleteNetworkImpl(nw)
if err != nil {
goto fail
return err
}
// Remove the network object.
@ -179,10 +187,6 @@ func (nm *networkManager) deleteNetwork(networkId string) error {
log.Printf("[net] Deleted network %+v.", nw)
return nil
fail:
log.Printf("[net] Failed to delete network %v, err:%v.", networkId, err)
return err
}
// GetNetwork returns the network with the given ID.

Просмотреть файл

@ -188,7 +188,10 @@ func (nm *networkManager) deleteBridgeRules(extIf *externalInterface) {
// ConnectExternalInterface connects the given host interface to a bridge.
func (nm *networkManager) connectExternalInterface(extIf *externalInterface, nwInfo *NetworkInfo) error {
var err error
log.Printf("[net] Connecting interface %v.", extIf.Name)
defer func() { log.Printf("[net] Connecting interface %v completed with err:%v.", extIf.Name, err) }()
// Check whether this interface is already connected.
if extIf.BridgeName != "" {
@ -226,9 +229,16 @@ func (nm *networkManager) connectExternalInterface(extIf *externalInterface, nwI
return err
}
// On failure, delete the bridge.
defer func() {
if err != nil {
netlink.DeleteLink(bridgeName)
}
}()
bridge, err = net.InterfaceByName(bridgeName)
if err != nil {
goto cleanup
return err
}
} else {
// Use the existing bridge.
@ -244,42 +254,42 @@ func (nm *networkManager) connectExternalInterface(extIf *externalInterface, nwI
// Add the bridge rules.
err = nm.addBridgeRules(extIf, hostIf, bridgeName, nwInfo.Mode)
if err != nil {
goto cleanup
return err
}
// External interface down.
log.Printf("[net] Setting link %v state down.", hostIf.Name)
err = netlink.SetLinkState(hostIf.Name, false)
if err != nil {
goto cleanup
return err
}
// Connect the external interface to the bridge.
log.Printf("[net] Setting link %v master %v.", hostIf.Name, bridgeName)
err = netlink.SetLinkMaster(hostIf.Name, bridgeName)
if err != nil {
goto cleanup
return err
}
// External interface up.
log.Printf("[net] Setting link %v state up.", hostIf.Name)
err = netlink.SetLinkState(hostIf.Name, true)
if err != nil {
goto cleanup
return err
}
// External interface hairpin on.
log.Printf("[net] Setting link %v hairpin on.", hostIf.Name)
err = netlink.SetLinkHairpin(hostIf.Name, true)
if err != nil {
goto cleanup
return err
}
// Bridge up.
log.Printf("[net] Setting link %v state up.", bridgeName)
err = netlink.SetLinkState(bridgeName, true)
if err != nil {
goto cleanup
return err
}
// Apply IP configuration to the bridge for host traffic.
@ -289,19 +299,11 @@ func (nm *networkManager) connectExternalInterface(extIf *externalInterface, nwI
}
extIf.BridgeName = bridgeName
err = nil
log.Printf("[net] Connected interface %v to bridge %v.", extIf.Name, extIf.BridgeName)
return nil
cleanup:
log.Printf("[net] Connecting interface %v failed, err:%v.", extIf.Name, err)
// Roll back the changes for the network.
nm.deleteBridgeRules(extIf)
netlink.DeleteLink(bridgeName)
return err
}
// DisconnectExternalInterface disconnects a host interface from its bridge.