diff --git a/networking/ipam/ipam.go b/networking/ipam/ipam.go index ce41c42..f439866 100644 --- a/networking/ipam/ipam.go +++ b/networking/ipam/ipam.go @@ -94,7 +94,13 @@ func findIPAMPlugin(plugin string) string { return "" } -func ExecPlugin(plugin string) (*IPConfig, error) { +// Executes IPAM plugin, assuming RKT_NETPLUGIN_COMMAND == ADD. +// Parses and returns resulting IPConfig +func ExecPluginAdd(plugin string) (*IPConfig, error) { + if os.Getenv("RKT_NETPLUGIN_COMMAND") != "ADD" { + return nil, fmt.Errorf("RKT_NETPLUGIN_COMMAND is not ADD") + } + pluginPath := findIPAMPlugin(plugin) if pluginPath == "" { return nil, fmt.Errorf("could not find %q plugin", plugin) @@ -117,6 +123,25 @@ func ExecPlugin(plugin string) (*IPConfig, error) { return ipConf, err } +// Executes IPAM plugin, assuming RKT_NETPLUGIN_COMMAND == DEL. +func ExecPluginDel(plugin string) error { + if os.Getenv("RKT_NETPLUGIN_COMMAND") != "DEL" { + return fmt.Errorf("RKT_NETPLUGIN_COMMAND is not DEL") + } + + pluginPath := findIPAMPlugin(plugin) + if pluginPath == "" { + return fmt.Errorf("could not find %q plugin", plugin) + } + + c := exec.Cmd{ + Path: pluginPath, + Args: []string{pluginPath}, + Stderr: os.Stderr, + } + return c.Run() +} + func ApplyIPConfig(ifName string, ipConf *IPConfig) error { link, err := netlink.LinkByName(ifName) if err != nil { diff --git a/networking/ipam/static/backend/disk/backend.go b/networking/ipam/static/backend/disk/backend.go index a45b86a..726e970 100644 --- a/networking/ipam/static/backend/disk/backend.go +++ b/networking/ipam/static/backend/disk/backend.go @@ -58,21 +58,20 @@ func (s *Store) Release(ip net.IP) error { return os.Remove(filepath.Join(s.dataDir, ip.String())) } +// N.B. This function eats errors to be tolerant and +// release as much as possible func (s *Store) ReleaseByContainerID(id string) error { err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() && path != s.dataDir { + if err != nil || info.IsDir() { return nil } data, err := ioutil.ReadFile(path) if err != nil { - return err + return nil } if string(data) == id { if err := os.Remove(path); err != nil { - return err + return nil } } return nil diff --git a/networking/net/bridge/bridge.go b/networking/net/bridge/bridge.go index e89bebf..df43a4a 100644 --- a/networking/net/bridge/bridge.go +++ b/networking/net/bridge/bridge.go @@ -45,6 +45,16 @@ func init() { runtime.LockOSThread() } +func loadConf(path string) (*Net, error) { + n := &Net{ + BrName: defaultBrName, + } + if err := rktnet.LoadNet(path, n); err != nil { + return nil, fmt.Errorf("failed to load %q: %v", path, err) + } + return n, nil +} + func ensureBridgeAddr(br *netlink.Bridge, ipn *net.IPNet) error { addrs, err := netlink.AddrList(br, syscall.AF_INET) if err != nil && err != syscall.ENOENT { @@ -183,15 +193,13 @@ func cmdAdd(contID, netns, netConf, ifName string) error { return fmt.Errorf("error parsing ContainerID: %v", err) } - n := &Net{ - BrName: defaultBrName, - } - if err := rktnet.LoadNet(netConf, n); err != nil { - return fmt.Errorf("failed to load %q: %v", netConf, err) + n, err := loadConf(netConf) + if err != nil { + return err } // run the IPAM plugin and get back the config to apply - ipConf, err := ipam.ExecPlugin(n.Net.IPAM.Type) + ipConf, err := ipam.ExecPluginAdd(n.Net.IPAM.Type) if err != nil { return err } @@ -211,9 +219,19 @@ func cmdAdd(contID, netns, netConf, ifName string) error { } func cmdDel(contID, netns, netConf, ifName string) error { - return util.WithNetNSPath(netns, func(hostNS *os.File) error { + n, err := loadConf(netConf) + if err != nil { + return err + } + + err = util.WithNetNSPath(netns, func(hostNS *os.File) error { return util.DelLinkByName(ifName) }) + if err != nil { + return err + } + + return ipam.ExecPluginDel(n.Net.IPAM.Type) } func main() { diff --git a/networking/net/veth/veth.go b/networking/net/veth/veth.go index f606bc6..66e311c 100644 --- a/networking/net/veth/veth.go +++ b/networking/net/veth/veth.go @@ -44,7 +44,7 @@ func cmdAdd(contID, netns, netConf, ifName, args string) error { } // run the IPAM plugin and get back the config to apply - ipConf, err := ipam.ExecPlugin(conf.IPAM.Type) + ipConf, err := ipam.ExecPluginAdd(conf.IPAM.Type) if err != nil { return err } @@ -96,9 +96,19 @@ func cmdAdd(contID, netns, netConf, ifName, args string) error { } func cmdDel(contID, netns, netConf, ifName, args string) error { - return util.WithNetNSPath(netns, func(hostNS *os.File) error { + conf := rktnet.Net{} + if err := rktnet.LoadNet(netConf, &conf); err != nil { + return fmt.Errorf("failed to load %q: %v", netConf, err) + } + + err := util.WithNetNSPath(netns, func(hostNS *os.File) error { return util.DelLinkByName(ifName) }) + if err != nil { + return err + } + + return ipam.ExecPluginDel(conf.IPAM.Type) } func main() { diff --git a/networking/networking.go b/networking/networking.go index 118a9a9..b16f8ac 100644 --- a/networking/networking.go +++ b/networking/networking.go @@ -182,7 +182,7 @@ func (e *containerEnv) setupNets(netns string, nets []Net) ([]activeNet, error) ifName: fmt.Sprintf(ifnamePattern, i), } - log.Printf("Executing net-plugin %v", nt.Type) + log.Printf("Setup: executing net-plugin %v", nt.Type) an.ip, err = e.netPluginAdd(&nt, netns, nt.args, an.ifName) if err != nil { @@ -193,8 +193,6 @@ func (e *containerEnv) setupNets(netns string, nets []Net) ([]activeNet, error) active = append(active, an) } - log.Print("Done executing net plugins") - if err != nil { e.teardownNets(netns, active) return nil, err @@ -206,6 +204,8 @@ func (e *containerEnv) setupNets(netns string, nets []Net) ([]activeNet, error) func (e *containerEnv) teardownNets(netns string, nets []activeNet) { for i := len(nets) - 1; i >= 0; i-- { nt := nets[i] + + log.Printf("Teardown: executing net-plugin %v", nt.Type) err := e.netPluginDel(&nt.Net, netns, nt.args, nt.ifName) if err != nil { log.Printf("Error deleting %q: %v", nt.Name, err)