Skip to content

Commit

Permalink
Only generate one Async Operation for CSI backup.
Browse files Browse the repository at this point in the history
Signed-off-by: Xun Jiang <[email protected]>
  • Loading branch information
blackpiglet committed Mar 18, 2024
1 parent a19af73 commit 53bca01
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 63 deletions.
4 changes: 2 additions & 2 deletions internal/backup/pvc_action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ func TestExecute(t *testing.T) {
if boolptr.IsSetToTrue(tc.backup.Spec.SnapshotMoveData) == true {
go func() {
var vsList *v1.VolumeSnapshotList
err := wait.PollImmediate(1*time.Second, 10*time.Second, func() (bool, error) {
vsList, err = pvcBIA.SnapshotClient.SnapshotV1().VolumeSnapshots(tc.pvc.Namespace).List(context.Background(), metav1.ListOptions{})
err := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, 10*time.Second, true, func(ctx context.Context) (bool, error) {
vsList, err = pvcBIA.SnapshotClient.SnapshotV1().VolumeSnapshots(tc.pvc.Namespace).List(ctx, metav1.ListOptions{})
require.NoError(t, err)
if err != nil || len(vsList.Items) == 0 {
return false, nil
Expand Down
36 changes: 34 additions & 2 deletions internal/backup/volumesnapshot_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ func (p *VolumeSnapshotBackupItemAction) Execute(item runtime.Unstructured, back
Namespace: vs.Namespace,
Name: vs.Name,
},
{
GroupResource: kuberesource.VolumeSnapshotContents,
Name: vsc.Name,
},
}
}

Expand Down Expand Up @@ -229,7 +233,8 @@ func (p *VolumeSnapshotBackupItemAction) Progress(operationID string, backup *ve
return progress, errors.WithStack(err)
}

vs, err := snapshotClient.SnapshotV1().VolumeSnapshots(operationIDParts[0]).Get(context.Background(), operationIDParts[1], metav1.GetOptions{})
vs, err := snapshotClient.SnapshotV1().VolumeSnapshots(operationIDParts[0]).Get(
context.Background(), operationIDParts[1], metav1.GetOptions{})
if err != nil {
p.Log.Errorf("error getting volumesnapshot %s/%s: %s", operationIDParts[0], operationIDParts[1], err.Error())
return progress, errors.WithStack(err)
Expand All @@ -241,13 +246,40 @@ func (p *VolumeSnapshotBackupItemAction) Progress(operationID string, backup *ve
}

if boolptr.IsSetToTrue(vs.Status.ReadyToUse) {
progress.Completed = true
p.Log.Debugf("VolumeSnapshot %s/%s is ReadyToUse. Continue on querying corresponding VolumeSnapshotContent.",
vs.Namespace, vs.Name)
} else if vs.Status.Error != nil {
errorMessage := ""
if vs.Status.Error.Message != nil {
errorMessage = *vs.Status.Error.Message
}
p.Log.Warnf("VolumeSnapshot has a temporary error %s. Snapshot controller will retry later.", errorMessage)

return progress, nil
}

if vs.Status != nil && vs.Status.BoundVolumeSnapshotContentName != nil {
vsc, err := snapshotClient.SnapshotV1().VolumeSnapshotContents().Get(
context.Background(), *vs.Status.BoundVolumeSnapshotContentName, metav1.GetOptions{})
if err != nil {
p.Log.Errorf("error getting VolumeSnapshotContent %s: %s", *vs.Status.BoundVolumeSnapshotContentName, err.Error())
return progress, errors.WithStack(err)
}

if vsc.Status == nil {
p.Log.Debugf("VolumeSnapshotContent %s has an empty Status. Skip progress update.", vsc.Name)
return progress, nil
}

if boolptr.IsSetToTrue(vsc.Status.ReadyToUse) {
progress.Completed = true
} else if vsc.Status.Error != nil {
progress.Completed = true
if vsc.Status.Error.Message != nil {
progress.Err = *vsc.Status.Error.Message
}
p.Log.Warnf("VolumeSnapshotContent meets an error %s.", progress.Err)
}
}

return progress, nil
Expand Down
58 changes: 0 additions & 58 deletions internal/backup/volumesnapshotcontent_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,19 @@ limitations under the License.
package backup

import (
"context"
"fmt"
"strings"
"time"

snapshotv1api "github.com/kubernetes-csi/external-snapshotter/client/v7/apis/volumesnapshot/v1"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/vmware-tanzu/velero-plugin-for-csi/internal/util"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/kuberesource"
"github.com/vmware-tanzu/velero/pkg/label"
"github.com/vmware-tanzu/velero/pkg/plugin/velero"
biav2 "github.com/vmware-tanzu/velero/pkg/plugin/velero/backupitemaction/v2"
"github.com/vmware-tanzu/velero/pkg/util/boolptr"
)

// VolumeSnapshotContentBackupItemAction is a backup item action plugin to backup
Expand Down Expand Up @@ -91,23 +84,9 @@ func (p *VolumeSnapshotContentBackupItemAction) Execute(item runtime.Unstructure
return nil, nil, "", nil, errors.WithStack(err)
}

backupOnGoing := snapCont.GetLabels()[velerov1api.BackupNameLabel] == label.GetValidName(backup.Name)
operationID := ""
var itemToUpdate []velero.ResourceIdentifier

// Only return Async operation for VSC created for this backup.
if backupOnGoing {
// The operationID is of the form <volumesnapshotcontent-name>/<started-time>
operationID = snapCont.Name + "/" + time.Now().Format(time.RFC3339)
itemToUpdate = []velero.ResourceIdentifier{
{
GroupResource: kuberesource.VolumeSnapshotContents,
Name: snapCont.Name,
},
}

}

p.Log.Infof("Returning from VolumeSnapshotContentBackupItemAction with %d additionalItems to backup", len(additionalItems))
return &unstructured.Unstructured{Object: snapContMap}, additionalItems, operationID, itemToUpdate, nil
}
Expand All @@ -122,43 +101,6 @@ func (p *VolumeSnapshotContentBackupItemAction) Progress(operationID string, bac
return progress, biav2.InvalidOperationIDError(operationID)
}

// The operationId is of the form <volumesnapshotcontent-name>/<started-time>
operationsIDParts := strings.Split(operationID, "/")
if len(operationsIDParts) != 2 {
p.Log.WithField("operationID", operationID).Error("Invalid operationID")
return progress, biav2.InvalidOperationIDError(operationID)
}
var err error
if progress.Started, err = time.Parse(time.RFC3339, operationsIDParts[1]); err != nil {
p.Log.Errorf("error parsing operationID's StartedTime part into time %s: %s", operationID, err.Error())
return progress, errors.WithStack(fmt.Errorf("fail to parse StartedTime: %s", err.Error()))
}

_, snapshotClient, err := util.GetClients()
if err != nil {
return progress, errors.WithStack(err)
}

vsc, err := snapshotClient.SnapshotV1().VolumeSnapshotContents().Get(context.Background(), operationsIDParts[0], metav1.GetOptions{})
if err != nil {
p.Log.Errorf("error getting volumesnapshotcontent %s: %s", operationsIDParts[0], err.Error())
return progress, errors.WithStack(err)
}

if vsc.Status == nil {
p.Log.Debugf("VolumeSnapshotContent %s has an empty Status. Skip progress update.", vsc.Name)
return progress, nil
}

if boolptr.IsSetToTrue(vsc.Status.ReadyToUse) {
progress.Completed = true
} else if vsc.Status.Error != nil {
progress.Completed = true
if vsc.Status.Error.Message != nil {
progress.Err = *vsc.Status.Error.Message
}
}

return progress, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ func CleanupVolumeSnapshot(volSnap *snapshotv1api.VolumeSnapshot, snapshotClient
}
}

// deleteVolumeSnapshot is called by deleteVolumeSnapshots and handles the single VolumeSnapshot
// DeleteVolumeSnapshot is called by deleteVolumeSnapshots and handles the single VolumeSnapshot
// instance.
func DeleteVolumeSnapshot(vs snapshotv1api.VolumeSnapshot, vsc snapshotv1api.VolumeSnapshotContent,
backup *velerov1api.Backup, snapshotClient snapshotter.SnapshotV1Interface, logger logrus.FieldLogger) {
Expand Down

0 comments on commit 53bca01

Please sign in to comment.