Skip to content

Commit 85dedd3

Browse files
committed
feat(api): add saving and restoring VD's ownerref
Signed-off-by: Dmitry Lopatin <dmitry.lopatin@flant.com>
1 parent 440fb14 commit 85dedd3

File tree

7 files changed

+110
-3
lines changed

7 files changed

+110
-3
lines changed

images/virtualization-artifact/pkg/common/annotations/annotations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ const (
197197
AnnVirtualDiskOriginalAnnotations = AnnAPIGroupV + "/vd-original-annotations"
198198
// AnnVirtualDiskOriginalLabels is the annotation for storing original VirtualDisk labels.
199199
AnnVirtualDiskOriginalLabels = AnnAPIGroupV + "/vd-original-labels"
200+
// AnnVirtualDiskHadOwnerReference is the annotation on VolumeSnapshot set to "true" when the source VirtualDisk had an owner reference at snapshot time; absent otherwise.
201+
AnnVirtualDiskHadOwnerReference = AnnAPIGroupV + "/vd-had-owner-reference"
200202
// AnnVMOPUID is an annotation on vmop that represents name of VMOP.
201203
AnnVMOPUID = AnnAPIGroupV + "/vmop-uid"
202204
// AnnVMOPSnapshotName is an annotation on vmop that represents name a snapshot created for VMOP.

images/virtualization-artifact/pkg/controller/service/restorer/common/common.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ var (
3333
ErrAlreadyInUse = errors.New("already in use")
3434
ErrRestoring = errors.New("will be restored")
3535
ErrUpdating = errors.New("will be updated")
36+
ErrQueueing = errors.New("will be queued")
3637
ErrWaitingForDeletion = errors.New("waiting for deletion to complete")
3738
ErrVMNotInMaintenance = errors.New("the virtual machine is not in maintenance mode")
3839
ErrVMMaintenanceCondNotFound = errors.New("the virtual machine maintenance condition is not found")

images/virtualization-artifact/pkg/controller/service/restorer/snapshot_resources.go

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,20 @@ func (r *SnapshotResources) Process(ctx context.Context) ([]v1alpha2.SnapshotRes
275275
return r.statuses, errors.New("fail to process the resources: check the status")
276276
}
277277

278+
vmKey, vdKeys := r.getRestoredVMAndVDKeys()
279+
vm := &v1alpha2.VirtualMachine{}
280+
if err := r.client.Get(ctx, vmKey, vm); err != nil {
281+
if apierrors.IsNotFound(err) {
282+
return r.statuses, common.ErrQueueing
283+
}
284+
return r.statuses, fmt.Errorf("failed to get virtual machine %s: %w", vmKey, err)
285+
}
286+
for _, vdKey := range vdKeys {
287+
if err := r.setOwnerRefOnVirtualDisk(ctx, vm, vdKey); err != nil {
288+
return r.statuses, err
289+
}
290+
}
291+
278292
return r.statuses, nil
279293
}
280294

@@ -338,7 +352,7 @@ func getVirtualDisks(ctx context.Context, client client.Client, vmSnapshot *v1al
338352
}
339353

340354
if vdSnapshot == nil {
341-
return nil, fmt.Errorf("the virtual disk snapshot %q %w", vdSnapshotName, common.ErrVirtualDiskSnapshotNotFound)
355+
return nil, fmt.Errorf("failed to get the virtual disk snapshot %q: %w", vdSnapshotName, common.ErrVirtualDiskSnapshotNotFound)
342356
}
343357

344358
vd := v1alpha2.VirtualDisk{
@@ -368,7 +382,7 @@ func getVirtualDisks(ctx context.Context, client client.Client, vmSnapshot *v1al
368382

369383
err = AddOriginalMetadata(ctx, &vd, vdSnapshot, client)
370384
if err != nil {
371-
return nil, fmt.Errorf("add original metadata: %w", err)
385+
return nil, fmt.Errorf("failed to add original metadata: %w", err)
372386
}
373387

374388
vds = append(vds, &vd)
@@ -381,6 +395,77 @@ func (r *SnapshotResources) GetObjectHandlers() []ObjectHandler {
381395
return r.objectHandlers
382396
}
383397

398+
func (r *SnapshotResources) getRestoredVMAndVDKeys() (types.NamespacedName, []types.NamespacedName) {
399+
var vmKey types.NamespacedName
400+
vdKeys := make([]types.NamespacedName, 0)
401+
for _, ov := range r.objectHandlers {
402+
obj := ov.Object()
403+
kind := obj.GetObjectKind().GroupVersionKind().Kind
404+
key := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetName()}
405+
switch kind {
406+
case v1alpha2.VirtualMachineKind:
407+
vmKey = key
408+
case v1alpha2.VirtualDiskKind:
409+
vdKeys = append(vdKeys, key)
410+
}
411+
}
412+
return vmKey, vdKeys
413+
}
414+
415+
func (r *SnapshotResources) setOwnerRefOnVirtualDisk(ctx context.Context, vm *v1alpha2.VirtualMachine, vdKey types.NamespacedName) error {
416+
vd := &v1alpha2.VirtualDisk{}
417+
if err := r.client.Get(ctx, vdKey, vd); err != nil {
418+
if apierrors.IsNotFound(err) {
419+
return common.ErrQueueing
420+
}
421+
return fmt.Errorf("failed to get virtual disk %s: %w", vdKey, err)
422+
}
423+
424+
if vd.Spec.DataSource == nil || vd.Spec.DataSource.ObjectRef == nil {
425+
return nil
426+
}
427+
428+
if vd.Annotations[annotations.AnnVMOPRestore] == r.uuid && len(vd.OwnerReferences) > 0 {
429+
return nil
430+
}
431+
432+
vdSnapshotName := vd.Spec.DataSource.ObjectRef.Name
433+
vdSnapshotKey := types.NamespacedName{Namespace: vd.Namespace, Name: vdSnapshotName}
434+
vdSnapshot := &v1alpha2.VirtualDiskSnapshot{}
435+
if err := r.client.Get(ctx, vdSnapshotKey, vdSnapshot); err != nil {
436+
return fmt.Errorf("failed to get virtual disk snapshot %s: %w", vdSnapshotKey, err)
437+
}
438+
if vdSnapshot.Status.VolumeSnapshotName == "" {
439+
return nil
440+
}
441+
442+
vsKey := types.NamespacedName{Namespace: vd.Namespace, Name: vdSnapshot.Status.VolumeSnapshotName}
443+
vs := &vsv1.VolumeSnapshot{}
444+
if err := r.client.Get(ctx, vsKey, vs); err != nil {
445+
return fmt.Errorf("failed to get volume snapshot %s: %w", vsKey, err)
446+
}
447+
448+
_, ok := vs.Annotations[annotations.AnnVirtualDiskHadOwnerReference]
449+
if !ok {
450+
return nil
451+
}
452+
453+
vd.OwnerReferences = append(vd.OwnerReferences, metav1.OwnerReference{
454+
APIVersion: v1alpha2.SchemeGroupVersion.String(),
455+
Kind: v1alpha2.VirtualMachineKind,
456+
Name: vm.Name,
457+
UID: vm.UID,
458+
})
459+
if err := r.client.Update(ctx, vd); err != nil {
460+
if apierrors.IsConflict(err) {
461+
return common.ErrQueueing
462+
}
463+
return err
464+
}
465+
466+
return nil
467+
}
468+
384469
func AddOriginalMetadata(ctx context.Context, vd *v1alpha2.VirtualDisk, vdSnapshot *v1alpha2.VirtualDiskSnapshot, client client.Client) error {
385470
vsKey := types.NamespacedName{
386471
Namespace: vdSnapshot.Namespace,
@@ -389,7 +474,7 @@ func AddOriginalMetadata(ctx context.Context, vd *v1alpha2.VirtualDisk, vdSnapsh
389474

390475
vs, err := object.FetchObject(ctx, vsKey, client, &vsv1.VolumeSnapshot{})
391476
if err != nil {
392-
return fmt.Errorf("fetch the volume snapshot %q: %w", vsKey.Name, err)
477+
return fmt.Errorf("failed to fetch the volume snapshot %q: %w", vsKey.Name, err)
393478
}
394479

395480
if vs == nil {

images/virtualization-artifact/pkg/controller/vdsnapshot/internal/life_cycle.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,13 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vdSnapshot *v1alpha2.Virtu
335335
}
336336
}
337337

338+
for _, ownerRef := range vd.OwnerReferences {
339+
if ownerRef.Kind == v1alpha2.VirtualMachineKind {
340+
anno[annotations.AnnVirtualDiskHadOwnerReference] = "true"
341+
break
342+
}
343+
}
344+
338345
vs = &vsv1.VolumeSnapshot{
339346
ObjectMeta: metav1.ObjectMeta{
340347
Annotations: anno,

images/virtualization-artifact/pkg/controller/vmop/snapshot/internal/step/process_clone_step.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/deckhouse/virtualization-controller/pkg/common/annotations"
2929
"github.com/deckhouse/virtualization-controller/pkg/common/object"
3030
"github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer"
31+
"github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer/common"
3132
"github.com/deckhouse/virtualization-controller/pkg/eventrecord"
3233
"github.com/deckhouse/virtualization/api/core/v1alpha2"
3334
)
@@ -102,6 +103,9 @@ func (s ProcessCloneStep) Take(ctx context.Context, vmop *v1alpha2.VirtualMachin
102103
statuses, err = snapshotResources.Process(ctx)
103104
vmop.Status.Resources = statuses
104105
if err != nil {
106+
if errors.Is(err, common.ErrQueueing) {
107+
return &reconcile.Result{}, nil
108+
}
105109
return &reconcile.Result{}, err
106110
}
107111

images/virtualization-artifact/pkg/controller/vmop/snapshot/internal/step/process_restore_step.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
"github.com/deckhouse/virtualization-controller/pkg/common/object"
3030
"github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
3131
"github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer"
32+
"github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer/common"
3233
"github.com/deckhouse/virtualization-controller/pkg/eventrecord"
3334
"github.com/deckhouse/virtualization/api/core/v1alpha2"
3435
"github.com/deckhouse/virtualization/api/core/v1alpha2/vmopcondition"
@@ -95,6 +96,9 @@ func (s ProcessRestoreStep) Take(ctx context.Context, vmop *v1alpha2.VirtualMach
9596
statuses, err = snapshotResources.Process(ctx)
9697
vmop.Status.Resources = statuses
9798
if err != nil {
99+
if errors.Is(err, common.ErrQueueing) {
100+
return &reconcile.Result{}, nil
101+
}
98102
return &reconcile.Result{}, err
99103
}
100104

images/virtualization-artifact/pkg/controller/vmsop/internal/handler/lifecycle.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/deckhouse/virtualization-controller/pkg/common/object"
3232
"github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
3333
"github.com/deckhouse/virtualization-controller/pkg/controller/service"
34+
"github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer/common"
3435
"github.com/deckhouse/virtualization-controller/pkg/eventrecord"
3536
"github.com/deckhouse/virtualization/api/core/v1alpha2"
3637
"github.com/deckhouse/virtualization/api/core/v1alpha2/vmsopcondition"
@@ -115,6 +116,9 @@ func (h *LifecycleHandler) Handle(ctx context.Context, vmsop *v1alpha2.VirtualMa
115116

116117
err = h.opExecutor.Execute(ctx, vmsop, vms, restorerSecret)
117118
if err != nil {
119+
if errors.Is(err, common.ErrQueueing) {
120+
return reconcile.Result{Requeue: true}, nil
121+
}
118122
h.setFailedCondition(cb, vmsop, vmsopcondition.ReasonOperationFailed, fmt.Errorf("%s is failed: %w", vmsop.Spec.Type, err).Error())
119123
} else {
120124
msg := "VirtualMachineSnapshotOperation completed"

0 commit comments

Comments
 (0)