Skip to content

Commit

Permalink
Include CSI volume snapshot information in velero backup describe (#…
Browse files Browse the repository at this point in the history
…2448)

* Add download methods for CSI objects

Signed-off-by: Nolan Brubaker <[email protected]>

* Add support for downloading CSI volume objects

Signed-off-by: Nolan Brubaker <[email protected]>

* Add new methods to mock.

Remove generated information from file since mockery no longer appears
to work. It isn't maintained anymore and doesn't support go module-based
projects.

Signed-off-by: Nolan Brubaker <[email protected]>

* Add describe command for CSI

Signed-off-by: Nolan Brubaker <[email protected]>

* Add csi package with helpers

Signed-off-by: Nolan Brubaker <[email protected]>

* Remove duplicate import from server

Signed-off-by: Nolan Brubaker <[email protected]>

* Remove CSI API that will not be used with describe

Signed-off-by: Nolan Brubaker <[email protected]>

* Add VolumeSnapshotContents output to describe command

Signed-off-by: Nolan Brubaker <[email protected]>

* Document NewCSIListOptions function

Signed-off-by: Nolan Brubaker <[email protected]>

* Document csi package

Signed-off-by: Nolan Brubaker <[email protected]>

* Remove stutter in function name

Signed-off-by: Nolan Brubaker <[email protected]>

* Fix CI

Signed-off-by: Nolan Brubaker <[email protected]>

* Fix nil pointer error when not using CSI snapshots

Signed-off-by: Nolan Brubaker <[email protected]>

* Remove unused CSI download request kinds

Signed-off-by: Nolan Brubaker <[email protected]>

* Add back mocks

Signed-off-by: Nolan Brubaker <[email protected]>

* Change persistent volumes to velero-native snapshots

Signed-off-by: Nolan Brubaker <[email protected]>

* Remove unused function

Signed-off-by: Nolan Brubaker <[email protected]>

* Address review feedback

Signed-off-by: Nolan Brubaker <[email protected]>

* Add changelog

Signed-off-by: Nolan Brubaker <[email protected]>

* Remove unnecessary doc.go

Signed-off-by: Nolan Brubaker <[email protected]>
  • Loading branch information
nrb authored May 8, 2020
1 parent f1eeff7 commit e400be9
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 12 deletions.
1 change: 1 addition & 0 deletions changelogs/unreleased/2448-nrb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add details of CSI volumesnapshotcontents associated with a backup to `velero backup describe` when the `EnableCSI` feature flag is given on the velero client.
28 changes: 24 additions & 4 deletions pkg/cmd/cli/backup/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ import (
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

v1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
snapshotv1beta1api "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1"
snapshotv1beta1client "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned"

velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
pkgbackup "github.com/vmware-tanzu/velero/pkg/backup"
"github.com/vmware-tanzu/velero/pkg/client"
"github.com/vmware-tanzu/velero/pkg/cmd"
"github.com/vmware-tanzu/velero/pkg/cmd/util/output"
"github.com/vmware-tanzu/velero/pkg/features"
"github.com/vmware-tanzu/velero/pkg/label"
)

Expand All @@ -51,9 +55,9 @@ func NewDescribeCommand(f client.Factory, use string) *cobra.Command {
veleroClient, err := f.Client()
cmd.CheckError(err)

var backups *v1.BackupList
var backups *velerov1api.BackupList
if len(args) > 0 {
backups = new(v1.BackupList)
backups = new(velerov1api.BackupList)
for _, name := range args {
backup, err := veleroClient.VeleroV1().Backups(f.Namespace()).Get(name, metav1.GetOptions{})
cmd.CheckError(err)
Expand All @@ -78,7 +82,23 @@ func NewDescribeCommand(f client.Factory, use string) *cobra.Command {
fmt.Fprintf(os.Stderr, "error getting PodVolumeBackups for backup %s: %v\n", backup.Name, err)
}

s := output.DescribeBackup(&backup, deleteRequestList.Items, podVolumeBackupList.Items, details, veleroClient, insecureSkipTLSVerify, caCertFile)
var csiClient *snapshotv1beta1client.Clientset
// declare vscList up here since it may be empty and we'll pass the empty Items field into DescribeBackup
vscList := new(snapshotv1beta1api.VolumeSnapshotContentList)
if features.IsEnabled(velerov1api.CSIFeatureFlag) {
clientConfig, err := f.ClientConfig()
cmd.CheckError(err)

csiClient, err = snapshotv1beta1client.NewForConfig(clientConfig)
cmd.CheckError(err)

vscList, err = csiClient.SnapshotV1beta1().VolumeSnapshotContents().List(opts)
if err != nil {
fmt.Fprintf(os.Stderr, "error getting VolumeSnapshotContent objects for backup %s: %v\n", backup.Name, err)
}
}

s := output.DescribeBackup(&backup, deleteRequestList.Items, podVolumeBackupList.Items, vscList.Items, details, veleroClient, insecureSkipTLSVerify, caCertFile)
if first {
first = false
fmt.Print(s)
Expand Down
3 changes: 1 addition & 2 deletions pkg/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"sync"
"time"

snapshotterClientSet "github.com/kubernetes-csi/external-snapshotter/v2/pkg/client/clientset/versioned"
"github.com/pkg/errors"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -229,7 +228,7 @@ type server struct {
dynamicClient dynamic.Interface
sharedInformerFactory informers.SharedInformerFactory
csiSnapshotterSharedInformerFactory *CSIInformerFactoryWrapper
csiSnapshotClient *snapshotterClientSet.Clientset
csiSnapshotClient *snapshotv1beta1client.Clientset
ctx context.Context
cancelFunc context.CancelFunc
logger logrus.FieldLogger
Expand Down
57 changes: 51 additions & 6 deletions pkg/cmd/util/output/backup_describer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ import (

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

snapshotv1beta1api "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1"

velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/cmd/util/downloadrequest"
"github.com/vmware-tanzu/velero/pkg/features"
clientset "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned"
"github.com/vmware-tanzu/velero/pkg/volume"
)
Expand All @@ -36,6 +39,7 @@ func DescribeBackup(
backup *velerov1api.Backup,
deleteRequests []velerov1api.DeleteBackupRequest,
podVolumeBackups []velerov1api.PodVolumeBackup,
volumeSnapshotContents []snapshotv1beta1api.VolumeSnapshotContent,
details bool,
veleroClient clientset.Interface,
insecureSkipTLSVerify bool,
Expand Down Expand Up @@ -87,6 +91,10 @@ func DescribeBackup(
d.Println()
DescribePodVolumeBackups(d, podVolumeBackups, details)
}

if features.IsEnabled(velerov1api.CSIFeatureFlag) {
DescribeCSIVolumeSnapshots(d, details, volumeSnapshotContents)
}
})
}

Expand Down Expand Up @@ -136,7 +144,7 @@ func DescribeBackupSpec(d *Describer, spec velerov1api.BackupSpec) {
d.Printf("Storage Location:\t%s\n", spec.StorageLocation)

d.Println()
d.Printf("Snapshot PVs:\t%s\n", BoolPointerString(spec.SnapshotVolumes, "false", "true", "auto"))
d.Printf("Velero-Native Snapshot PVs:\t%s\n", BoolPointerString(spec.SnapshotVolumes, "false", "true", "auto"))

d.Println()
d.Printf("TTL:\t%s\n", spec.TTL.Duration)
Expand Down Expand Up @@ -257,30 +265,30 @@ func DescribeBackupStatus(d *Describer, backup *velerov1api.Backup, details bool

if status.VolumeSnapshotsAttempted > 0 {
if !details {
d.Printf("Persistent Volumes:\t%d of %d snapshots completed successfully (specify --details for more information)\n", status.VolumeSnapshotsCompleted, status.VolumeSnapshotsAttempted)
d.Printf("Velero-Native Snapshots:\t%d of %d snapshots completed successfully (specify --details for more information)\n", status.VolumeSnapshotsCompleted, status.VolumeSnapshotsAttempted)
return
}

buf := new(bytes.Buffer)
if err := downloadrequest.Stream(veleroClient.VeleroV1(), backup.Namespace, backup.Name, velerov1api.DownloadTargetKindBackupVolumeSnapshots, buf, downloadRequestTimeout, insecureSkipTLSVerify, caCertPath); err != nil {
d.Printf("Persistent Volumes:\t<error getting volume snapshot info: %v>\n", err)
d.Printf("Velero-Native Snapshots:\t<error getting snapshot info: %v>\n", err)
return
}

var snapshots []*volume.Snapshot
if err := json.NewDecoder(buf).Decode(&snapshots); err != nil {
d.Printf("Persistent Volumes:\t<error reading volume snapshot info: %v>\n", err)
d.Printf("Velero-Native Snapshots:\t<error reading snapshot info: %v>\n", err)
return
}

d.Printf("Persistent Volumes:\n")
d.Printf("Velero-Native Snapshots:\n")
for _, snap := range snapshots {
describeSnapshot(d, snap.Spec.PersistentVolumeName, snap.Status.ProviderSnapshotID, snap.Spec.VolumeType, snap.Spec.VolumeAZ, snap.Spec.VolumeIOPS)
}
return
}

d.Printf("Persistent Volumes: <none included>\n")
d.Printf("Velero-Native Snapshots: <none included>\n")
}

func describeBackupResourceList(d *Describer, backup *velerov1api.Backup, veleroClient clientset.Interface, insecureSkipTLSVerify bool, caCertPath string) {
Expand Down Expand Up @@ -479,3 +487,40 @@ func (v *volumesByPod) Sorted() []*podVolumeGroup {

return v.volumesByPodSlice
}

func DescribeCSIVolumeSnapshots(d *Describer, details bool, volumeSnapshotContents []snapshotv1beta1api.VolumeSnapshotContent) {
if !features.IsEnabled(velerov1api.CSIFeatureFlag) {
return
}

if !details {
d.Printf("CSI Volume Snapshots:\t%d included (specify --details for more information)\n", len(volumeSnapshotContents))
return
}
d.Printf("CSI Volume Snapshots:\n")

for _, vsc := range volumeSnapshotContents {
DescribeVSC(d, details, vsc)
}
}

func DescribeVSC(d *Describer, details bool, vsc snapshotv1beta1api.VolumeSnapshotContent) {
if vsc.Status == nil {
d.Printf("Volume Snapshot Content %s cannot be described because its status is nil\n", vsc.Name)
return
}

d.Printf("Snapshot Content Name: %s\n", vsc.Name)

if vsc.Status.SnapshotHandle != nil {
d.Printf("\tStorage Snapshot ID: %s\n", *vsc.Status.SnapshotHandle)
}

if vsc.Status.RestoreSize != nil {
d.Printf("\tSnapshot Size (bytes): %d\n", *vsc.Status.RestoreSize)
}

if vsc.Status.ReadyToUse != nil {
d.Printf("\tReady to use: %t\n", *vsc.Status.ReadyToUse)
}
}

0 comments on commit e400be9

Please sign in to comment.