diff --git a/controllers/elfmachine_controller_placement_group.go b/controllers/elfmachine_controller_placement_group.go index 5f249a3b..6a13b896 100644 --- a/controllers/elfmachine_controller_placement_group.go +++ b/controllers/elfmachine_controller_placement_group.go @@ -168,9 +168,9 @@ func (r *ElfMachineReconciler) preCheckPlacementGroup(ctx *context.MachineContex return nil, err } - // KCP is not in scaling down/rolling update. + // When KCP is not in scaling down and it's not rolling update the 1st CP Machine, just return since the placement group is full. if !(kcputil.IsKCPRollingUpdateFirstMachine(kcp) || kcputil.IsKCPInScalingDown(kcp)) { - ctx.Logger.V(1).Info("The placement group is full, wait for enough available hosts", "placementGroup", *placementGroup.Name, "availableHosts", availableHosts.String(), "usedHostsByPG", usedHostsByPG.String()) + ctx.Logger.V(1).Info("KCP is not in scaling down and it's not rolling update the 1st CP Machine, the placement group is full, wait for enough available hosts", "placementGroup", *placementGroup.Name, "availableHosts", availableHosts.String(), "usedHostsByPG", usedHostsByPG.String()) return nil, nil } @@ -211,7 +211,9 @@ func (r *ElfMachineReconciler) preCheckPlacementGroup(ctx *context.MachineContex return nil, nil } - // KCP is in rolling update. + // When the PlacementGroup is full and it's rolling update the 1st CP Machine and, + // place the VM on the target host without joining the PlacementGroup and power it on. + // After other CP Machine are rolled out successfully, add this 1st CP VM into the PlacementGroup. if usedHostsByPG.Len() == usedHostsByPG.Available(*service.TowerMemory(ctx.ElfMachine.Spec.MemoryMiB)).Len() && int(*kcp.Spec.Replicas) == usedHostsByPG.Len() { @@ -225,7 +227,7 @@ func (r *ElfMachineReconciler) preCheckPlacementGroup(ctx *context.MachineContex return pointer.String(hostID), err } - ctx.Logger.V(1).Info("The placement group is full, wait for enough available hosts", "placementGroup", *placementGroup.Name, "availableHosts", availableHosts.String(), "usedHostsByPG", usedHostsByPG.String()) + ctx.Logger.V(1).Info("KCP is rolling update the 1st CP Machine, the placement group is full, wait for enough available hosts", "placementGroup", *placementGroup.Name, "availableHosts", availableHosts.String(), "usedHostsByPG", usedHostsByPG.String()) return nil, nil } @@ -448,7 +450,7 @@ func (r *ElfMachineReconciler) joinPlacementGroup(ctx *context.MachineContext, v return false, err } - if kcputil.IsKCPRollingUpdate(kcp) { + if kcputil.IsKCPInRollingUpdate(kcp) { ctx.Logger.Info("KCP rolling update in progress, skip migrating VM", "vmRef", ctx.ElfMachine.Status.VMRef, "vmId", *vm.ID) return true, nil } diff --git a/controllers/elfmachine_controller_test.go b/controllers/elfmachine_controller_test.go index c74c0ca1..61da905c 100644 --- a/controllers/elfmachine_controller_test.go +++ b/controllers/elfmachine_controller_test.go @@ -1260,7 +1260,7 @@ var _ = Describe("ElfMachineReconciler", func() { hostID, err = reconciler.preCheckPlacementGroup(machineContext) Expect(err).To(BeZero()) Expect(hostID).To(BeNil()) - Expect(logBuffer.String()).To(ContainSubstring("The placement group is full, wait for enough available hosts")) + Expect(logBuffer.String()).To(ContainSubstring("KCP is not in scaling down and it's not rolling update the 1st CP Machine, the placement group is full, wait for enough available hosts")) }) It("when placement group is full and KCP rolling update in progress", func() { @@ -1334,7 +1334,7 @@ var _ = Describe("ElfMachineReconciler", func() { host, err = reconciler.preCheckPlacementGroup(machineContext) Expect(err).To(BeZero()) Expect(host).To(BeNil()) - Expect(logBuffer.String()).To(ContainSubstring("The placement group is full, wait for enough available hosts")) + Expect(logBuffer.String()).To(ContainSubstring("KCP is rolling update the 1st CP Machine, the placement group is full, wait for enough available hosts")) logBuffer = new(bytes.Buffer) klog.SetOutput(logBuffer) @@ -1348,7 +1348,7 @@ var _ = Describe("ElfMachineReconciler", func() { host, err = reconciler.preCheckPlacementGroup(machineContext) Expect(err).To(BeZero()) Expect(host).To(BeNil()) - Expect(logBuffer.String()).To(ContainSubstring("The placement group is full, wait for enough available hosts")) + Expect(logBuffer.String()).To(ContainSubstring("KCP is rolling update the 1st CP Machine, the placement group is full, wait for enough available hosts")) logBuffer = new(bytes.Buffer) klog.SetOutput(logBuffer) @@ -1362,7 +1362,7 @@ var _ = Describe("ElfMachineReconciler", func() { host, err = reconciler.preCheckPlacementGroup(machineContext) Expect(err).To(BeZero()) Expect(host).To(BeNil()) - Expect(logBuffer.String()).To(ContainSubstring("The placement group is full, wait for enough available hosts")) + Expect(logBuffer.String()).To(ContainSubstring("KCP is rolling update the 1st CP Machine, the placement group is full, wait for enough available hosts")) logBuffer = new(bytes.Buffer) klog.SetOutput(logBuffer) @@ -1458,7 +1458,7 @@ var _ = Describe("ElfMachineReconciler", func() { hostID, err := reconciler.preCheckPlacementGroup(machineContext) Expect(err).To(BeZero()) Expect(hostID).To(BeNil()) - Expect(logBuffer.String()).To(ContainSubstring("The placement group is full, wait for enough available hosts")) + Expect(logBuffer.String()).To(ContainSubstring("KCP is not in scaling down and it's not rolling update the 1st CP Machine, the placement group is full, wait for enough available hosts")) expectConditions(elfMachine, []conditionAssertion{{infrav1.VMProvisionedCondition, corev1.ConditionFalse, clusterv1.ConditionSeverityInfo, infrav1.WaitingForAvailableHostRequiredByPlacementGroupReason}}) elfMachine.Status.Conditions = nil diff --git a/pkg/service/mock_services/vm_mock.go b/pkg/service/mock_services/vm_mock.go index 968f2293..a0567d38 100644 --- a/pkg/service/mock_services/vm_mock.go +++ b/pkg/service/mock_services/vm_mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: /root/github/cluster-api-provider-elf/pkg/service/vm.go +// Source: github.com/smartxworks/cluster-api-provider-elf/pkg/service/vm.go // Package mock_services is a generated GoMock package. package mock_services diff --git a/pkg/util/kcp/kcp.go b/pkg/util/kcp/kcp.go index ae0654c2..0c9a33e8 100644 --- a/pkg/util/kcp/kcp.go +++ b/pkg/util/kcp/kcp.go @@ -22,7 +22,7 @@ import ( "sigs.k8s.io/cluster-api/util/conditions" ) -// IsKCPRollingUpdate returns whether KCP is in scaling down. +// IsKCPInRollingUpdate returns whether KCP is in scaling down. // // When KCP is in rolling update, KCP controller marks // MachinesSpecUpToDateCondition to false and RollingUpdateInProgressReason as Reason. @@ -30,7 +30,7 @@ import ( // When all machines are up to date, KCP controller marks MachinesSpecUpToDateCondition to true. // // For more information about KCP MachinesSpecUpToDateCondition and RollingUpdateInProgressReason, refer to https://github.com/kubernetes-sigs/cluster-api/blob/main/api/v1beta1/condition_consts.go -func IsKCPRollingUpdate(kcp *controlplanev1.KubeadmControlPlane) bool { +func IsKCPInRollingUpdate(kcp *controlplanev1.KubeadmControlPlane) bool { return conditions.IsFalse(kcp, controlplanev1.MachinesSpecUpToDateCondition) && conditions.GetReason(kcp, controlplanev1.MachinesSpecUpToDateCondition) == controlplanev1.RollingUpdateInProgressReason } @@ -51,7 +51,7 @@ func IsKCPRollingUpdate(kcp *controlplanev1.KubeadmControlPlane) bool { // For more information about KCP replicas, refer to https://github.com/kubernetes-sigs/cluster-api/blob/main/controlplane/kubeadm/api/v1beta1/kubeadm_control_plane_types.go // For more information about KCP rollout, refer to https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20191017-kubeadm-based-control-plane.md#kubeadmcontrolplane-rollout func IsKCPRollingUpdateFirstMachine(kcp *controlplanev1.KubeadmControlPlane) bool { - return IsKCPRollingUpdate(kcp) && kcp.Status.UpdatedReplicas == 1 + return IsKCPInRollingUpdate(kcp) && kcp.Status.UpdatedReplicas == 1 } // IsKCPInScalingDown returns whether KCP is in scaling down.