From 31583e54514c60d160cefcc045853ea517a4a791 Mon Sep 17 00:00:00 2001 From: Arjun Baindur Date: Thu, 12 Jan 2023 14:25:16 -0800 Subject: [PATCH] Return existing reservation if podRef matches --- pkg/allocate/allocate.go | 11 +++++++---- pkg/storage/kubernetes/ipam.go | 16 +++++++++++++--- pkg/storage/storage.go | 2 +- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/pkg/allocate/allocate.go b/pkg/allocate/allocate.go index 2c22bc039..79dbce4e7 100644 --- a/pkg/allocate/allocate.go +++ b/pkg/allocate/allocate.go @@ -194,9 +194,9 @@ func IterateForAssignment(ipnet net.IPNet, rangeStart net.IP, rangeEnd net.IP, r } logging.Debugf("IterateForAssignment input >> ip: %v | ipnet: %v | first IP: %v | last IP: %v", rangeStart, ipnet, firstip, lastip) - reserved := make(map[string]bool) + reserved := make(map[string]string) for _, r := range reservelist { - reserved[r.IP.String()] = true + reserved[r.IP.String()] = r.PodRef } // excluded, "192.168.2.229/30", "192.168.1.229/30", @@ -212,8 +212,11 @@ func IterateForAssignment(ipnet net.IPNet, rangeStart net.IP, rangeEnd net.IP, r endip := IPAddOffset(lastip, uint64(1)) for i := firstip; !i.Equal(endip); i = IPAddOffset(i, uint64(1)) { // if already reserved, skip it - if reserved[i.String()] { - continue + if reserved[i.String()] != "" { + if reserved[i.String()] != podRef { + continue + } + logging.Debugf("Found existing reservation %v with matching podRef %s", i.String(), podRef) } // Lastly, we need to check if this IP is within the range of excluded subnets diff --git a/pkg/storage/kubernetes/ipam.go b/pkg/storage/kubernetes/ipam.go index 574b79c0f..a8c95f0c7 100644 --- a/pkg/storage/kubernetes/ipam.go +++ b/pkg/storage/kubernetes/ipam.go @@ -175,14 +175,14 @@ func (i *KubernetesIPAM) GetOverlappingRangeStore() (storage.OverlappingRangeSto } // IsAllocatedInOverlappingRange checks for IP addresses to see if they're allocated cluster wide, for overlapping ranges -func (c *KubernetesOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP) (bool, error) { +func (c *KubernetesOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP, podRef string) (bool, error) { // IPv6 doesn't make for valid CR names, so normalize it. normalizedip := strings.ReplaceAll(fmt.Sprint(ip), ":", "-") logging.Debugf("OverlappingRangewide allocation check for IP: %v", normalizedip) - _, err := c.client.WhereaboutsV1alpha1().OverlappingRangeIPReservations(c.namespace).Get(ctx, normalizedip, metav1.GetOptions{}) + clusteripres, err := c.client.WhereaboutsV1alpha1().OverlappingRangeIPReservations(c.namespace).Get(ctx, normalizedip, metav1.GetOptions{}) if err != nil && errors.IsNotFound(err) { // cluster ip reservation does not exist, this appears to be good news. // logging.Debugf("IP %v is not reserved cluster wide, allowing.", ip) @@ -192,6 +192,11 @@ func (c *KubernetesOverlappingRangeStore) IsAllocatedInOverlappingRange(ctx cont return false, fmt.Errorf("k8s get OverlappingRangeIPReservation error: %s", err) } + if clusteripres.Spec.PodRef == podRef { + logging.Debugf("IP %v matches existing podRef %s", ip, podRef) + return false, nil + } + logging.Debugf("IP %v is reserved cluster wide.", ip) return true, nil } @@ -220,6 +225,11 @@ func (c *KubernetesOverlappingRangeStore) UpdateOverlappingRangeAllocation(ctx c _, err = c.client.WhereaboutsV1alpha1().OverlappingRangeIPReservations(c.namespace).Create( ctx, clusteripres, metav1.CreateOptions{}) + if errors.IsAlreadyExists(err) { + logging.Debugf("clusteripres already exists, updating with %v", clusteripres.Spec) + _, err = c.client.WhereaboutsV1alpha1().OverlappingRangeIPReservations(c.namespace).Update(ctx, clusteripres, metav1.UpdateOptions{}) + } + case whereaboutstypes.Deallocate: verb = "deallocate" err = c.client.WhereaboutsV1alpha1().OverlappingRangeIPReservations(c.namespace).Delete(ctx, clusteripres.GetName(), metav1.DeleteOptions{}) @@ -480,7 +490,7 @@ func IPManagementKubernetesUpdate(ctx context.Context, mode int, ipam *Kubernete // When it's allocated overlappingrange wide, we add it to a local reserved list // And we try again. if ipamConf.OverlappingRanges { - isallocated, err := overlappingrangestore.IsAllocatedInOverlappingRange(requestCtx, newip.IP) + isallocated, err := overlappingrangestore.IsAllocatedInOverlappingRange(requestCtx, newip.IP, podRef) if err != nil { logging.Errorf("Error checking overlappingrange allocation: %v", err) return newips, err diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 40302d112..bc93d65aa 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -32,7 +32,7 @@ type Store interface { // OverlappingRangeStore is an interface for wrapping overlappingrange storage options type OverlappingRangeStore interface { - IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP) (bool, error) + IsAllocatedInOverlappingRange(ctx context.Context, ip net.IP, podRef string) (bool, error) UpdateOverlappingRangeAllocation(ctx context.Context, mode int, ip net.IP, containerID string, podRef string) error }