vgdp ms pvr data path

Signed-off-by: Lyndon-Li <lyonghui@vmware.com>
This commit is contained in:
Lyndon-Li
2025-06-06 15:53:34 +08:00
parent 73e1c8ae4a
commit ac4cf70d67
5 changed files with 344 additions and 3 deletions

View File

@@ -304,6 +304,10 @@ func (r *RestoreMicroService) cancelPodVolumeRestore(pvr *velerov1api.PodVolumeR
}
}
var funcRemoveAll = os.RemoveAll
var funcMkdirAll = os.MkdirAll
var funcWriteFile = os.WriteFile
func writeCompletionMark(pvr *velerov1api.PodVolumeRestore, result datapath.RestoreResult, log logrus.FieldLogger) error {
volumePath := result.Target.ByPath
if volumePath == "" {
@@ -314,7 +318,7 @@ func writeCompletionMark(pvr *velerov1api.PodVolumeRestore, result datapath.Rest
// of this volume, which we don't want to carry over). If this fails for any reason, log and continue, since
// this is non-essential cleanup (the done files are named based on restore UID and the init container looks
// for the one specific to the restore being executed).
if err := os.RemoveAll(filepath.Join(volumePath, ".velero")); err != nil {
if err := funcRemoveAll(filepath.Join(volumePath, ".velero")); err != nil {
log.WithError(err).Warnf("Failed to remove .velero directory from directory %s", volumePath)
}
@@ -326,14 +330,14 @@ func writeCompletionMark(pvr *velerov1api.PodVolumeRestore, result datapath.Rest
// Create the .velero directory within the volume dir so we can write a done file
// for this restore.
if err := os.MkdirAll(filepath.Join(volumePath, ".velero"), 0755); err != nil {
if err := funcMkdirAll(filepath.Join(volumePath, ".velero"), 0755); err != nil {
return errors.Wrapf(err, "error creating .velero directory for done file")
}
// Write a done file with name=<restore-uid> into the just-created .velero dir
// within the volume. The velero init container on the pod is waiting
// for this file to exist in each restored volume before completing.
if err := os.WriteFile(filepath.Join(volumePath, ".velero", string(restoreUID)), nil, 0644); err != nil { //nolint:gosec // Internal usage. No need to check.
if err := funcWriteFile(filepath.Join(volumePath, ".velero", string(restoreUID)), nil, 0644); err != nil {
return errors.Wrapf(err, "error writing done file")
}

View File

@@ -19,6 +19,7 @@ package podvolume
import (
"context"
"fmt"
"os"
"sync"
"testing"
"time"
@@ -42,6 +43,8 @@ import (
kbclient "sigs.k8s.io/controller-runtime/pkg/client"
datapathmockes "github.com/vmware-tanzu/velero/pkg/datapath/mocks"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type restoreMsTestHelper struct {
@@ -468,3 +471,152 @@ func TestRunCancelableDataPathRestore(t *testing.T) {
cancel()
}
func TestWriteCompletionMark(t *testing.T) {
tests := []struct {
name string
pvr *velerov1api.PodVolumeRestore
result datapath.RestoreResult
funcRemoveAll func(string) error
funcMkdirAll func(string, os.FileMode) error
funcWriteFile func(string, []byte, os.FileMode) error
expectedErr string
expectedLog string
}{
{
name: "no volume path",
result: datapath.RestoreResult{},
expectedErr: "target volume is empty in restore result",
},
{
name: "no owner reference",
result: datapath.RestoreResult{
Target: datapath.AccessPoint{
ByPath: "fake-volume-path",
},
},
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").Result(),
funcRemoveAll: func(string) error {
return nil
},
expectedErr: "error finding restore UID",
},
{
name: "mkdir fail",
result: datapath.RestoreResult{
Target: datapath.AccessPoint{
ByPath: "fake-volume-path",
},
},
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
{
UID: "fake-uid",
},
}).Result(),
funcRemoveAll: func(string) error {
return nil
},
funcMkdirAll: func(string, os.FileMode) error {
return errors.New("fake-mk-dir-error")
},
expectedErr: "error creating .velero directory for done file: fake-mk-dir-error",
},
{
name: "write file fail",
result: datapath.RestoreResult{
Target: datapath.AccessPoint{
ByPath: "fake-volume-path",
},
},
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
{
UID: "fake-uid",
},
}).Result(),
funcRemoveAll: func(string) error {
return nil
},
funcMkdirAll: func(string, os.FileMode) error {
return nil
},
funcWriteFile: func(string, []byte, os.FileMode) error {
return errors.New("fake-write-file-error")
},
expectedErr: "error writing done file: fake-write-file-error",
},
{
name: "succeed",
result: datapath.RestoreResult{
Target: datapath.AccessPoint{
ByPath: "fake-volume-path",
},
},
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
{
UID: "fake-uid",
},
}).Result(),
funcRemoveAll: func(string) error {
return nil
},
funcMkdirAll: func(string, os.FileMode) error {
return nil
},
funcWriteFile: func(string, []byte, os.FileMode) error {
return nil
},
},
{
name: "succeed but previous dir is not removed",
result: datapath.RestoreResult{
Target: datapath.AccessPoint{
ByPath: "fake-volume-path",
},
},
pvr: builder.ForPodVolumeRestore(velerov1api.DefaultNamespace, "fake-pvr").OwnerReference([]metav1.OwnerReference{
{
UID: "fake-uid",
},
}).Result(),
funcRemoveAll: func(string) error {
return errors.New("fake-remove-dir-error")
},
funcMkdirAll: func(string, os.FileMode) error {
return nil
},
funcWriteFile: func(string, []byte, os.FileMode) error {
return nil
},
expectedLog: "Failed to remove .velero directory from directory fake-volume-path",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
if test.funcRemoveAll != nil {
funcRemoveAll = test.funcRemoveAll
}
if test.funcMkdirAll != nil {
funcMkdirAll = test.funcMkdirAll
}
if test.funcWriteFile != nil {
funcWriteFile = test.funcWriteFile
}
logBuffer := ""
err := writeCompletionMark(test.pvr, test.result, velerotest.NewSingleLogger(&logBuffer))
if test.expectedErr == "" {
assert.NoError(t, err)
} else {
assert.EqualError(t, err, test.expectedErr)
}
if test.expectedLog != "" {
assert.Contains(t, logBuffer, test.expectedLog)
}
})
}
}