diff --git a/plugins/ipam/host-local/backend/allocator/allocator.go b/plugins/ipam/host-local/backend/allocator/allocator.go index 1d2964b9..d1c2b101 100644 --- a/plugins/ipam/host-local/backend/allocator/allocator.go +++ b/plugins/ipam/host-local/backend/allocator/allocator.go @@ -41,7 +41,7 @@ func NewIPAllocator(s *RangeSet, store backend.Store, id int) *IPAllocator { } // Get alocates an IP -func (a *IPAllocator) Get(id string, requestedIP net.IP) (*current.IPConfig, error) { +func (a *IPAllocator) Get(id string, ifname string, requestedIP net.IP) (*current.IPConfig, error) { a.store.Lock() defer a.store.Unlock() @@ -62,7 +62,7 @@ func (a *IPAllocator) Get(id string, requestedIP net.IP) (*current.IPConfig, err return nil, fmt.Errorf("requested ip %s is subnet's gateway", requestedIP.String()) } - reserved, err := a.store.Reserve(id, requestedIP, a.rangeID) + reserved, err := a.store.Reserve(id, ifname, requestedIP, a.rangeID) if err != nil { return nil, err } @@ -83,7 +83,7 @@ func (a *IPAllocator) Get(id string, requestedIP net.IP) (*current.IPConfig, err break } - reserved, err := a.store.Reserve(id, reservedIP.IP, a.rangeID) + reserved, err := a.store.Reserve(id, ifname, reservedIP.IP, a.rangeID) if err != nil { return nil, err } @@ -110,11 +110,11 @@ func (a *IPAllocator) Get(id string, requestedIP net.IP) (*current.IPConfig, err } // Release clears all IPs allocated for the container with given ID -func (a *IPAllocator) Release(id string) error { +func (a *IPAllocator) Release(id string, ifname string) error { a.store.Lock() defer a.store.Unlock() - return a.store.ReleaseByID(id) + return a.store.ReleaseByID(id, ifname) } type RangeIter struct { diff --git a/plugins/ipam/host-local/backend/allocator/allocator_test.go b/plugins/ipam/host-local/backend/allocator/allocator_test.go index 436aaa52..5888c14b 100644 --- a/plugins/ipam/host-local/backend/allocator/allocator_test.go +++ b/plugins/ipam/host-local/backend/allocator/allocator_test.go @@ -70,7 +70,7 @@ func (t AllocatorTestCase) run(idx int) (*current.IPConfig, error) { rangeID: "rangeid", } - return alloc.Get("ID", nil) + return alloc.Get("ID", "eth0", nil) } var _ = Describe("host-local ip allocator", func() { @@ -88,8 +88,8 @@ var _ = Describe("host-local ip allocator", func() { It("should loop correctly from the end", func() { a := mkalloc() - a.store.Reserve("ID", net.IP{192, 168, 1, 6}, a.rangeID) - a.store.ReleaseByID("ID") + a.store.Reserve("ID", "eth0", net.IP{192, 168, 1, 6}, a.rangeID) + a.store.ReleaseByID("ID", "eth0") r, _ := a.GetIter() Expect(r.nextip()).To(Equal(net.IP{192, 168, 1, 2})) Expect(r.nextip()).To(Equal(net.IP{192, 168, 1, 3})) @@ -100,8 +100,8 @@ var _ = Describe("host-local ip allocator", func() { }) It("should loop correctly from the middle", func() { a := mkalloc() - a.store.Reserve("ID", net.IP{192, 168, 1, 3}, a.rangeID) - a.store.ReleaseByID("ID") + a.store.Reserve("ID", "eth0", net.IP{192, 168, 1, 3}, a.rangeID) + a.store.ReleaseByID("ID", "eth0") r, _ := a.GetIter() Expect(r.nextip()).To(Equal(net.IP{192, 168, 1, 4})) Expect(r.nextip()).To(Equal(net.IP{192, 168, 1, 5})) @@ -221,28 +221,28 @@ var _ = Describe("host-local ip allocator", func() { It("should not allocate the broadcast address", func() { alloc := mkalloc() for i := 2; i < 7; i++ { - res, err := alloc.Get("ID", nil) + res, err := alloc.Get("ID", "eth0", nil) Expect(err).ToNot(HaveOccurred()) s := fmt.Sprintf("192.168.1.%d/29", i) Expect(s).To(Equal(res.Address.String())) fmt.Fprintln(GinkgoWriter, "got ip", res.Address.String()) } - x, err := alloc.Get("ID", nil) + x, err := alloc.Get("ID", "eth0", nil) fmt.Fprintln(GinkgoWriter, "got ip", x) Expect(err).To(HaveOccurred()) }) It("should allocate in a round-robin fashion", func() { alloc := mkalloc() - res, err := alloc.Get("ID", nil) + res, err := alloc.Get("ID", "eth0", nil) Expect(err).ToNot(HaveOccurred()) Expect(res.Address.String()).To(Equal("192.168.1.2/29")) - err = alloc.Release("ID") + err = alloc.Release("ID", "eth0") Expect(err).ToNot(HaveOccurred()) - res, err = alloc.Get("ID", nil) + res, err = alloc.Get("ID", "eth0", nil) Expect(err).ToNot(HaveOccurred()) Expect(res.Address.String()).To(Equal("192.168.1.3/29")) @@ -252,7 +252,7 @@ var _ = Describe("host-local ip allocator", func() { It("must allocate the requested IP", func() { alloc := mkalloc() requestedIP := net.IP{192, 168, 1, 5} - res, err := alloc.Get("ID", requestedIP) + res, err := alloc.Get("ID", "eth0", requestedIP) Expect(err).ToNot(HaveOccurred()) Expect(res.Address.IP.String()).To(Equal(requestedIP.String())) }) @@ -260,11 +260,11 @@ var _ = Describe("host-local ip allocator", func() { It("must fail when the requested IP is allocated", func() { alloc := mkalloc() requestedIP := net.IP{192, 168, 1, 5} - res, err := alloc.Get("ID", requestedIP) + res, err := alloc.Get("ID", "eth0", requestedIP) Expect(err).ToNot(HaveOccurred()) Expect(res.Address.IP.String()).To(Equal(requestedIP.String())) - _, err = alloc.Get("ID", requestedIP) + _, err = alloc.Get("ID", "eth0", requestedIP) Expect(err).To(MatchError(`requested IP address 192.168.1.5 is not available in range set 192.168.1.1-192.168.1.6`)) }) @@ -272,7 +272,7 @@ var _ = Describe("host-local ip allocator", func() { alloc := mkalloc() (*alloc.rangeset)[0].RangeEnd = net.IP{192, 168, 1, 4} requestedIP := net.IP{192, 168, 1, 5} - _, err := alloc.Get("ID", requestedIP) + _, err := alloc.Get("ID", "eth0", requestedIP) Expect(err).To(HaveOccurred()) }) @@ -280,7 +280,7 @@ var _ = Describe("host-local ip allocator", func() { alloc := mkalloc() (*alloc.rangeset)[0].RangeStart = net.IP{192, 168, 1, 3} requestedIP := net.IP{192, 168, 1, 2} - _, err := alloc.Get("ID", requestedIP) + _, err := alloc.Get("ID", "eth0", requestedIP) Expect(err).To(HaveOccurred()) }) }) diff --git a/plugins/ipam/host-local/backend/disk/backend.go b/plugins/ipam/host-local/backend/disk/backend.go index 08bb4eb9..cc19afa9 100644 --- a/plugins/ipam/host-local/backend/disk/backend.go +++ b/plugins/ipam/host-local/backend/disk/backend.go @@ -55,7 +55,7 @@ func New(network, dataDir string) (*Store, error) { return &Store{lk, dir}, nil } -func (s *Store) Reserve(id string, ip net.IP, rangeID string) (bool, error) { +func (s *Store) Reserve(id string, ifname string, ip net.IP, rangeID string) (bool, error) { fname := GetEscapedPath(s.dataDir, ip.String()) f, err := os.OpenFile(fname, os.O_RDWR|os.O_EXCL|os.O_CREATE, 0644) @@ -65,7 +65,7 @@ func (s *Store) Reserve(id string, ip net.IP, rangeID string) (bool, error) { if err != nil { return false, err } - if _, err := f.WriteString(strings.TrimSpace(id)); err != nil { + if _, err := f.WriteString(strings.TrimSpace(id) + "\n" + ifname); err != nil { f.Close() os.Remove(f.Name()) return false, err @@ -99,7 +99,7 @@ func (s *Store) Release(ip net.IP) error { // N.B. This function eats errors to be tolerant and // release as much as possible -func (s *Store) ReleaseByID(id string) error { +func (s *Store) ReleaseByID(id string, ifname string) error { err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error { if err != nil || info.IsDir() { return nil @@ -108,7 +108,7 @@ func (s *Store) ReleaseByID(id string) error { if err != nil { return nil } - if strings.TrimSpace(string(data)) == strings.TrimSpace(id) { + if strings.TrimSpace(string(data)) == (strings.TrimSpace(id) + "\n" + ifname) { if err := os.Remove(path); err != nil { return nil } diff --git a/plugins/ipam/host-local/backend/store.go b/plugins/ipam/host-local/backend/store.go index 3d695847..4ea845da 100644 --- a/plugins/ipam/host-local/backend/store.go +++ b/plugins/ipam/host-local/backend/store.go @@ -20,8 +20,8 @@ type Store interface { Lock() error Unlock() error Close() error - Reserve(id string, ip net.IP, rangeID string) (bool, error) + Reserve(id string, ifname string, ip net.IP, rangeID string) (bool, error) LastReservedIP(rangeID string) (net.IP, error) Release(ip net.IP) error - ReleaseByID(id string) error + ReleaseByID(id string, ifname string) error } diff --git a/plugins/ipam/host-local/backend/testing/fake_store.go b/plugins/ipam/host-local/backend/testing/fake_store.go index 49a0f554..631fca2e 100644 --- a/plugins/ipam/host-local/backend/testing/fake_store.go +++ b/plugins/ipam/host-local/backend/testing/fake_store.go @@ -45,7 +45,7 @@ func (s *FakeStore) Close() error { return nil } -func (s *FakeStore) Reserve(id string, ip net.IP, rangeID string) (bool, error) { +func (s *FakeStore) Reserve(id string, ifname string, ip net.IP, rangeID string) (bool, error) { key := ip.String() if _, ok := s.ipMap[key]; !ok { s.ipMap[key] = id @@ -68,7 +68,7 @@ func (s *FakeStore) Release(ip net.IP) error { return nil } -func (s *FakeStore) ReleaseByID(id string) error { +func (s *FakeStore) ReleaseByID(id string, ifname string) error { toDelete := []string{} for k, v := range s.ipMap { if v == id { diff --git a/plugins/ipam/host-local/host_local_test.go b/plugins/ipam/host-local/host_local_test.go index 653d6175..04edf035 100644 --- a/plugins/ipam/host-local/host_local_test.go +++ b/plugins/ipam/host-local/host_local_test.go @@ -111,12 +111,12 @@ var _ = Describe("host-local Operations", func() { ipFilePath1 := filepath.Join(tmpDir, "mynet", "10.1.2.2") contents, err := ioutil.ReadFile(ipFilePath1) Expect(err).NotTo(HaveOccurred()) - Expect(string(contents)).To(Equal(args.ContainerID)) + Expect(string(contents)).To(Equal(args.ContainerID + "\n" + ifname)) ipFilePath2 := filepath.Join(tmpDir, disk.GetEscapedPath("mynet", "2001:db8:1::2")) contents, err = ioutil.ReadFile(ipFilePath2) Expect(err).NotTo(HaveOccurred()) - Expect(string(contents)).To(Equal(args.ContainerID)) + Expect(string(contents)).To(Equal(args.ContainerID + "\n" + ifname)) lastFilePath1 := filepath.Join(tmpDir, "mynet", "last_reserved_ip.0") contents, err = ioutil.ReadFile(lastFilePath1) @@ -223,7 +223,7 @@ var _ = Describe("host-local Operations", func() { ipFilePath := filepath.Join(tmpDir, "mynet", "10.1.2.2") contents, err := ioutil.ReadFile(ipFilePath) Expect(err).NotTo(HaveOccurred()) - Expect(string(contents)).To(Equal(args.ContainerID)) + Expect(string(contents)).To(Equal(args.ContainerID + "\n" + ifname)) lastFilePath := filepath.Join(tmpDir, "mynet", "last_reserved_ip.0") contents, err = ioutil.ReadFile(lastFilePath) @@ -281,7 +281,7 @@ var _ = Describe("host-local Operations", func() { ipFilePath := filepath.Join(tmpDir, "mynet", result.IPs[0].Address.IP.String()) contents, err := ioutil.ReadFile(ipFilePath) Expect(err).NotTo(HaveOccurred()) - Expect(string(contents)).To(Equal("dummy")) + Expect(string(contents)).To(Equal("dummy" + "\n" + ifname)) // Release the IP err = testutils.CmdDelWithArgs(args, func() error { diff --git a/plugins/ipam/host-local/main.go b/plugins/ipam/host-local/main.go index 132391d0..cb1328e4 100644 --- a/plugins/ipam/host-local/main.go +++ b/plugins/ipam/host-local/main.go @@ -85,11 +85,11 @@ func cmdAdd(args *skel.CmdArgs) error { } } - ipConf, err := allocator.Get(args.ContainerID, requestedIP) + ipConf, err := allocator.Get(args.ContainerID, args.IfName, requestedIP) if err != nil { // Deallocate all already allocated IPs for _, alloc := range allocs { - _ = alloc.Release(args.ContainerID) + _ = alloc.Release(args.ContainerID, args.IfName) } return fmt.Errorf("failed to allocate for range %d: %v", idx, err) } @@ -102,7 +102,7 @@ func cmdAdd(args *skel.CmdArgs) error { // If an IP was requested that wasn't fulfilled, fail if len(requestedIPs) != 0 { for _, alloc := range allocs { - _ = alloc.Release(args.ContainerID) + _ = alloc.Release(args.ContainerID, args.IfName) } errstr := "failed to allocate all requested IPs:" for _, ip := range requestedIPs { @@ -133,7 +133,7 @@ func cmdDel(args *skel.CmdArgs) error { for idx, rangeset := range ipamConf.Ranges { ipAllocator := allocator.NewIPAllocator(&rangeset, store, idx) - err := ipAllocator.Release(args.ContainerID) + err := ipAllocator.Release(args.ContainerID, args.IfName) if err != nil { errors = append(errors, err.Error()) }