csi data mover backup describe, support legacy backups

Signed-off-by: Lyndon-Li <lyonghui@vmware.com>
This commit is contained in:
Lyndon-Li
2023-12-05 15:49:35 +08:00
parent 81183f683e
commit 434e073c67
2 changed files with 175 additions and 36 deletions

View File

@@ -22,11 +22,15 @@ import (
"encoding/json"
"fmt"
"sort"
"strconv"
"strings"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v4/apis/volumesnapshot/v1"
"github.com/pkg/errors"
"github.com/fatih/color"
kbclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -438,26 +442,40 @@ func describeBackupVolumes(ctx context.Context, kbClient kbclient.Client, d *Des
d.Println("Backup Volumes:")
buf := new(bytes.Buffer)
if err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupVolumeInfos, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath); err != nil {
d.Printf("\t<error getting backup volume info: %v>\n", err)
return
}
var volumeInfos *volume.VolumeInfos
if err := json.NewDecoder(buf).Decode(&volumeInfos); err != nil {
d.Printf("\t<error reading backup volume info: %v>\n", err)
return
}
nativeSnapshots := []*volume.VolumeInfo{}
csiSnapshots := []*volume.VolumeInfo{}
for i := range volumeInfos.VolumeInfos {
switch volumeInfos.VolumeInfos[i].BackupMethod {
case volume.NativeSnapshot:
nativeSnapshots = append(nativeSnapshots, &volumeInfos.VolumeInfos[i])
case volume.CSISnapshot:
csiSnapshots = append(csiSnapshots, &volumeInfos.VolumeInfos[i])
buf := new(bytes.Buffer)
err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupVolumeInfos, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath)
if err == downloadrequest.ErrNotFound {
nativeSnapshots, err = retrieveNativeSnapshotLegacy(ctx, kbClient, backup, insecureSkipTLSVerify, caCertPath)
if err != nil {
d.Printf("\t<error concluding native snapshot info: %v>\n", err)
return
}
csiSnapshots, err = retrieveCSISnapshotLegacy(ctx, kbClient, backup, insecureSkipTLSVerify, caCertPath)
if err != nil {
d.Printf("\t<error concluding CSI snapshot info: %v>\n", err)
return
}
} else if err != nil {
d.Printf("\t<error getting backup volume info: %v>\n", err)
return
} else {
var volumeInfos *volume.VolumeInfos
if err := json.NewDecoder(buf).Decode(&volumeInfos); err != nil {
d.Printf("\t<error reading backup volume info: %v>\n", err)
return
}
for i := range volumeInfos.VolumeInfos {
switch volumeInfos.VolumeInfos[i].BackupMethod {
case volume.NativeSnapshot:
nativeSnapshots = append(nativeSnapshots, &volumeInfos.VolumeInfos[i])
case volume.CSISnapshot:
csiSnapshots = append(csiSnapshots, &volumeInfos.VolumeInfos[i])
}
}
}
@@ -471,6 +489,113 @@ func describeBackupVolumes(ctx context.Context, kbClient kbclient.Client, d *Des
d.Println()
}
func retrieveNativeSnapshotLegacy(ctx context.Context, kbClient kbclient.Client, backup *velerov1api.Backup, insecureSkipTLSVerify bool, caCertPath string) ([]*volume.VolumeInfo, error) {
status := backup.Status
nativeSnapshots := []*volume.VolumeInfo{}
if status.VolumeSnapshotsAttempted == 0 {
return nativeSnapshots, nil
}
buf := new(bytes.Buffer)
if err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupVolumeSnapshots, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath); err != nil {
return nativeSnapshots, errors.Wrapf(err, "error to download native snapshot info")
}
var snapshots []*volume.Snapshot
if err := json.NewDecoder(buf).Decode(&snapshots); err != nil {
return nativeSnapshots, errors.Wrapf(err, "error to decode native snapshot info")
}
for _, snap := range snapshots {
volumeInfo := volume.VolumeInfo{
PVName: snap.Spec.PersistentVolumeName,
NativeSnapshotInfo: volume.NativeSnapshotInfo{
SnapshotHandle: snap.Status.ProviderSnapshotID,
VolumeType: snap.Spec.VolumeType,
VolumeAZ: snap.Spec.VolumeAZ,
},
}
if snap.Spec.VolumeIOPS != nil {
volumeInfo.NativeSnapshotInfo.IOPS = strconv.FormatInt(*snap.Spec.VolumeIOPS, 10)
}
nativeSnapshots = append(nativeSnapshots, &volumeInfo)
}
return nativeSnapshots, nil
}
func retrieveCSISnapshotLegacy(ctx context.Context, kbClient kbclient.Client, backup *velerov1api.Backup, insecureSkipTLSVerify bool, caCertPath string) ([]*volume.VolumeInfo, error) {
csiSnapshots := []*volume.VolumeInfo{}
if !features.IsEnabled(velerov1api.CSIFeatureFlag) {
return csiSnapshots, nil
}
vsBuf := new(bytes.Buffer)
err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindCSIBackupVolumeSnapshots, vsBuf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath)
if err != nil {
return csiSnapshots, errors.Wrapf(err, "error to download vs list")
}
var vsList []snapshotv1api.VolumeSnapshot
if err := json.NewDecoder(vsBuf).Decode(&vsList); err != nil {
return csiSnapshots, errors.Wrapf(err, "error to decode vs list")
}
vscBuf := new(bytes.Buffer)
err = downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindCSIBackupVolumeSnapshotContents, vscBuf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath)
if err != nil {
return csiSnapshots, errors.Wrapf(err, "error to download vsc list")
}
var vscList []snapshotv1api.VolumeSnapshotContent
if err := json.NewDecoder(vsBuf).Decode(&vscList); err != nil {
return csiSnapshots, errors.Wrapf(err, "error to decode vsc list")
}
for _, vsc := range vscList {
volInfo := volume.VolumeInfo{
CSISnapshotInfo: volume.CSISnapshotInfo{
VSCName: vsc.Name,
Driver: vsc.Spec.Driver,
},
}
if vsc.Status != nil && vsc.Status.SnapshotHandle != nil {
volInfo.CSISnapshotInfo.SnapshotHandle = *vsc.Status.SnapshotHandle
}
if vsc.Status != nil && vsc.Status.RestoreSize != nil {
volInfo.CSISnapshotInfo.Size = *vsc.Status.RestoreSize
}
for _, vs := range vsList {
if vs.Spec.Source.VolumeSnapshotContentName == nil {
continue
}
if vs.Spec.Source.PersistentVolumeClaimName == nil {
continue
}
if *vs.Spec.Source.VolumeSnapshotContentName == vsc.Name {
volInfo.PVCName = *vs.Spec.Source.PersistentVolumeClaimName
}
}
if volInfo.PVCName == "" {
volInfo.PVCName = "<PVC name not found>"
}
csiSnapshots = append(csiSnapshots, &volInfo)
}
return csiSnapshots, nil
}
func describeNativeSnapshots(d *Describer, details bool, infos []*volume.VolumeInfo) {
if len(infos) == 0 {
d.Printf("\tVelero-Native Snapshots: <none included>\n")

View File

@@ -309,26 +309,40 @@ func describeBackupVolumesInSF(ctx context.Context, kbClient kbclient.Client, ba
backupVolumes := make(map[string]interface{})
buf := new(bytes.Buffer)
if err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupVolumeInfos, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath); err != nil {
backupVolumes["errorGetBackupVolumeInfo"] = fmt.Sprintf("error getting backup volume info: %v", err)
return
}
var volumeInfos *volume.VolumeInfos
if err := json.NewDecoder(buf).Decode(&volumeInfos); err != nil {
backupVolumes["errorReadBackupVolumeInfo"] = fmt.Sprintf("error reading backup volume info: %v", err)
return
}
nativeSnapshots := []*volume.VolumeInfo{}
csiSnapshots := []*volume.VolumeInfo{}
for i := range volumeInfos.VolumeInfos {
switch volumeInfos.VolumeInfos[i].BackupMethod {
case volume.NativeSnapshot:
nativeSnapshots = append(nativeSnapshots, &volumeInfos.VolumeInfos[i])
case volume.CSISnapshot:
csiSnapshots = append(csiSnapshots, &volumeInfos.VolumeInfos[i])
buf := new(bytes.Buffer)
err := downloadrequest.Stream(ctx, kbClient, backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupVolumeInfos, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath)
if err == downloadrequest.ErrNotFound {
nativeSnapshots, err = retrieveNativeSnapshotLegacy(ctx, kbClient, backup, insecureSkipTLSVerify, caCertPath)
if err != nil {
backupVolumes["errorConcludeNativeSnapshot"] = fmt.Sprintf("error concluding native snapshot info: %v", err)
return
}
csiSnapshots, err = retrieveCSISnapshotLegacy(ctx, kbClient, backup, insecureSkipTLSVerify, caCertPath)
if err != nil {
backupVolumes["errorConcludeCSISnapshot"] = fmt.Sprintf("error concluding CSI snapshot info: %v", err)
return
}
} else if err != nil {
backupVolumes["errorGetBackupVolumeInfo"] = fmt.Sprintf("error getting backup volume info: %v", err)
return
} else {
var volumeInfos *volume.VolumeInfos
if err := json.NewDecoder(buf).Decode(&volumeInfos); err != nil {
backupVolumes["errorReadBackupVolumeInfo"] = fmt.Sprintf("error reading backup volume info: %v", err)
return
}
for i := range volumeInfos.VolumeInfos {
switch volumeInfos.VolumeInfos[i].BackupMethod {
case volume.NativeSnapshot:
nativeSnapshots = append(nativeSnapshots, &volumeInfos.VolumeInfos[i])
case volume.CSISnapshot:
csiSnapshots = append(csiSnapshots, &volumeInfos.VolumeInfos[i])
}
}
}