diff --git a/images/virtualization-artifact/pkg/common/vdsnapshot/vdsnapshot.go b/images/virtualization-artifact/pkg/common/vdsnapshot/vdsnapshot.go new file mode 100644 index 0000000000..9154c9d3f4 --- /dev/null +++ b/images/virtualization-artifact/pkg/common/vdsnapshot/vdsnapshot.go @@ -0,0 +1,72 @@ +/* +Copyright 2025 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vdsnapshot + +import ( + "encoding/json" + "fmt" + + vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" + + "github.com/deckhouse/virtualization-controller/pkg/common/annotations" + "github.com/deckhouse/virtualization/api/core/v1alpha2" +) + +// AddOriginalMetadata adds original annotations and labels from VolumeSnapshot to VirtualDisk, +// without overwriting existing values +func AddOriginalMetadata(vd *v1alpha2.VirtualDisk, vs *vsv1.VolumeSnapshot) error { + var ( + labelsMap map[string]string + annotationsMap map[string]string + ) + + if vs != nil && vs.Annotations != nil { + if vs.Annotations[annotations.AnnVirtualDiskOriginalLabels] != "" { + err := json.Unmarshal([]byte(vs.Annotations[annotations.AnnVirtualDiskOriginalLabels]), &labelsMap) + if err != nil { + return fmt.Errorf("failed to unmarshal the original labels: %w", err) + } + } + + if vd.Labels == nil { + vd.Labels = make(map[string]string) + } + for key, value := range labelsMap { + if _, exists := vd.Labels[key]; !exists { + vd.Labels[key] = value + } + } + + if vs.Annotations[annotations.AnnVirtualDiskOriginalAnnotations] != "" { + err := json.Unmarshal([]byte(vs.Annotations[annotations.AnnVirtualDiskOriginalAnnotations]), &annotationsMap) + if err != nil { + return fmt.Errorf("failed to unmarshal the original annotations: %w", err) + } + } + + if vd.Annotations == nil { + vd.Annotations = make(map[string]string) + } + for key, value := range labelsMap { + if _, exists := vd.Annotations[key]; !exists { + vd.Annotations[key] = value + } + } + } + + return nil +} diff --git a/images/virtualization-artifact/pkg/controller/service/restorer/snapshot_resources.go b/images/virtualization-artifact/pkg/controller/service/restorer/snapshot_resources.go index fdb401e470..1b825b8481 100644 --- a/images/virtualization-artifact/pkg/controller/service/restorer/snapshot_resources.go +++ b/images/virtualization-artifact/pkg/controller/service/restorer/snapshot_resources.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" + vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,6 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/deckhouse/virtualization-controller/pkg/common/object" + commonvdsnapshot "github.com/deckhouse/virtualization-controller/pkg/common/vdsnapshot" "github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer/common" restorer "github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer/restorers" "github.com/deckhouse/virtualization/api/core/v1alpha2" @@ -363,6 +365,23 @@ func getVirtualDisks(ctx context.Context, client client.Client, vmSnapshot *v1al }, } + if vdSnapshot.Status.VolumeSnapshotName != "" { + vsKey := types.NamespacedName{ + Namespace: vdSnapshot.Namespace, + Name: vdSnapshot.Status.VolumeSnapshotName, + } + + vs, err := object.FetchObject(ctx, vsKey, client, &vsv1.VolumeSnapshot{}) + if err != nil { + return nil, fmt.Errorf("failed to fetch the volume snapshot %q: %w", vsKey.Name, err) + } + + err = commonvdsnapshot.AddOriginalMetadata(&vd, vs) + if err != nil { + return nil, fmt.Errorf("failed to add original metadata: %w", err) + } + } + vds = append(vds, &vd) } diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/source/step/create_pvc_from_vdsnapshot_step.go b/images/virtualization-artifact/pkg/controller/vd/internal/source/step/create_pvc_from_vdsnapshot_step.go index 955c9fd662..be0ea0357b 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/source/step/create_pvc_from_vdsnapshot_step.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/source/step/create_pvc_from_vdsnapshot_step.go @@ -18,7 +18,6 @@ package step import ( "context" - "encoding/json" "fmt" "strings" @@ -35,6 +34,7 @@ import ( "github.com/deckhouse/virtualization-controller/pkg/common/annotations" "github.com/deckhouse/virtualization-controller/pkg/common/object" "github.com/deckhouse/virtualization-controller/pkg/common/pointer" + commonvdsnapshot "github.com/deckhouse/virtualization-controller/pkg/common/vdsnapshot" "github.com/deckhouse/virtualization-controller/pkg/controller/conditions" "github.com/deckhouse/virtualization-controller/pkg/controller/service" vdsupplements "github.com/deckhouse/virtualization-controller/pkg/controller/vd/internal/supplements" @@ -137,41 +137,12 @@ func (s CreatePVCFromVDSnapshotStep) Take(ctx context.Context, vd *v1alpha2.Virt vd.Status.SourceUID = pointer.GetPointer(vdSnapshot.UID) vdsupplements.SetPVCName(vd, pvc.Name) - s.AddOriginalMetadata(vd, vs) - return nil, nil -} - -// AddOriginalMetadata adds original annotations and labels from VolumeSnapshot to VirtualDisk, -// without overwriting existing values -func (s CreatePVCFromVDSnapshotStep) AddOriginalMetadata(vd *v1alpha2.VirtualDisk, vs *vsv1.VolumeSnapshot) { - if vd.Annotations == nil { - vd.Annotations = make(map[string]string) - } - if vd.Labels == nil { - vd.Labels = make(map[string]string) - } - - if annotationsJSON := vs.Annotations[annotations.AnnVirtualDiskOriginalAnnotations]; annotationsJSON != "" { - var originalAnnotations map[string]string - if err := json.Unmarshal([]byte(annotationsJSON), &originalAnnotations); err == nil { - for key, value := range originalAnnotations { - if _, exists := vd.Annotations[key]; !exists { - vd.Annotations[key] = value - } - } - } + err = commonvdsnapshot.AddOriginalMetadata(vd, vs) + if err != nil { + return nil, fmt.Errorf("failed to add original metadata: %w", err) } - if labelsJSON := vs.Annotations[annotations.AnnVirtualDiskOriginalLabels]; labelsJSON != "" { - var originalLabels map[string]string - if err := json.Unmarshal([]byte(labelsJSON), &originalLabels); err == nil { - for key, value := range originalLabels { - if _, exists := vd.Labels[key]; !exists { - vd.Labels[key] = value - } - } - } - } + return nil, nil } func (s CreatePVCFromVDSnapshotStep) buildPVC(vd *v1alpha2.VirtualDisk, vs *vsv1.VolumeSnapshot) *corev1.PersistentVolumeClaim {