From 329c128279651bf17cb425e8591b9bb90185b330 Mon Sep 17 00:00:00 2001 From: Lyndon-Li Date: Thu, 19 Oct 2023 11:45:58 +0800 Subject: [PATCH] issue 6964: get volume size from source PVC if it is invalid in VS Signed-off-by: Lyndon-Li --- changelogs/unreleased/6976-Lyndon-Li | 1 + pkg/controller/data_upload_controller.go | 1 + pkg/exposer/csi_snapshot.go | 13 ++++- pkg/exposer/csi_snapshot_test.go | 70 ++++++++++++++++++++---- 4 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 changelogs/unreleased/6976-Lyndon-Li diff --git a/changelogs/unreleased/6976-Lyndon-Li b/changelogs/unreleased/6976-Lyndon-Li new file mode 100644 index 0000000000..06cf694ade --- /dev/null +++ b/changelogs/unreleased/6976-Lyndon-Li @@ -0,0 +1 @@ +It is a valid case that the Status.RestoreSize field in VolumeSnapshot is not set, if so, get the volume size from the source PVC to create the backup PVC \ No newline at end of file diff --git a/pkg/controller/data_upload_controller.go b/pkg/controller/data_upload_controller.go index 8bc650f5f9..1a307b0d13 100644 --- a/pkg/controller/data_upload_controller.go +++ b/pkg/controller/data_upload_controller.go @@ -762,6 +762,7 @@ func (r *DataUploadReconciler) setupExposeParam(du *velerov2alpha1api.DataUpload HostingPodLabels: map[string]string{velerov1api.DataUploadLabel: du.Name}, AccessMode: accessMode, Timeout: du.Spec.OperationTimeout.Duration, + VolumeSize: pvc.Spec.Resources.Requests[corev1.ResourceStorage], }, nil } return nil, nil diff --git a/pkg/exposer/csi_snapshot.go b/pkg/exposer/csi_snapshot.go index 85f511524c..18350e0999 100644 --- a/pkg/exposer/csi_snapshot.go +++ b/pkg/exposer/csi_snapshot.go @@ -61,6 +61,9 @@ type CSISnapshotExposeParam struct { // Timeout specifies the time wait for resources operations in Expose Timeout time.Duration + + // VolumeSize specifies the size of the source volume + VolumeSize resource.Quantity } // CSISnapshotExposeWaitParam define the input param for WaitExposed of CSI snapshots @@ -156,7 +159,15 @@ func (e *csiSnapshotExposer) Expose(ctx context.Context, ownerObject corev1.Obje curLog.WithField("vsc name", backupVSC.Name).Infof("Backup VSC is created from %s", vsc.Name) - backupPVC, err := e.createBackupPVC(ctx, ownerObject, backupVS.Name, csiExposeParam.StorageClass, csiExposeParam.AccessMode, *volumeSnapshot.Status.RestoreSize) + var volumeSize resource.Quantity + if volumeSnapshot.Status.RestoreSize != nil && !volumeSnapshot.Status.RestoreSize.IsZero() { + volumeSize = *volumeSnapshot.Status.RestoreSize + } else { + volumeSize = csiExposeParam.VolumeSize + curLog.WithField("vs name", volumeSnapshot.Name).Warnf("The snapshot doesn't contain a valid restore size, use source volume's size %v", volumeSize) + } + + backupPVC, err := e.createBackupPVC(ctx, ownerObject, backupVS.Name, csiExposeParam.StorageClass, csiExposeParam.AccessMode, volumeSize) if err != nil { return errors.Wrap(err, "error to create backup pvc") } diff --git a/pkg/exposer/csi_snapshot_test.go b/pkg/exposer/csi_snapshot_test.go index 7ea6d5bf05..9bb3a40559 100644 --- a/pkg/exposer/csi_snapshot_test.go +++ b/pkg/exposer/csi_snapshot_test.go @@ -59,6 +59,8 @@ func TestExpose(t *testing.T) { }, } + var restoreSize int64 = 123456 + snapshotClass := "fake-snapshot-class" vsObject := &snapshotv1api.VolumeSnapshot{ ObjectMeta: metav1.ObjectMeta{ @@ -78,11 +80,31 @@ func TestExpose(t *testing.T) { Status: &snapshotv1api.VolumeSnapshotStatus{ BoundVolumeSnapshotContentName: &vscName, ReadyToUse: boolptr.True(), - RestoreSize: &resource.Quantity{}, + RestoreSize: resource.NewQuantity(restoreSize, ""), + }, + } + + vsObjectWithoutRestoreSize := &snapshotv1api.VolumeSnapshot{ + ObjectMeta: metav1.ObjectMeta{ + Name: "fake-vs", + Namespace: "fake-ns", + Annotations: map[string]string{ + "fake-key-1": "fake-value-1", + "fake-key-2": "fake-value-2", + }, + }, + Spec: snapshotv1api.VolumeSnapshotSpec{ + Source: snapshotv1api.VolumeSnapshotSource{ + VolumeSnapshotContentName: &vscName, + }, + VolumeSnapshotClassName: &snapshotClass, + }, + Status: &snapshotv1api.VolumeSnapshotStatus{ + BoundVolumeSnapshotContentName: &vscName, + ReadyToUse: boolptr.True(), }, } - var restoreSize int64 snapshotHandle := "fake-handle" vscObj := &snapshotv1api.VolumeSnapshotContent{ ObjectMeta: metav1.ObjectMeta{ @@ -116,14 +138,15 @@ func TestExpose(t *testing.T) { } tests := []struct { - name string - snapshotClientObj []runtime.Object - kubeClientObj []runtime.Object - ownerBackup *velerov1.Backup - exposeParam CSISnapshotExposeParam - snapReactors []reactor - kubeReactors []reactor - err string + name string + snapshotClientObj []runtime.Object + kubeClientObj []runtime.Object + ownerBackup *velerov1.Backup + exposeParam CSISnapshotExposeParam + snapReactors []reactor + kubeReactors []reactor + err string + expectedVolumeSize *resource.Quantity }{ { name: "wait vs ready fail", @@ -321,6 +344,25 @@ func TestExpose(t *testing.T) { daemonSet, }, }, + { + name: "restore size from exposeParam", + ownerBackup: backup, + exposeParam: CSISnapshotExposeParam{ + SnapshotName: "fake-vs", + SourceNamespace: "fake-ns", + AccessMode: AccessModeFileSystem, + Timeout: time.Millisecond, + VolumeSize: *resource.NewQuantity(567890, ""), + }, + snapshotClientObj: []runtime.Object{ + vsObjectWithoutRestoreSize, + vscObj, + }, + kubeClientObj: []runtime.Object{ + daemonSet, + }, + expectedVolumeSize: resource.NewQuantity(567890, ""), + }, } for _, test := range tests { @@ -360,7 +402,7 @@ func TestExpose(t *testing.T) { _, err = exposer.kubeClient.CoreV1().Pods(ownerObject.Namespace).Get(context.Background(), ownerObject.Name, metav1.GetOptions{}) assert.NoError(t, err) - _, err = exposer.kubeClient.CoreV1().PersistentVolumeClaims(ownerObject.Namespace).Get(context.Background(), ownerObject.Name, metav1.GetOptions{}) + backupPVC, err := exposer.kubeClient.CoreV1().PersistentVolumeClaims(ownerObject.Namespace).Get(context.Background(), ownerObject.Name, metav1.GetOptions{}) assert.NoError(t, err) expectedVS, err := exposer.csiSnapshotClient.VolumeSnapshots(ownerObject.Namespace).Get(context.Background(), ownerObject.Name, metav1.GetOptions{}) @@ -377,6 +419,12 @@ func TestExpose(t *testing.T) { assert.Equal(t, expectedVSC.Spec.DeletionPolicy, vscObj.Spec.DeletionPolicy) assert.Equal(t, expectedVSC.Spec.Driver, vscObj.Spec.Driver) assert.Equal(t, *expectedVSC.Spec.VolumeSnapshotClassName, *vscObj.Spec.VolumeSnapshotClassName) + + if test.expectedVolumeSize != nil { + assert.Equal(t, *test.expectedVolumeSize, backupPVC.Spec.Resources.Requests[corev1.ResourceStorage]) + } else { + assert.Equal(t, *resource.NewQuantity(restoreSize, ""), backupPVC.Spec.Resources.Requests[corev1.ResourceStorage]) + } } else { assert.EqualError(t, err, test.err) }