Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cherry-pick][release-1.12]Add DataUpload Result and CSI VolumeSnapshot check for restore PV. #7087

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelogs/unreleased/7087-blackpiglet
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add DataUpload Result and CSI VolumeSnapshot check for restore PV.
5 changes: 5 additions & 0 deletions pkg/builder/volume_snapshot_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,8 @@ func (v *VolumeSnapshotBuilder) BoundVolumeSnapshotContentName(vscName string) *
v.object.Status.BoundVolumeSnapshotContentName = &vscName
return v
}

func (v *VolumeSnapshotBuilder) SourcePVC(name string) *VolumeSnapshotBuilder {
v.object.Spec.Source.PersistentVolumeClaimName = &name
return v
}
6 changes: 6 additions & 0 deletions pkg/controller/restore_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,11 @@
return errors.Wrap(err, "error fetching volume snapshots metadata")
}

csiVolumeSnapshots, err := backupStore.GetCSIVolumeSnapshots(restore.Spec.BackupName)
if err != nil {
return errors.Wrap(err, "fail to fetch CSI VolumeSnapshots metadata")
}

Check warning on line 521 in pkg/controller/restore_controller.go

View check run for this annotation

Codecov / codecov/patch

pkg/controller/restore_controller.go#L520-L521

Added lines #L520 - L521 were not covered by tests

restoreLog.Info("starting restore")

var podVolumeBackups []*api.PodVolumeBackup
Expand All @@ -531,6 +536,7 @@
BackupReader: backupFile,
ResourceModifiers: resourceModifiers,
DisableInformerCache: r.disableInformerCache,
CSIVolumeSnapshots: csiVolumeSnapshots,
}
restoreWarnings, restoreErrors := r.restorer.RestoreWithResolvers(restoreReq, actionsResolver, pluginManager)

Expand Down
2 changes: 2 additions & 0 deletions pkg/controller/restore_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"testing"
"time"

snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -471,6 +472,7 @@ func TestRestoreReconcile(t *testing.T) {
}
if test.expectedRestorerCall != nil {
backupStore.On("GetBackupContents", test.backup.Name).Return(io.NopCloser(bytes.NewReader([]byte("hello world"))), nil)
backupStore.On("GetCSIVolumeSnapshots", test.backup.Name).Return([]*snapshotv1api.VolumeSnapshot{}, nil)

restorer.On("RestoreWithResolvers", mock.Anything, mock.Anything, mock.Anything, mock.Anything,
mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(warnings, errors)
Expand Down
2 changes: 2 additions & 0 deletions pkg/restore/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"io"
"sort"

snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/runtime"

Expand Down Expand Up @@ -60,6 +61,7 @@ type Request struct {
itemOperationsList *[]*itemoperation.RestoreOperation
ResourceModifiers *resourcemodifiers.ResourceModifiers
DisableInformerCache bool
CSIVolumeSnapshots []*snapshotv1api.VolumeSnapshot
}

type restoredItemStatus struct {
Expand Down
94 changes: 91 additions & 3 deletions pkg/restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"time"

"github.com/google/uuid"
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -298,6 +299,7 @@
pvsToProvision: sets.NewString(),
pvRestorer: pvRestorer,
volumeSnapshots: req.VolumeSnapshots,
csiVolumeSnapshots: req.CSIVolumeSnapshots,
podVolumeBackups: req.PodVolumeBackups,
resourceTerminatingTimeout: kr.resourceTerminatingTimeout,
resourceTimeout: kr.resourceTimeout,
Expand Down Expand Up @@ -347,6 +349,7 @@
pvsToProvision sets.String
pvRestorer PVRestorer
volumeSnapshots []*volume.Snapshot
csiVolumeSnapshots []*snapshotv1api.VolumeSnapshot
podVolumeBackups []*velerov1api.PodVolumeBackup
resourceTerminatingTimeout time.Duration
resourceTimeout time.Duration
Expand Down Expand Up @@ -1287,23 +1290,59 @@
}

case hasPodVolumeBackup(obj, ctx):
ctx.log.Infof("Dynamically re-provisioning persistent volume because it has a pod volume backup to be restored.")
ctx.log.WithFields(logrus.Fields{
"namespace": obj.GetNamespace(),
"name": obj.GetName(),
"groupResource": groupResource.String(),
}).Infof("Dynamically re-provisioning persistent volume because it has a pod volume backup to be restored.")
ctx.pvsToProvision.Insert(name)

// Return early because we don't want to restore the PV itself, we
// want to dynamically re-provision it.
return warnings, errs, itemExists

Check warning on line 1302 in pkg/restore/restore.go

View check run for this annotation

Codecov / codecov/patch

pkg/restore/restore.go#L1293-L1302

Added lines #L1293 - L1302 were not covered by tests

case hasCSIVolumeSnapshot(ctx, obj):
ctx.log.WithFields(logrus.Fields{
"namespace": obj.GetNamespace(),
"name": obj.GetName(),
"groupResource": groupResource.String(),
}).Infof("Dynamically re-provisioning persistent volume because it has a related CSI VolumeSnapshot.")
ctx.pvsToProvision.Insert(name)

// Return early because we don't want to restore the PV itself, we
// want to dynamically re-provision it.
return warnings, errs, itemExists

case hasSnapshotDataUpload(ctx, obj):
ctx.log.WithFields(logrus.Fields{
"namespace": obj.GetNamespace(),
"name": obj.GetName(),
"groupResource": groupResource.String(),
}).Infof("Dynamically re-provisioning persistent volume because it has a related snapshot DataUpload.")

Check warning on line 1321 in pkg/restore/restore.go

View check run for this annotation

Codecov / codecov/patch

pkg/restore/restore.go#L1316-L1321

Added lines #L1316 - L1321 were not covered by tests
ctx.pvsToProvision.Insert(name)

// Return early because we don't want to restore the PV itself, we
// want to dynamically re-provision it.
return warnings, errs, itemExists

case hasDeleteReclaimPolicy(obj.Object):
ctx.log.Infof("Dynamically re-provisioning persistent volume because it doesn't have a snapshot and its reclaim policy is Delete.")
ctx.log.WithFields(logrus.Fields{
"namespace": obj.GetNamespace(),
"name": obj.GetName(),
"groupResource": groupResource.String(),
}).Infof("Dynamically re-provisioning persistent volume because it doesn't have a snapshot and its reclaim policy is Delete.")
ctx.pvsToProvision.Insert(name)

// Return early because we don't want to restore the PV itself, we
// want to dynamically re-provision it.
return warnings, errs, itemExists

default:
ctx.log.Infof("Restoring persistent volume as-is because it doesn't have a snapshot and its reclaim policy is not Delete.")
ctx.log.WithFields(logrus.Fields{
"namespace": obj.GetNamespace(),
"name": obj.GetName(),
"groupResource": groupResource.String(),
}).Infof("Restoring persistent volume as-is because it doesn't have a snapshot and its reclaim policy is not Delete.")

// Check to see if the claimRef.namespace field needs to be remapped, and do so if necessary.
_, err = remapClaimRefNS(ctx, obj)
Expand Down Expand Up @@ -1929,6 +1968,55 @@
return false
}

func hasCSIVolumeSnapshot(ctx *restoreContext, unstructuredPV *unstructured.Unstructured) bool {
pv := new(v1.PersistentVolume)
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.Object, pv); err != nil {
ctx.log.WithError(err).Warnf("Unable to convert PV from unstructured to structured")
return false
}

for _, vs := range ctx.csiVolumeSnapshots {
if pv.Spec.ClaimRef.Name == *vs.Spec.Source.PersistentVolumeClaimName &&
pv.Spec.ClaimRef.Namespace == vs.Namespace {
return true
}
}
return false
}

func hasSnapshotDataUpload(ctx *restoreContext, unstructuredPV *unstructured.Unstructured) bool {
pv := new(v1.PersistentVolume)
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPV.Object, pv); err != nil {
ctx.log.WithError(err).Warnf("Unable to convert PV from unstructured to structured")
return false
}

if pv.Spec.ClaimRef == nil {
return false
}

dataUploadResultList := new(v1.ConfigMapList)
err := ctx.kbClient.List(go_context.TODO(), dataUploadResultList, &crclient.ListOptions{
LabelSelector: labels.SelectorFromSet(map[string]string{
velerov1api.RestoreUIDLabel: label.GetValidName(string(ctx.restore.GetUID())),
velerov1api.PVCNamespaceNameLabel: label.GetValidName(pv.Spec.ClaimRef.Namespace + "." + pv.Spec.ClaimRef.Name),
velerov1api.ResourceUsageLabel: label.GetValidName(string(velerov1api.VeleroResourceUsageDataUploadResult)),
}),
})
if err != nil {
ctx.log.WithError(err).Warnf("Fail to list DataUpload result CM.")
return false
}

Check warning on line 2009 in pkg/restore/restore.go

View check run for this annotation

Codecov / codecov/patch

pkg/restore/restore.go#L2007-L2009

Added lines #L2007 - L2009 were not covered by tests

if len(dataUploadResultList.Items) != 1 {
ctx.log.WithError(fmt.Errorf("dataupload result number is not expected")).
Warnf("Got %d DataUpload result. Expect one.", len(dataUploadResultList.Items))
return false
}

return true

Check warning on line 2017 in pkg/restore/restore.go

View check run for this annotation

Codecov / codecov/patch

pkg/restore/restore.go#L2017

Added line #L2017 was not covered by tests
}

func hasPodVolumeBackup(unstructuredPV *unstructured.Unstructured, ctx *restoreContext) bool {
if len(ctx.podVolumeBackups) == 0 {
return false
Expand Down
Loading
Loading