net: call ipam plugin on container shutdown

- Fixes bugs in ipam/static release path
- veth and bridge plugins invoke ipam plugin during DEL cmd
This commit is contained in:
Eugene Yakubovich
2015-02-04 14:02:53 -08:00
parent 6edd1973c9
commit a9c8cf4b45
5 changed files with 71 additions and 19 deletions
+26 -1
View File
@@ -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 {
@@ -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
+25 -7
View File
@@ -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() {
+12 -2
View File
@@ -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() {
+3 -3
View File
@@ -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)