diff --git a/pkg/ippoolmanager/ippool_manager.go b/pkg/ippoolmanager/ippool_manager.go index 400f3f0d4e..febbf9e1a6 100644 --- a/pkg/ippoolmanager/ippool_manager.go +++ b/pkg/ippoolmanager/ippool_manager.go @@ -215,7 +215,15 @@ func (im *ipPoolManager) genRandomIP(ctx context.Context, ipPool *spiderpoolv2be ipPool.Status.AllocatedIPCount = new(int64) } - *ipPool.Status.AllocatedIPCount++ + // reference issue: https://github.com/spidernet-io/spiderpool/issues/3771 + if int64(len(usedIPs)) != *ipPool.Status.AllocatedIPCount { + logger.Sugar().Errorf("Handling AllocatedIPCount while allocating IP from IPPool %s, but there is a data discrepancy. Expected %d, but got %d.", ipPool.Name, len(usedIPs), *ipPool.Status.AllocatedIPCount) + } + + // Adding a newly assigned IP + usedIPs = append(usedIPs, resIP) + *ipPool.Status.AllocatedIPCount = int64(len(usedIPs)) + if *ipPool.Status.AllocatedIPCount > int64(*im.config.MaxAllocatedIPs) { return nil, fmt.Errorf("%w, threshold of IP records(<=%d) for IPPool %s exceeded", constant.ErrIPUsedOut, im.config.MaxAllocatedIPs, ipPool.Name) } @@ -248,12 +256,17 @@ func (im *ipPoolManager) ReleaseIP(ctx context.Context, poolName string, ipAndUI ipPool.Status.AllocatedIPCount = new(int64) } + // reference issue: https://github.com/spidernet-io/spiderpool/issues/3771 + if int64(len(allocatedRecords)) != *ipPool.Status.AllocatedIPCount { + logger.Sugar().Errorf("Handling AllocatedIPCount while releasing IP from IPPool %s, but there is a data discrepancy. Expected %d, but got %d.", ipPool.Name, len(allocatedRecords), *ipPool.Status.AllocatedIPCount) + } + release := false for _, iu := range ipAndUIDs { if record, ok := allocatedRecords[iu.IP]; ok { if record.PodUID == iu.UID { delete(allocatedRecords, iu.IP) - *ipPool.Status.AllocatedIPCount-- + *ipPool.Status.AllocatedIPCount = int64(len(allocatedRecords)) release = true } } diff --git a/test/e2e/reclaim/reclaim_test.go b/test/e2e/reclaim/reclaim_test.go index 692b2ff164..285f357e20 100644 --- a/test/e2e/reclaim/reclaim_test.go +++ b/test/e2e/reclaim/reclaim_test.go @@ -460,7 +460,7 @@ var _ = Describe("test ip with reclaim ip case", Label("reclaim"), func() { } }) }) - DescribeTable("dirty IP record in the IPPool should be auto clean by Spiderpool", Pending, func() { + DescribeTable("dirty IP record in the IPPool should be auto clean by Spiderpool", func() { // Generate IPPool annotation string podIppoolAnnoStr := common.GeneratePodIPPoolAnnotations(frame, common.NIC1, v4poolNameList, v6poolNameList) @@ -586,8 +586,25 @@ var _ = Describe("test ip with reclaim ip case", Label("reclaim"), func() { // Delete Pod Expect(frame.DeletePod(podName, namespace)).To(Succeed(), "Failed to delete pod %v/%v\n", namespace, podName) GinkgoWriter.Printf("succeed to delete pod %v/%v\n", namespace, podName) + + // Check whether the dirty IP data is recovered successfully and whether the AllocatedIPCount decreases and meets expectations? + Eventually(func() error { + if frame.Info.IpV4Enabled { + if err := common.CheckIppoolSanity(frame, v4poolName); err != nil { + return err + } + GinkgoWriter.Printf("successfully checked sanity of v4 spiderIPPool %v \n", v4poolName) + } + if frame.Info.IpV6Enabled { + if err := common.CheckIppoolSanity(frame, v6poolName); err != nil { + return err + } + GinkgoWriter.Printf("successfully checked sanity of v6 spiderIPPool %v \n", v6poolName) + } + return nil + }).WithTimeout(time.Minute).WithPolling(time.Second * 10).Should(BeNil()) }, - PEntry("a dirty IP record (pod name is wrong or containerID is wrong) in the IPPool should be auto clean by Spiderpool", Serial, Label("G00005", "G00007")), + Entry("a dirty IP record (pod name is wrong or containerID is wrong) in the IPPool should be auto clean by Spiderpool", Serial, Label("G00005", "G00007")), ) })