-
Notifications
You must be signed in to change notification settings - Fork 3
fix(vd): prevent VirtualDisk from stuck in WaitForFirstConsumer phase when VM is attached #1516
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
base: main
Are you sure you want to change the base?
Changes from all commits
1909f13
d10efe4
6ceef9b
a79f8e9
99d306c
095eb4c
2f17c96
d910056
253200e
33dd5f1
d4cdc27
99449cc
af28afe
01626ea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -126,13 +126,18 @@ func (s WaitForDVStep) setForProvisioning(vd *v1alpha2.VirtualDisk) (set bool) { | |
| } | ||
|
|
||
| func (s WaitForDVStep) setForFirstConsumerIsAwaited(ctx context.Context, vd *v1alpha2.VirtualDisk) (set bool, err error) { | ||
| if vd.Status.StorageClassName == "" { | ||
| return false, nil | ||
| } | ||
|
|
||
| sc, err := object.FetchObject(ctx, types.NamespacedName{Name: vd.Status.StorageClassName}, s.client, &storagev1.StorageClass{}) | ||
| if err != nil { | ||
| return false, fmt.Errorf("get sc: %w", err) | ||
| } | ||
|
|
||
| dvRunningCond, _ := conditions.GetDataVolumeCondition(conditions.DVRunningConditionType, s.dv.Status.Conditions) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Consider checking for nil dvRunningCond before accessing its fields. Accessing dvRunningCond.Status or dvRunningCond.Reason without a nil check may cause a panic if GetDataVolumeCondition returns nil. Please add a nil check to prevent this. |
||
| isWFFC := sc != nil && sc.VolumeBindingMode != nil && *sc.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer | ||
| if isWFFC && (s.dv.Status.Phase == cdiv1.PendingPopulation || s.dv.Status.Phase == cdiv1.WaitForFirstConsumer) { | ||
| if isWFFC && (s.dv.Status.Phase == cdiv1.PendingPopulation || s.dv.Status.Phase == cdiv1.WaitForFirstConsumer) && dvRunningCond.Status == corev1.ConditionFalse && dvRunningCond.Reason == "" { | ||
| vd.Status.Phase = v1alpha2.DiskWaitForFirstConsumer | ||
| s.cb. | ||
| Status(metav1.ConditionFalse). | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -73,6 +73,13 @@ func (w *DataVolumeWatcher) Watch(mgr manager.Manager, ctr controller.Controller | |
| return true | ||
| } | ||
|
|
||
| oldDVRunning, _ := conditions.GetDataVolumeCondition(conditions.DVRunningConditionType, e.ObjectOld.Status.Conditions) | ||
| newDVRunning, _ := conditions.GetDataVolumeCondition(conditions.DVRunningConditionType, e.ObjectNew.Status.Conditions) | ||
|
|
||
| if oldDVRunning.Reason != newDVRunning.Reason { | ||
|
Comment on lines
+76
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Potential nil dereference if oldDVRunning or newDVRunning is nil. Add nil checks for oldDVRunning and newDVRunning before accessing their Reason fields to prevent panics. |
||
| return true | ||
| } | ||
|
|
||
| dvRunning := service.GetDataVolumeCondition(cdiv1.DataVolumeRunning, e.ObjectNew.Status.Conditions) | ||
| return dvRunning != nil && (dvRunning.Reason == "Error" || dvRunning.Reason == "ImagePullFailed") | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,8 +21,11 @@ import ( | |
| "fmt" | ||
| "strings" | ||
|
|
||
| storagev1 "k8s.io/api/storage/v1" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/types" | ||
|
|
||
| "github.com/deckhouse/virtualization-controller/pkg/common/object" | ||
| "github.com/deckhouse/virtualization-controller/pkg/controller/conditions" | ||
| "github.com/deckhouse/virtualization-controller/pkg/controller/vm/internal/state" | ||
| "github.com/deckhouse/virtualization-controller/pkg/logger" | ||
|
|
@@ -54,8 +57,17 @@ func (h *BlockDeviceHandler) checkVirtualDisksToBeWFFC(ctx context.Context, s st | |
| } | ||
|
|
||
| for _, vd := range vds { | ||
| if vd.Status.Phase == v1alpha2.DiskWaitForFirstConsumer { | ||
| return true, nil | ||
| scName := vd.Status.StorageClassName | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we check the SC type of the disk in VM? Why can't we trust the VD phase? |
||
| sc, err := object.FetchObject(ctx, types.NamespacedName{Name: scName}, h.client, &storagev1.StorageClass{}) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Consider handling the case where scName is empty before fetching the StorageClass. A guard clause for empty scName would avoid unnecessary API calls and reduce confusion from attempting to fetch a StorageClass with no name. |
||
| if err != nil { | ||
| return false, fmt.Errorf("fetch storage class %s: %w", scName, err) | ||
| } | ||
|
|
||
| if sc != nil && sc.VolumeBindingMode != nil && *sc.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer { | ||
|
Comment on lines
+60
to
+66
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Consider handling missing or empty StorageClassName more explicitly. If vd.Status.StorageClassName is empty, FetchObject will try to fetch a storage class with an empty name, which could cause errors or unnecessary log entries. Consider adding a check to handle this case before calling FetchObject. |
||
| readyCondition, _ := conditions.GetCondition(vdcondition.ReadyType, vd.Status.Conditions) | ||
| if readyCondition.Status != metav1.ConditionTrue { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Check for nil readyCondition before accessing Status. Add a nil check for readyCondition before accessing its Status to prevent a potential panic. |
||
| return true, nil | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (bug_risk): Missing nil check for dvRunningCond could lead to panics.
Add a nil check for dvRunningCond before accessing its fields to prevent potential panics.