Skip to content
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

host-local: add ifname to file tracking IP address used #203

Merged
merged 10 commits into from
Oct 10, 2018
10 changes: 5 additions & 5 deletions plugins/ipam/host-local/backend/allocator/allocator.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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
}
Expand All @@ -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
}
Expand All @@ -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 {
Expand Down
30 changes: 15 additions & 15 deletions plugins/ipam/host-local/backend/allocator/allocator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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}))
Expand All @@ -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}))
Expand Down Expand Up @@ -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"))

Expand All @@ -252,35 +252,35 @@ 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()))
})

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`))
})

It("must return an error when the requested IP is after RangeEnd", 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())
})

It("must return an error when the requested IP is before RangeStart", 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())
})
})
Expand Down
29 changes: 23 additions & 6 deletions plugins/ipam/host-local/backend/disk/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
)

const lastIPFilePrefix = "last_reserved_ip."
const LineBreak = "\r\n"

var defaultDataDir = "/var/lib/cni/networks"

Expand Down Expand Up @@ -55,7 +56,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)
Expand All @@ -65,7 +66,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) + LineBreak + ifname); err != nil {
f.Close()
os.Remove(f.Name())
return false, err
Expand Down Expand Up @@ -97,9 +98,8 @@ func (s *Store) Release(ip net.IP) error {
return os.Remove(GetEscapedPath(s.dataDir, ip.String()))
}

// 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) ReleaseByKey(id string, ifname string, match string) (bool, error) {
found := false
err := filepath.Walk(s.dataDir, func(path string, info os.FileInfo, err error) error {
if err != nil || info.IsDir() {
return nil
Expand All @@ -108,13 +108,30 @@ 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)) == match {
if err := os.Remove(path); err != nil {
return nil
}
found = true
}
return nil
})
return found, err

}

// N.B. This function eats errors to be tolerant and
// release as much as possible
func (s *Store) ReleaseByID(id string, ifname string) error {
found := false
match := strings.TrimSpace(id) + LineBreak + ifname
found, err := s.ReleaseByKey(id, ifname, match)

// For backwards compatibility, look for files written by a previous version
if !found && err == nil {
match := strings.TrimSpace(id)
found, err = s.ReleaseByKey(id, ifname, match)
}
return err
}

Expand Down
4 changes: 2 additions & 2 deletions plugins/ipam/host-local/backend/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
4 changes: 2 additions & 2 deletions plugins/ipam/host-local/backend/testing/fake_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down
Loading