Skip to content

Conversation

yaroslavborbat
Copy link
Member

@yaroslavborbat yaroslavborbat commented Oct 14, 2025

Description

Improve VMOp migration condition

This PR enhances the migration condition reporting for VM operations.
It adds more detailed and descriptive messages when a migration fails — for example:

  • the migration pod was deleted after a timeout because it couldn’t be scheduled on any node,
  • or other specific reasons observed during the migration process.

These improvements make it easier to diagnose and understand the cause of migration failures.

Why do we need it, and what problem does it solve?

What is the expected result?

Checklist

  • The code is covered by unit tests.
  • e2e tests passed.
  • Documentation updated according to the changes.
  • Changes were tested in the Kubernetes cluster manually.

Changelog entries

section: vmop
type: feature
summary: Improve vmop migration condition. Adds more detailed and descriptive messages when a migration fails.

Copy link
Contributor

sourcery-ai bot commented Oct 14, 2025

Reviewer's Guide

Enhance VMOP migration conditions by introducing dynamic messaging based on migration failure reasons and pod scheduling status, refactoring event logging, updating dependencies, and applying minor handler and build config adjustments.

Sequence diagram for dynamic migration condition messaging

sequenceDiagram
participant H as LifecycleHandler
participant M as VirtualMachineInstanceMigration
participant P as Pod
participant C as Conditions
H->>M: getConditionCompletedMessageByReason(ctx, reason, mig)
H->>M: getTargetPod(ctx, mig)
M-->>H: returns Pod
H->>P: isPodPendingUnschedulable(pod)
P-->>H: returns bool
H->>C: SetCondition with dynamic message
Loading

Class diagram for updated LifecycleHandler methods

classDiagram
class LifecycleHandler {
  +syncOperationComplete(ctx, vmop)
  +execute(ctx, vmop)
  +getTargetPod(ctx, mig)
  +getConditionCompletedMessageByReason(ctx, reason, mig)
}
class virtv1.VirtualMachineInstanceMigration {
  +Status
  +UID
  +Namespace
}
class corev1.Pod {
  +Status
  +Namespace
  +Name
  +DeletionTimestamp
}
LifecycleHandler --> virtv1.VirtualMachineInstanceMigration : uses
LifecycleHandler --> corev1.Pod : uses
LifecycleHandler : getTargetPod returns Pod
LifecycleHandler : getConditionCompletedMessageByReason uses getTargetPod
LifecycleHandler : syncOperationComplete uses getConditionCompletedMessageByReason
LifecycleHandler : execute uses getConditionCompletedMessageByReason
Loading

Class diagram for new helper functions related to migration conditions

classDiagram
class getMessageByMigrationFailedReason {
  +mig: VirtualMachineInstanceMigration
  +returns: string
}
class isPodPendingUnschedulable {
  +pod: Pod
  +returns: bool
}
getMessageByMigrationFailedReason --> virtv1.VirtualMachineInstanceMigration : parameter
isPodPendingUnschedulable --> corev1.Pod : parameter
LifecycleHandler ..> getMessageByMigrationFailedReason : uses
LifecycleHandler ..> isPodPendingUnschedulable : uses
Loading

Class diagram for MigratingHandler syncMigrating update

classDiagram
class MigratingHandler {
  +syncMigrating(ctx, s)
}
class completed {
  +Message: string
}
MigratingHandler --> completed : uses
Loading

File-Level Changes

Change Details Files
Consolidated migration failure reason handling
  • Added getMessageByMigrationFailedReason helper to map failure reasons to user-friendly messages
  • Integrated additional failure reason message into syncOperationComplete logic
images/virtualization-artifact/pkg/controller/vmop/migration/internal/handler/lifecycle.go
Dynamic completed condition messaging based on migration state and pod scheduling
  • Introduced getConditionCompletedMessageByReason to build context-aware messages
  • Implemented getTargetPod and isPodPendingUnschedulable to detect unschedulable pods
  • Replaced static ‘Wait…’ messages with dynamic outputs in syncOperationComplete and execute
images/virtualization-artifact/pkg/controller/vmop/migration/internal/handler/lifecycle.go
Encapsulated event logging logic
  • Scoped VMOPInProgress event recorder calls inside a dedicated block for clarity
images/virtualization-artifact/pkg/controller/vmop/migration/internal/handler/lifecycle.go
Dependency and component version updates
  • Bumped kubevirt.io/api replace version in go.mod
  • Updated 3p-kubevirt version in build/components/versions.yml
images/virtualization-artifact/go.mod
build/components/versions.yml
Minor migrating handler and build config adjustments
  • Adjusted migrating handler to use actual completed.Message for failure cases
  • Added fromCacheVersion entry in werf.inc.yaml
images/virtualization-artifact/pkg/controller/vm/internal/migrating.go
images/virt-artifact/werf.inc.yaml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@yaroslavborbat yaroslavborbat added this to the v1.2.0 milestone Oct 14, 2025
@Isteb4k Isteb4k modified the milestones: v1.2.0, v1.1.1 Oct 14, 2025
@yaroslavborbat yaroslavborbat force-pushed the feat/vmop/improve-migration-conditions branch from e2fc1e8 to d4cedd3 Compare October 14, 2025 13:21
@nevermarine nevermarine modified the milestones: v1.1.1, v1.2.0 Oct 16, 2025
@yaroslavborbat yaroslavborbat force-pushed the feat/vmop/improve-migration-conditions branch from da078fe to 9bbe400 Compare October 21, 2025 09:13
@yaroslavborbat yaroslavborbat marked this pull request as ready for review October 21, 2025 12:57
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • The new pod lookup and unschedulable-check logic in LifecycleHandler could be extracted into a dedicated helper or service to keep the handler focused on orchestration and improve testability.
  • Consider centralizing the dynamic condition message templates (including punctuation) in one place to ensure consistency and simplify future updates or localizations.
  • The getTargetPod method issues a direct list call on every reconcile; you might optimize it by leveraging a cached informer or limiting API calls in high-frequency paths.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new pod lookup and unschedulable-check logic in LifecycleHandler could be extracted into a dedicated helper or service to keep the handler focused on orchestration and improve testability.
- Consider centralizing the dynamic condition message templates (including punctuation) in one place to ensure consistency and simplify future updates or localizations.
- The getTargetPod method issues a direct list call on every reconcile; you might optimize it by leveraging a cached informer or limiting API calls in high-frequency paths.

## Individual Comments

### Comment 1
<location> `images/virtualization-artifact/pkg/controller/vmop/migration/internal/handler/lifecycle.go:519-520` </location>
<code_context>
 	virtv1.MigrationFailed:      vmopcondition.ReasonOperationFailed,
 }
+
+func getMessageByMigrationFailedReason(mig *virtv1.VirtualMachineInstanceMigration) string {
+	cond, found := conditions.GetKVVMIMCondition(virtv1.VirtualMachineInstanceMigrationFailed, mig.Status.Conditions)
+
</code_context>

<issue_to_address>
**suggestion:** Consider handling nil mig defensively in getMessageByMigrationFailedReason.

Accessing mig.Status.Conditions without checking if mig is nil can cause a panic. Add a nil check at the start of the function to prevent this.

```suggestion
func getMessageByMigrationFailedReason(mig *virtv1.VirtualMachineInstanceMigration) string {
	if mig == nil {
		return "migration object is nil"
	}
	cond, found := conditions.GetKVVMIMCondition(virtv1.VirtualMachineInstanceMigrationFailed, mig.Status.Conditions)
```
</issue_to_address>

### Comment 2
<location> `images/virtualization-artifact/pkg/controller/vmop/migration/internal/handler/lifecycle.go:584-586` </location>
<code_context>
+	return false
+}
+
+func (h LifecycleHandler) getConditionCompletedMessageByReason(ctx context.Context, reason vmopcondition.ReasonCompleted, mig *virtv1.VirtualMachineInstanceMigration) (string, error) {
+	msg := "Wait until operation is completed"
+	if reason == vmopcondition.ReasonMigrationPending || reason == vmopcondition.ReasonMigrationPrepareTarget {
</code_context>

<issue_to_address>
**suggestion:** Consider including more context in the unschedulable pod message.

Including the specific scheduling error or reason, if available, would make the message more informative for debugging and user feedback.

```suggestion
		if isPodPendingUnschedulable(pod) {
			unschedulableMsg := ""
			for _, cond := range pod.Status.Conditions {
				if cond.Type == corev1.PodScheduled &&
					cond.Status == corev1.ConditionFalse &&
					cond.Reason == corev1.PodReasonUnschedulable {
					unschedulableMsg = cond.Message
					break
				}
			}
			if unschedulableMsg != "" {
				msg += fmt.Sprintf(" (target pod is unschedulable: %s/%s, reason: %q)", pod.Namespace, pod.Name, unschedulableMsg)
			} else {
				msg += fmt.Sprintf(" (target pod is unschedulable: %s/%s)", pod.Namespace, pod.Name)
			}
		}
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Signed-off-by: Yaroslav Borbat <[email protected]>
@yaroslavborbat yaroslavborbat force-pushed the feat/vmop/improve-migration-conditions branch from 5152274 to 14449b5 Compare October 21, 2025 13:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants