Skip to content

Commit

Permalink
Generate VolumeInfo.
Browse files Browse the repository at this point in the history
Remove CSI VolumeSnapshot listter and the informer.

Signed-off-by: Xun Jiang <[email protected]>
  • Loading branch information
Xun Jiang committed Nov 20, 2023
1 parent 939dd71 commit a6057bb
Show file tree
Hide file tree
Showing 17 changed files with 684 additions and 164 deletions.
3 changes: 2 additions & 1 deletion design/pv_backup_info.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ type PodVolumeBackupInfo struct {

UploaderType string // The type of the uploader that uploads the data. The valid values are `kopia` and `restic`. It's useful for file-system backup and snapshot data mover.
VolumeName string // The PVC's corresponding volume name used by Pod: https://github.com/kubernetes/kubernetes/blob/e4b74dd12fa8cb63c174091d5536a10b8ec19d34/pkg/apis/core/types.go#L48
PodName string // The Pod name mounting this PVC. The format should be <namespace-name>/<pod-name>.
PodName string // The Pod name mounting this PVC.
PodNamespace string // The Pod namespace.
NodeName string // The PVB-taken k8s node's name.
}

Expand Down
5 changes: 3 additions & 2 deletions pkg/backup/backup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func TestBackedUpItemsMatchesTarballContents(t *testing.T) {
req := &Request{
Backup: defaultBackup().Result(),
SkippedPVTracker: NewSkipPVTracker(),
PVMap: map[string]PvcPvInfo{},
}
backupFile := bytes.NewBuffer([]byte{})

Expand All @@ -84,8 +85,8 @@ func TestBackedUpItemsMatchesTarballContents(t *testing.T) {
builder.ForDeployment("zoo", "raz").Result(),
),
test.PVs(
builder.ForPersistentVolume("bar").Result(),
builder.ForPersistentVolume("baz").Result(),
builder.ForPersistentVolume("bar").ClaimRef("foo", "pvc1").Result(),
builder.ForPersistentVolume("baz").ClaimRef("bar", "pvc2").Result(),
),
}
for _, resource := range apiResources {
Expand Down
37 changes: 37 additions & 0 deletions pkg/backup/item_backupper.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,10 @@ func (ib *itemBackupper) backupItemInternal(logger logrus.FieldLogger, obj runti
namespace = metadata.GetNamespace()

if groupResource == kuberesource.PersistentVolumes {
if err := ib.addVolumeInfo(obj, log); err != nil {
backupErrs = append(backupErrs, err)
}

Check warning on line 255 in pkg/backup/item_backupper.go

View check run for this annotation

Codecov / codecov/patch

pkg/backup/item_backupper.go#L254-L255

Added lines #L254 - L255 were not covered by tests

if err := ib.takePVSnapshot(obj, log); err != nil {
backupErrs = append(backupErrs, err)
}
Expand Down Expand Up @@ -685,6 +689,39 @@ func (ib *itemBackupper) unTrackSkippedPV(obj runtime.Unstructured, groupResourc
}
}

func (ib *itemBackupper) addVolumeInfo(obj runtime.Unstructured, log logrus.FieldLogger) error {
pv := new(corev1api.PersistentVolume)
err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.UnstructuredContent(), pv)
if err != nil {
log.WithError(err).Warnf("Fail to convert PV")
return err
}

Check warning on line 698 in pkg/backup/item_backupper.go

View check run for this annotation

Codecov / codecov/patch

pkg/backup/item_backupper.go#L696-L698

Added lines #L696 - L698 were not covered by tests

if ib.backupRequest.PVMap == nil {
ib.backupRequest.PVMap = make(map[string]PvcPvInfo)
}

pvcName := ""
pvcNamespace := ""
if pv.Spec.ClaimRef != nil {
pvcName = pv.Spec.ClaimRef.Name
pvcNamespace = pv.Spec.ClaimRef.Namespace

ib.backupRequest.PVMap[pvcNamespace+"/"+pvcName] = PvcPvInfo{
PVCName: pvcName,
PVCNamespace: pvcNamespace,
PV: *pv,
}
}

ib.backupRequest.PVMap[pv.Name] = PvcPvInfo{
PVCName: pvcName,
PVCNamespace: pvcNamespace,
PV: *pv,
}
return nil
}

// convert the input object to PV/PVC and get the PV name
func getPVName(obj runtime.Unstructured, groupResource schema.GroupResource) (string, error) {
if groupResource == kuberesource.PersistentVolumes {
Expand Down
54 changes: 54 additions & 0 deletions pkg/backup/item_backupper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ package backup
import (
"testing"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/vmware-tanzu/velero/pkg/kuberesource"
"github.com/vmware-tanzu/velero/pkg/volume"

"github.com/stretchr/testify/assert"
corev1api "k8s.io/api/core/v1"
Expand Down Expand Up @@ -237,3 +239,55 @@ func TestRandom(t *testing.T) {
err2 := runtime.DefaultUnstructuredConverter.FromUnstructured(o, pvc)
t.Logf("err1: %v, err2: %v", err1, err2)
}

func TestAddVolumeInfo(t *testing.T) {
tests := []struct {
name string
pv *corev1api.PersistentVolume
expectedVolumeInfo map[string]PvcPvInfo
}{
{
name: "PV has ClaimRef",
pv: builder.ForPersistentVolume("testPV").ClaimRef("testNS", "testPVC").Result(),
expectedVolumeInfo: map[string]PvcPvInfo{
"testPV": {
PVCName: "testPVC",
PVCNamespace: "testNS",
PV: *builder.ForPersistentVolume("testPV").ClaimRef("testNS", "testPVC").Result(),
},
"testNS/testPVC": {
PVCName: "testPVC",
PVCNamespace: "testNS",
PV: *builder.ForPersistentVolume("testPV").ClaimRef("testNS", "testPVC").Result(),
},
},
},
{
name: "PV has no ClaimRef",
pv: builder.ForPersistentVolume("testPV").Result(),
expectedVolumeInfo: map[string]PvcPvInfo{
"testPV": {
PVCName: "",
PVCNamespace: "",
PV: *builder.ForPersistentVolume("testPV").Result(),
},
},
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
ib := itemBackupper{}
ib.backupRequest = new(Request)
ib.backupRequest.VolumeInfos.VolumeInfos = make([]volume.VolumeInfo, 0)

pvObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(tc.pv)
require.NoError(t, err)
logger := logrus.StandardLogger()

err = ib.addVolumeInfo(&unstructured.Unstructured{Object: pvObj}, logger)
require.NoError(t, err)
require.Equal(t, tc.expectedVolumeInfo, ib.backupRequest.PVMap)
})
}
}
8 changes: 8 additions & 0 deletions pkg/backup/pv_skip_tracker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ type SkippedPV struct {
Reasons []PVSkipReason `json:"reasons"`
}

func (s *SkippedPV) SerializeSkipReasons() string {
ret := ""
for _, reason := range s.Reasons {
ret = ret + reason.Approach + ": " + reason.Reason + ";"
}
return ret
}

type PVSkipReason struct {
Approach string `json:"approach"`
Reason string `json:"reason"`
Expand Down
12 changes: 12 additions & 0 deletions pkg/backup/pv_skip_tracker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestSummary(t *testing.T) {
Expand Down Expand Up @@ -41,3 +42,14 @@ func TestSummary(t *testing.T) {
}
assert.Equal(t, expected, tracker.Summary())
}

func TestSerializeSkipReasons(t *testing.T) {
tracker := NewSkipPVTracker()
//tracker.Track("pv5", "", "skipped due to policy")
tracker.Track("pv3", podVolumeApproach, "it's set to opt-out")
tracker.Track("pv3", csiSnapshotApproach, "not applicable for CSI ")

for _, skippedPV := range tracker.Summary() {
require.Equal(t, "csiSnapshot: not applicable for CSI ;podvolume: it's set to opt-out;", skippedPV.SerializeSkipReasons())
}
}
14 changes: 14 additions & 0 deletions pkg/backup/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
"fmt"
"sort"

snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
corev1api "k8s.io/api/core/v1"

"github.com/vmware-tanzu/velero/internal/hook"
"github.com/vmware-tanzu/velero/internal/resourcepolicies"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
Expand Down Expand Up @@ -49,9 +52,20 @@ type Request struct {
VolumeSnapshots []*volume.Snapshot
PodVolumeBackups []*velerov1api.PodVolumeBackup
BackedUpItems map[itemKey]struct{}
CSISnapshots []snapshotv1api.VolumeSnapshot
itemOperationsList *[]*itemoperation.BackupOperation
ResPolicies *resourcepolicies.Policies
SkippedPVTracker *skipPVTracker
// A map contains the backup-included PV detail content.
// The key is PV name or PVC name(The format is PVC-namespace/PVC-name)
PVMap map[string]PvcPvInfo
VolumeInfos volume.VolumeInfos
}

type PvcPvInfo struct {
PVCName string
PVCNamespace string
PV corev1api.PersistentVolume
}

// GetItemOperationsList returns ItemOperationsList, initializing it if necessary
Expand Down
21 changes: 9 additions & 12 deletions pkg/backup/snapshots.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"

snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
snapshotv1listers "github.com/kubernetes-csi/external-snapshotter/client/v4/listers/volumesnapshot/v1"
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/util/sets"
kbclient "sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -17,25 +16,23 @@ import (

// Common function to update the status of CSI snapshots
// returns VolumeSnapshot, VolumeSnapshotContent, VolumeSnapshotClasses referenced
func UpdateBackupCSISnapshotsStatus(client kbclient.Client, volumeSnapshotLister snapshotv1listers.VolumeSnapshotLister, backup *velerov1api.Backup, backupLog logrus.FieldLogger) (volumeSnapshots []snapshotv1api.VolumeSnapshot, volumeSnapshotContents []snapshotv1api.VolumeSnapshotContent, volumeSnapshotClasses []snapshotv1api.VolumeSnapshotClass) {
func UpdateBackupCSISnapshotsStatus(client kbclient.Client, globalCRClient kbclient.Client, backup *velerov1api.Backup, backupLog logrus.FieldLogger) (volumeSnapshots []snapshotv1api.VolumeSnapshot, volumeSnapshotContents []snapshotv1api.VolumeSnapshotContent, volumeSnapshotClasses []snapshotv1api.VolumeSnapshotClass) {

Check warning on line 19 in pkg/backup/snapshots.go

View check run for this annotation

Codecov / codecov/patch

pkg/backup/snapshots.go#L19

Added line #L19 was not covered by tests
if boolptr.IsSetToTrue(backup.Spec.SnapshotMoveData) {
backupLog.Info("backup SnapshotMoveData is set to true, skip VolumeSnapshot resource persistence.")
} else if features.IsEnabled(velerov1api.CSIFeatureFlag) {
selector := label.NewSelectorForBackup(backup.Name)
vscList := &snapshotv1api.VolumeSnapshotContentList{}

if volumeSnapshotLister != nil {
tmpVSs, err := volumeSnapshotLister.List(label.NewSelectorForBackup(backup.Name))
if err != nil {
backupLog.Error(err)
}
for _, vs := range tmpVSs {
volumeSnapshots = append(volumeSnapshots, *vs)
}
vsList := new(snapshotv1api.VolumeSnapshotList)
err := globalCRClient.List(context.TODO(), vsList, &kbclient.ListOptions{
LabelSelector: label.NewSelectorForBackup(backup.Name),
})
if err != nil {
backupLog.Error(err)

Check warning on line 31 in pkg/backup/snapshots.go

View check run for this annotation

Codecov / codecov/patch

pkg/backup/snapshots.go#L26-L31

Added lines #L26 - L31 were not covered by tests
}
volumeSnapshots = append(volumeSnapshots, vsList.Items...)

Check warning on line 33 in pkg/backup/snapshots.go

View check run for this annotation

Codecov / codecov/patch

pkg/backup/snapshots.go#L33

Added line #L33 was not covered by tests

err := client.List(context.Background(), vscList, &kbclient.ListOptions{LabelSelector: selector})
if err != nil {
if err := client.List(context.Background(), vscList, &kbclient.ListOptions{LabelSelector: selector}); err != nil {

Check warning on line 35 in pkg/backup/snapshots.go

View check run for this annotation

Codecov / codecov/patch

pkg/backup/snapshots.go#L35

Added line #L35 was not covered by tests
backupLog.Error(err)
}
if len(vscList.Items) >= 0 {
Expand Down
15 changes: 15 additions & 0 deletions pkg/builder/volume_snapshot_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package builder

import (
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -68,7 +69,21 @@ func (v *VolumeSnapshotBuilder) BoundVolumeSnapshotContentName(vscName string) *
return v
}

// SourcePVC set the built VolumeSnapshot's spec.Source.PersistentVolumeClaimName.
func (v *VolumeSnapshotBuilder) SourcePVC(name string) *VolumeSnapshotBuilder {
v.object.Spec.Source.PersistentVolumeClaimName = &name
return v
}

// RestoreSize set the built VolumeSnapshot's status.RestoreSize.
func (v *VolumeSnapshotBuilder) RestoreSize(size string) *VolumeSnapshotBuilder {
resourceSize := resource.MustParse(size)
v.object.Status.RestoreSize = &resourceSize
return v
}

// VolumeSnapshotClass set the built VolumeSnapshot's spec.VolumeSnapshotClassName value.
func (v *VolumeSnapshotBuilder) VolumeSnapshotClass(name string) *VolumeSnapshotBuilder {
v.object.Spec.VolumeSnapshotClassName = &name
return v
}
16 changes: 16 additions & 0 deletions pkg/builder/volume_snapshot_content_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ func (v *VolumeSnapshotContentBuilder) DeletionPolicy(policy snapshotv1api.Delet
return v
}

// VolumeSnapshotRef sets the built VolumeSnapshotContent's spec.VolumeSnapshotRef value.
func (v *VolumeSnapshotContentBuilder) VolumeSnapshotRef(namespace, name string) *VolumeSnapshotContentBuilder {
v.object.Spec.VolumeSnapshotRef = v1.ObjectReference{
APIVersion: "snapshot.storage.k8s.io/v1",
Expand All @@ -68,3 +69,18 @@ func (v *VolumeSnapshotContentBuilder) VolumeSnapshotRef(namespace, name string)
}
return v
}

// VolumeSnapshotClassName sets the built VolumeSnapshotContent's spec.VolumeSnapshotClassName value.
func (v *VolumeSnapshotContentBuilder) VolumeSnapshotClassName(name string) *VolumeSnapshotContentBuilder {
v.object.Spec.VolumeSnapshotClassName = &name
return v
}

// ObjectMeta applies functional options to the VolumeSnapshotContent's ObjectMeta.
func (v *VolumeSnapshotContentBuilder) ObjectMeta(opts ...ObjectMetaOpt) *VolumeSnapshotContentBuilder {
for _, opt := range opts {
opt(v.object)
}

return v
}
4 changes: 4 additions & 0 deletions pkg/client/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
k8scheme "k8s.io/client-go/kubernetes/scheme"
kbclient "sigs.k8s.io/controller-runtime/pkg/client"

snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/pkg/errors"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -158,6 +159,9 @@ func (f *factory) KubebuilderClient() (kbclient.Client, error) {
if err := apiextv1.AddToScheme(scheme); err != nil {
return nil, err
}
if err := snapshotv1api.AddToScheme(scheme); err != nil {
return nil, err
}

Check warning on line 164 in pkg/client/factory.go

View check run for this annotation

Codecov / codecov/patch

pkg/client/factory.go#L163-L164

Added lines #L163 - L164 were not covered by tests
kubebuilderClient, err := kbclient.New(clientConfig, kbclient.Options{
Scheme: scheme,
})
Expand Down
Loading

0 comments on commit a6057bb

Please sign in to comment.