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

Restore PVs regardless of the reclaim policy #6850

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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/6850-27149chen
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Restore PVs regardless of the reclaim policy
3 changes: 3 additions & 0 deletions pkg/apis/velero/v1/labels_annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ const (

// ResourceUsageLabel is the label key to explain the Velero resource usage.
ResourceUsageLabel = "velero.io/resource-usage"

// RestorePVsAnnotation is the annotation key used to indicate whether PVs should be restored. If a PV name appears in this annotation, restore it regardless of the reclaim policy.
RestorePVsAnnotation = "velero.io/restore-pvs"
)

type AsyncOperationIDPrefix string
Expand Down
57 changes: 47 additions & 10 deletions pkg/restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -1181,6 +1181,17 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso
// want to dynamically re-provision it.
return warnings, errs, itemExists

case hasRestorePVAnnotation(obj, ctx):
ctx.log.Infof("Restoring persistent volume as-is because it has a restore annotation.")

updatedObj, err := updatePVObject(ctx, obj, resourceID)
if err != nil {
errs.Add(namespace, err)
return warnings, errs, itemExists
}

obj = updatedObj

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.pvsToProvision.Insert(name)
Expand All @@ -1192,20 +1203,12 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso
default:
ctx.log.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)
updatedObj, err := updatePVObject(ctx, obj, resourceID)
if err != nil {
errs.Add(namespace, err)
return warnings, errs, itemExists
}
obj = resetVolumeBindingInfo(obj)
// We call the pvRestorer here to clear out the PV's claimRef.UID,
// so it can be re-claimed when its PVC is restored and gets a new UID.
updatedObj, err := ctx.pvRestorer.executePVAction(obj)
if err != nil {
errs.Add(namespace, fmt.Errorf("error executing PVAction for %s: %v", resourceID, err))
return warnings, errs, itemExists
}

obj = updatedObj
}
}
Expand Down Expand Up @@ -1826,11 +1829,45 @@ func hasPodVolumeBackup(unstructuredPV *unstructured.Unstructured, ctx *restoreC
return found
}

func hasRestorePVAnnotation(unstructuredPV *unstructured.Unstructured, ctx *restoreContext) bool {
annotation, ok := ctx.restore.GetAnnotations()[velerov1api.RestorePVsAnnotation]
if !ok {
return false
}

pvsToBeRestored := strings.Split(annotation, ",")
pvName := unstructuredPV.GetName()
for _, pvToBeRestored := range pvsToBeRestored {
if pvToBeRestored == pvName {
return true
}
}
return false
}

func hasDeleteReclaimPolicy(obj map[string]interface{}) bool {
policy, _, _ := unstructured.NestedString(obj, "spec", "persistentVolumeReclaimPolicy")
return policy == string(v1.PersistentVolumeReclaimDelete)
}

func updatePVObject(ctx *restoreContext, obj *unstructured.Unstructured, resourceID string) (*unstructured.Unstructured, error) {
// Check to see if the claimRef.namespace field needs to be remapped, and do so if necessary.
_, err := remapClaimRefNS(ctx, obj)
if err != nil {
return nil, err
}

obj = resetVolumeBindingInfo(obj)
// We call the pvRestorer here to clear out the PV's claimRef.UID,
// so it can be re-claimed when its PVC is restored and gets a new UID.
updatedObj, err := ctx.pvRestorer.executePVAction(obj)
if err != nil {
return nil, fmt.Errorf("error executing PVAction for %s: %v", resourceID, err)
}

return updatedObj, nil
}

// resetVolumeBindingInfo clears any necessary metadata out of a PersistentVolume
// or PersistentVolumeClaim that would make it ineligible to be re-bound by Velero.
func resetVolumeBindingInfo(obj *unstructured.Unstructured) *unstructured.Unstructured {
Expand Down
Loading