From 26d9b4f297631c1e11bbf9c9de41cb22ea41f48a Mon Sep 17 00:00:00 2001 From: Yaroslav Borbat Date: Tue, 13 May 2025 23:12:53 +0300 Subject: [PATCH 1/3] fix Signed-off-by: Yaroslav Borbat --- .../live_migration_reconciler.go | 15 +++++++-- .../livemigration/migration_configuration.go | 31 ++++++++++--------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go b/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go index cb491b1ce3..a6f4b80cec 100644 --- a/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go @@ -20,6 +20,7 @@ import ( "context" "fmt" + "k8s.io/apimachinery/pkg/types" virtv1 "kubevirt.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" @@ -88,15 +89,23 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco return h.Handle(ctx, kvvmi.Changed()) }) rec.SetResourceUpdater(func(ctx context.Context) error { - if livemigration.IsMigrationConfigurationChanged(kvvmi.Current(), kvvmi.Changed()) { - // Directly update kvvmi and not use kvvmi.Update as kvvmi status is a regular field, not a subresource. + + patchBytes, err := livemigration.GenerateMigrationConfigurationPatch(kvvmi.Current(), kvvmi.Changed()) + if err != nil { + return err + } + + if patchBytes != nil { log.Debug("About to update changed kvvmi", "changed.migration.configuration", livemigration.DumpKVVMIMigrationConfiguration(kvvmi.Changed()), "current.migration.configuration", livemigration.DumpKVVMIMigrationConfiguration(kvvmi.Current()), ) - if err := r.client.Update(ctx, kvvmi.Changed()); err != nil { + + jsonPatch := client.RawPatch(types.JSONPatchType, patchBytes) + if err := r.client.Patch(ctx, kvvmi.Current(), jsonPatch); err != nil { return fmt.Errorf("error updating status subresource: %w", err) } + return nil } diff --git a/images/virtualization-artifact/pkg/livemigration/migration_configuration.go b/images/virtualization-artifact/pkg/livemigration/migration_configuration.go index 6b9bd0cdca..e73eb9264d 100644 --- a/images/virtualization-artifact/pkg/livemigration/migration_configuration.go +++ b/images/virtualization-artifact/pkg/livemigration/migration_configuration.go @@ -19,10 +19,12 @@ package livemigration import ( "encoding/json" "fmt" - "reflect" + "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/resource" virtv1 "kubevirt.io/api/core/v1" + + "github.com/deckhouse/virtualization-controller/pkg/common/patch" ) // Live migration defaults from kubevirt @@ -93,22 +95,21 @@ func DumpKVVMIMigrationConfiguration(kvvmi *virtv1.VirtualMachineInstance) strin return string(out) } -// IsMigrationConfigurationChanged detects if MigrationConfiguration was changed. -func IsMigrationConfigurationChanged(current, changed *virtv1.VirtualMachineInstance) bool { - // true if migrationConfiguration was added. - if current.Status.MigrationState != nil && current.Status.MigrationState.MigrationConfiguration == nil && - changed.Status.MigrationState != nil && changed.Status.MigrationState.MigrationConfiguration != nil { - return true +func GenerateMigrationConfigurationPatch(current, changed *virtv1.VirtualMachineInstance) ([]byte, error) { + if current.Status.MigrationState == nil || changed.Status.MigrationState == nil { + return nil, fmt.Errorf("MigrationState is not set") + } + currentConf := current.Status.MigrationState.MigrationConfiguration + changedConf := changed.Status.MigrationState.MigrationConfiguration + + if equality.Semantic.DeepEqual(currentConf, changedConf) { + return nil, nil } - // Compare MigrationConfiguration. Handler may change options. - if current.Status.MigrationState != nil && current.Status.MigrationState.MigrationConfiguration != nil && - changed.Status.MigrationState != nil && changed.Status.MigrationState.MigrationConfiguration != nil { - return !reflect.DeepEqual( - current.Status.MigrationState.MigrationConfiguration, - changed.Status.MigrationState.MigrationConfiguration, - ) + op := patch.PatchReplaceOp + if currentConf == nil { + op = patch.PatchAddOp } - return false + return patch.NewJsonPatch(patch.NewJsonPatchOperation(op, "/status/migrationState/migrationConfiguration", changedConf)).Bytes() } From 6aa170868b6a09ad8f2fc11b99663ce33ba01785 Mon Sep 17 00:00:00 2001 From: Yaroslav Borbat Date: Wed, 14 May 2025 09:54:49 +0300 Subject: [PATCH 2/3] fix Signed-off-by: Yaroslav Borbat --- .../pkg/livemigration/migration_configuration.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virtualization-artifact/pkg/livemigration/migration_configuration.go b/images/virtualization-artifact/pkg/livemigration/migration_configuration.go index e73eb9264d..8c16335caa 100644 --- a/images/virtualization-artifact/pkg/livemigration/migration_configuration.go +++ b/images/virtualization-artifact/pkg/livemigration/migration_configuration.go @@ -97,7 +97,7 @@ func DumpKVVMIMigrationConfiguration(kvvmi *virtv1.VirtualMachineInstance) strin func GenerateMigrationConfigurationPatch(current, changed *virtv1.VirtualMachineInstance) ([]byte, error) { if current.Status.MigrationState == nil || changed.Status.MigrationState == nil { - return nil, fmt.Errorf("MigrationState is not set") + return nil, nil } currentConf := current.Status.MigrationState.MigrationConfiguration changedConf := changed.Status.MigrationState.MigrationConfiguration From 0efa47895d68fd9eed853e98544ddcfb716649a3 Mon Sep 17 00:00:00 2001 From: Yaroslav Borbat <86148689+yaroslavborbat@users.noreply.github.com> Date: Wed, 14 May 2025 10:45:19 +0300 Subject: [PATCH 3/3] Update images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go Co-authored-by: Ivan Mikheykin Signed-off-by: Yaroslav Borbat <86148689+yaroslavborbat@users.noreply.github.com> --- .../pkg/controller/livemigration/live_migration_reconciler.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go b/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go index a6f4b80cec..dc1e5e915a 100644 --- a/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/livemigration/live_migration_reconciler.go @@ -103,7 +103,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (reco jsonPatch := client.RawPatch(types.JSONPatchType, patchBytes) if err := r.client.Patch(ctx, kvvmi.Current(), jsonPatch); err != nil { - return fmt.Errorf("error updating status subresource: %w", err) + return fmt.Errorf("error patching status field: %w", err) } return nil