diff --git a/Makefile b/Makefile index e4942522..a5cf9c4d 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ BUILD_IMAGE ?= golang:1.20.6-bullseye REGISTRY ?= catalogicsoftware IMAGE_NAME ?= $(REGISTRY)/velero-plugin-for-csi -TAG ?= v0.5.1.6 +TAG ?= v0.5.1.7 IMAGE ?= $(IMAGE_NAME):$(TAG) diff --git a/internal/backup/pvc_action.go b/internal/backup/pvc_action.go index 1dd9f584..2a8d051b 100644 --- a/internal/backup/pvc_action.go +++ b/internal/backup/pvc_action.go @@ -127,33 +127,10 @@ func (p *PVCBackupItemAction) Execute(item runtime.Unstructured, backup *velerov return nil, nil, errors.Wrap(err, "error getting storage class") } - config, err := catalogic.GetPluginConfig(p.Log) - if err != nil { - return nil, nil, errors.Wrap(err, "error getting plugin config") - } - - for _, driver := range liveCopyDrivers { - if config.SnapshotLonghorn && (driver == "driver.longhorn.io") { - continue - } - if storageClass.Provisioner == driver { - p.Log.Infof("Skipping PVC %s/%s, associated PV %s with provisioner %s is not supported", - pvc.Namespace, pvc.Name, pv.Name, storageClass.Provisioner) - return item, nil, nil - } - } - - if backupMethod, found := config.StorageClassBackupMethodMap[*pvc.Spec.StorageClassName]; found { - if strings.HasPrefix(backupMethod, "LIVE") { - if *pvc.Spec.VolumeMode != corev1api.PersistentVolumeBlock { - p.Log.Infof("Skipping PVC %s/%s with storage class %s and backup method %s", - pvc.Namespace, pvc.Name, *pvc.Spec.StorageClassName, backupMethod) - return item, nil, nil - } else { - p.Log.Infof("Ignoring PVC %s/%s backup method %s because it is a block volume", - pvc.Namespace, pvc.Name, backupMethod) - } - } + if shouldSkipSnapshot, err := p.shouldSkipSnapshot(&pvc, pv.Name, storageClass.Provisioner); err != nil { + return nil, nil, err + } else if shouldSkipSnapshot { + return item, nil, nil } p.Log.Debugf("Fetching volumesnapshot class for %s", storageClass.Provisioner) @@ -250,3 +227,51 @@ func (p *PVCBackupItemAction) Execute(item runtime.Unstructured, backup *velerov return &unstructured.Unstructured{Object: pvcMap}, additionalItems, nil } + +func (p *PVCBackupItemAction) shouldSkipSnapshot(pvc *corev1api.PersistentVolumeClaim, pvName string, provisioner string) (bool, error) { + config, err := catalogic.GetPluginConfig(p.Log) + if err != nil { + return false, errors.Wrap(err, "error getting plugin config") + } + + if config.SnapshotLonghorn && (provisioner == "driver.longhorn.io") { + p.Log.Infof("Longhorn PVC %s/%s will be snapshotted as SnapshotLonghorn is set", pvc.Namespace, pvc.Name) + return false, nil + } + + for _, driver := range liveCopyDrivers { + if provisioner == driver { + p.Log.Infof("PVC %s/%s, associated PV %s with provisioner %s is not supported for snapshotting", pvc.Namespace, pvc.Name, + pvName, provisioner) + return true, nil + } + } + + if backupMethod, found := config.StorageClassBackupMethodMap[*pvc.Spec.StorageClassName]; found { + if backupMethod == "SNAPSHOT" { + return false, nil + } + + if backupMethod == "SKIP" { + p.Log.Infof("Skipping snapshot of PVC %s/%s because backupMethod is set to SKIP", pvc.Namespace, pvc.Name) + return true, nil + } + + if strings.HasPrefix(backupMethod, "LIVE") { + if *pvc.Spec.VolumeMode != corev1api.PersistentVolumeBlock { + p.Log.Infof("Skipping snapshot of PVC %s/%s with storage class %s and backup method %s", pvc.Namespace, pvc.Name, + *pvc.Spec.StorageClassName, backupMethod) + return true, nil + } else { + p.Log.Infof("Ignoring PVC %s/%s backup method %s because it is a block volume", pvc.Namespace, pvc.Name, backupMethod) + } + } + } + + if !config.SnapshotWherePossible { + p.Log.Infof("Skipping snapshot of PVC %s/%s because SnapshotWherePossible is false", pvc.Namespace, pvc.Name) + return true, nil + } + + return false, nil +} diff --git a/internal/catalogic/types.go b/internal/catalogic/types.go index 4173f5ce..cfdee758 100644 --- a/internal/catalogic/types.go +++ b/internal/catalogic/types.go @@ -18,6 +18,7 @@ type PvcSnapshotProgressData struct { } type PluginConfig struct { + SnapshotWherePossible bool SnapshotLonghorn bool CsiSnapshotTimeout int StorageClassBackupMethodMap map[string]string diff --git a/internal/catalogic/utils.go b/internal/catalogic/utils.go index ac647cbf..555e97b8 100644 --- a/internal/catalogic/utils.go +++ b/internal/catalogic/utils.go @@ -159,6 +159,19 @@ func GetPluginConfig(log logrus.FieldLogger) (*PluginConfig, error) { return nil, err } + snapshotWherePossibleString := string(configMap.BinaryData["snapshotWherePossible"]) + snapshotWherePossible, err := strconv.ParseBool(snapshotWherePossibleString) + if err != nil { + log.Error(errors.Wrapf(err, "Failed to parse snapshotWherePossible value %q from %q", snapshotWherePossibleString, + VeleroCsiPluginConfigMapName)) + return nil, err + } + if snapshotWherePossible { + log.Info("Will snapshot PVCs where possible") + } else { + log.Info("Will backup all PVCs live") + } + snapshotLonghornString := string(configMap.BinaryData["snapshotLonghorn"]) snapshotLonghorn, err := strconv.ParseBool(snapshotLonghornString) if err != nil { @@ -191,6 +204,7 @@ func GetPluginConfig(log logrus.FieldLogger) (*PluginConfig, error) { } return &PluginConfig{ + SnapshotWherePossible: snapshotWherePossible, SnapshotLonghorn: snapshotLonghorn, CsiSnapshotTimeout: csiSnapshotTimeout, StorageClassBackupMethodMap: storageClassBackupMethodMap,