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..dc1e5e915a 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 { - return fmt.Errorf("error updating status subresource: %w", err) + + jsonPatch := client.RawPatch(types.JSONPatchType, patchBytes) + if err := r.client.Patch(ctx, kvvmi.Current(), jsonPatch); err != nil { + return fmt.Errorf("error patching status field: %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..8c16335caa 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, nil + } + 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() }