Skip to content

Commit 006d435

Browse files
authored
fix(vd): prevent VirtualDisk from stuck in WaitForFirstConsumer phase when VM is attached (#1516)
Fix VirtualDisk remaining in WaitForFirstConsumer phase even after VM attachment and provisioning has started. When using WFFC storage class with volume populators: 1. VD transitions to `WaitForFirstConsumer` waiting for VM 2. VM is created and attached to VD 3. Volume provisioning starts (importer pod running) 4. Issue: VD controller continues setting phase to `WaitForFirstConsumer` because DataVolume is in `PendingPopulation` state, even though the "first consumer" (VM) already exists Signed-off-by: Daniil Loktev <[email protected]>
1 parent 6c7dfcc commit 006d435

File tree

5 files changed

+31
-5
lines changed

5 files changed

+31
-5
lines changed

images/virtualization-artifact/pkg/controller/vd/internal/source/object_ref_cvi_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,13 @@ var _ = Describe("ObjectRef ClusterVirtualImage", func() {
184184

185185
It("waits for the first consumer", func() {
186186
dv.Status.Phase = cdiv1.PendingPopulation
187+
dv.Status.Conditions = []cdiv1.DataVolumeCondition{
188+
{
189+
Type: cdiv1.DataVolumeRunning,
190+
Status: corev1.ConditionFalse,
191+
Reason: "",
192+
},
193+
}
187194
sc.VolumeBindingMode = ptr.To(storagev1.VolumeBindingWaitForFirstConsumer)
188195
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(pvc, dv, sc).Build()
189196

images/virtualization-artifact/pkg/controller/vd/internal/source/object_ref_vi_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,13 @@ var _ = Describe("ObjectRef VirtualImage", func() {
184184

185185
It("waits for the first consumer", func() {
186186
dv.Status.Phase = cdiv1.PendingPopulation
187+
dv.Status.Conditions = []cdiv1.DataVolumeCondition{
188+
{
189+
Type: cdiv1.DataVolumeRunning,
190+
Status: corev1.ConditionFalse,
191+
Reason: "",
192+
},
193+
}
187194
sc.VolumeBindingMode = ptr.To(storagev1.VolumeBindingWaitForFirstConsumer)
188195
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(pvc, dv, sc).Build()
189196

images/virtualization-artifact/pkg/controller/vd/internal/source/sources.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,9 @@ func setPhaseConditionForPVCProvisioningDisk(
182182
Message("Waiting for the pvc importer to be created")
183183
return nil
184184
}
185-
if isStorageClassWFFC(sc) && (dv.Status.Phase == cdiv1.PendingPopulation || dv.Status.Phase == cdiv1.WaitForFirstConsumer) {
185+
186+
dvRunningCond, _ := conditions.GetDataVolumeCondition(conditions.DVRunningConditionType, dv.Status.Conditions)
187+
if isStorageClassWFFC(sc) && (dv.Status.Phase == cdiv1.PendingPopulation || dv.Status.Phase == cdiv1.WaitForFirstConsumer) && dvRunningCond.Reason == "" {
186188
vd.Status.Phase = v1alpha2.DiskWaitForFirstConsumer
187189
cb.
188190
Status(metav1.ConditionFalse).

images/virtualization-artifact/pkg/controller/vd/internal/source/step/wait_for_dv_step.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,18 @@ func (s WaitForDVStep) setForProvisioning(vd *v1alpha2.VirtualDisk) (set bool) {
126126
}
127127

128128
func (s WaitForDVStep) setForFirstConsumerIsAwaited(ctx context.Context, vd *v1alpha2.VirtualDisk) (set bool, err error) {
129+
if vd.Status.StorageClassName == "" {
130+
return false, fmt.Errorf("StorageClassName is empty, please report a bug")
131+
}
132+
129133
sc, err := object.FetchObject(ctx, types.NamespacedName{Name: vd.Status.StorageClassName}, s.client, &storagev1.StorageClass{})
130134
if err != nil {
131135
return false, fmt.Errorf("get sc: %w", err)
132136
}
133137

138+
dvRunningCond, _ := conditions.GetDataVolumeCondition(conditions.DVRunningConditionType, s.dv.Status.Conditions)
134139
isWFFC := sc != nil && sc.VolumeBindingMode != nil && *sc.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer
135-
if isWFFC && (s.dv.Status.Phase == cdiv1.PendingPopulation || s.dv.Status.Phase == cdiv1.WaitForFirstConsumer) {
140+
if isWFFC && (s.dv.Status.Phase == cdiv1.PendingPopulation || s.dv.Status.Phase == cdiv1.WaitForFirstConsumer) && dvRunningCond.Reason == "" {
136141
vd.Status.Phase = v1alpha2.DiskWaitForFirstConsumer
137142
s.cb.
138143
Status(metav1.ConditionFalse).

images/virtualization-artifact/pkg/controller/vd/internal/watcher/datavolume_watcher.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import (
2828
"sigs.k8s.io/controller-runtime/pkg/source"
2929

3030
"github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
31-
"github.com/deckhouse/virtualization-controller/pkg/controller/service"
3231
"github.com/deckhouse/virtualization/api/core/v1alpha2"
3332
)
3433

@@ -73,8 +72,14 @@ func (w *DataVolumeWatcher) Watch(mgr manager.Manager, ctr controller.Controller
7372
return true
7473
}
7574

76-
dvRunning := service.GetDataVolumeCondition(cdiv1.DataVolumeRunning, e.ObjectNew.Status.Conditions)
77-
return dvRunning != nil && (dvRunning.Reason == "Error" || dvRunning.Reason == "ImagePullFailed")
75+
oldDVRunning, _ := conditions.GetDataVolumeCondition(conditions.DVRunningConditionType, e.ObjectOld.Status.Conditions)
76+
newDVRunning, _ := conditions.GetDataVolumeCondition(conditions.DVRunningConditionType, e.ObjectNew.Status.Conditions)
77+
78+
if oldDVRunning.Reason != newDVRunning.Reason {
79+
return true
80+
}
81+
82+
return newDVRunning.Reason == "Error" || newDVRunning.Reason == "ImagePullFailed"
7883
},
7984
},
8085
),

0 commit comments

Comments
 (0)