diff --git a/pkg/azurefile/azurefile.go b/pkg/azurefile/azurefile.go index 08e1dfda7f..afe37d72e4 100644 --- a/pkg/azurefile/azurefile.go +++ b/pkg/azurefile/azurefile.go @@ -1115,9 +1115,6 @@ func (d *Driver) ResizeFileShare(ctx context.Context, subsID, resourceGroup, acc // copyFileShare copies a fileshare, if dstAccountName is empty, then copy in the same account func (d *Driver) copyFileShare(ctx context.Context, req *csi.CreateVolumeRequest, dstAccountName string, dstAccountSasToken string, authAzcopyEnv []string, secretNamespace string, shareOptions *ShareOptions, accountOptions *storage.AccountOptions, storageEndpointSuffix string) error { - if shareOptions.Protocol == armstorage.EnabledProtocolsNFS { - return fmt.Errorf("protocol nfs is not supported for volume cloning") - } var sourceVolumeID string if req.GetVolumeContentSource() != nil && req.GetVolumeContentSource().GetVolume() != nil { sourceVolumeID = req.GetVolumeContentSource().GetVolume().GetVolumeId() @@ -1149,7 +1146,7 @@ func (d *Driver) copyFileShare(ctx context.Context, req *csi.CreateVolumeRequest srcPath := fmt.Sprintf("https://%s.file.%s/%s%s", srcAccountName, storageEndpointSuffix, srcFileShareName, srcAccountSasToken) dstPath := fmt.Sprintf("https://%s.file.%s/%s%s", dstAccountName, storageEndpointSuffix, dstFileShareName, dstAccountSasToken) - return d.copyFileShareByAzcopy(ctx, srcFileShareName, dstFileShareName, srcPath, dstPath, "", srcAccountName, dstAccountName, srcAccountSasToken, authAzcopyEnv, accountOptions) + return d.copyFileShareByAzcopy(ctx, srcFileShareName, dstFileShareName, srcPath, dstPath, "", srcAccountName, dstAccountName, srcAccountSasToken, authAzcopyEnv, shareOptions, accountOptions) } // GetTotalAccountQuota returns the total quota in GB of all file shares in the storage account and the number of file shares diff --git a/pkg/azurefile/controllerserver.go b/pkg/azurefile/controllerserver.go index 95bc1320d5..cd6fdd40ab 100644 --- a/pkg/azurefile/controllerserver.go +++ b/pkg/azurefile/controllerserver.go @@ -1128,9 +1128,6 @@ func (d *Driver) ListSnapshots(_ context.Context, _ *csi.ListSnapshotsRequest) ( // restoreSnapshot restores from a snapshot func (d *Driver) restoreSnapshot(ctx context.Context, req *csi.CreateVolumeRequest, dstAccountName, dstAccountSasToken string, authAzcopyEnv []string, secretNamespace string, shareOptions *ShareOptions, accountOptions *storage.AccountOptions, storageEndpointSuffix string) error { - if shareOptions.Protocol == armstorage.EnabledProtocolsNFS { - return fmt.Errorf("protocol nfs is not supported for snapshot restore") - } var sourceSnapshotID string if req.GetVolumeContentSource() != nil && req.GetVolumeContentSource().GetSnapshot() != nil { sourceSnapshotID = req.GetVolumeContentSource().GetSnapshot().GetSnapshotId() @@ -1171,10 +1168,10 @@ func (d *Driver) restoreSnapshot(ctx context.Context, req *csi.CreateVolumeReque dstPath := fmt.Sprintf("https://%s.file.%s/%s%s", dstAccountName, storageEndpointSuffix, dstFileShareName, dstAccountSasToken) srcFileShareSnapshotName := fmt.Sprintf("%s(snapshot: %s)", srcFileShareName, snapshot) - return d.copyFileShareByAzcopy(ctx, srcFileShareSnapshotName, dstFileShareName, srcPath, dstPath, snapshot, srcAccountName, dstAccountName, srcAccountSasToken, authAzcopyEnv, accountOptions) + return d.copyFileShareByAzcopy(ctx, srcFileShareSnapshotName, dstFileShareName, srcPath, dstPath, snapshot, srcAccountName, dstAccountName, srcAccountSasToken, authAzcopyEnv, shareOptions, accountOptions) } -func (d *Driver) copyFileShareByAzcopy(ctx context.Context, srcFileShareName, dstFileShareName, srcPath, dstPath, snapshot, srcAccountName, dstAccountName, accountSASToken string, authAzcopyEnv []string, accountOptions *storage.AccountOptions) error { +func (d *Driver) copyFileShareByAzcopy(ctx context.Context, srcFileShareName, dstFileShareName, srcPath, dstPath, snapshot, srcAccountName, dstAccountName, accountSASToken string, authAzcopyEnv []string, shareOptions *ShareOptions, accountOptions *storage.AccountOptions) error { azcopyCopyOptions := azcopyCloneVolumeOptions srcPathAuth := srcPath if snapshot != "" { @@ -1186,6 +1183,10 @@ func (d *Driver) copyFileShareByAzcopy(ctx context.Context, srcFileShareName, ds } } + if shareOptions.Protocol == armstorage.EnabledProtocolsNFS { + azcopyCopyOptions = append(azcopyCopyOptions, "--from-to=FileNFSFileNFS") + } + jobState, percent, err := d.azcopy.GetAzcopyJob(dstFileShareName, authAzcopyEnv) klog.V(2).Infof("azcopy job status: %s, copy percent: %s%%, error: %v", jobState, percent, err) diff --git a/pkg/azurefile/controllerserver_test.go b/pkg/azurefile/controllerserver_test.go index 3f72bdf274..43f04c9a9d 100644 --- a/pkg/azurefile/controllerserver_test.go +++ b/pkg/azurefile/controllerserver_test.go @@ -1430,33 +1430,6 @@ var _ = ginkgo.Describe("TestCopyVolume", func() { ginkgo.AfterEach(func() { ctrl.Finish() }) - ginkgo.When("restore volume from volumeSnapshot nfs is not supported", func() { - ginkgo.It("should fail", func(ctx context.Context) { - allParam := map[string]string{} - - volumeSnapshotSource := &csi.VolumeContentSource_SnapshotSource{ - SnapshotId: "unit-test", - } - volumeContentSourceSnapshotSource := &csi.VolumeContentSource_Snapshot{ - Snapshot: volumeSnapshotSource, - } - volumecontensource := csi.VolumeContentSource{ - Type: volumeContentSourceSnapshotSource, - } - - req := &csi.CreateVolumeRequest{ - Name: "random-vol-name-valid-request", - VolumeCapabilities: stdVolCap, - CapacityRange: lessThanPremCapRange, - Parameters: allParam, - VolumeContentSource: &volumecontensource, - } - - expectedErr := fmt.Errorf("protocol nfs is not supported for snapshot restore") - err := d.copyVolume(ctx, req, "", "", []string{}, "", &ShareOptions{Protocol: armstorage.EnabledProtocolsNFS}, nil, "core.windows.net") - gomega.Expect(err).To(gomega.Equal(expectedErr)) - }) - }) ginkgo.When("restore volume from volumeSnapshot not found", func() { ginkgo.It("should fail", func(ctx context.Context) { allParam := map[string]string{} @@ -1511,33 +1484,6 @@ var _ = ginkgo.Describe("TestCopyVolume", func() { gomega.Expect(err).To(gomega.Equal(expectedErr)) }) }) - ginkgo.When("copy volume nfs is not supported", func() { - ginkgo.It("should fail", func(ctx context.Context) { - allParam := map[string]string{} - - volumeSource := &csi.VolumeContentSource_VolumeSource{ - VolumeId: "unit-test", - } - volumeContentSourceVolumeSource := &csi.VolumeContentSource_Volume{ - Volume: volumeSource, - } - volumecontensource := csi.VolumeContentSource{ - Type: volumeContentSourceVolumeSource, - } - - req := &csi.CreateVolumeRequest{ - Name: "random-vol-name-valid-request", - VolumeCapabilities: stdVolCap, - CapacityRange: lessThanPremCapRange, - Parameters: allParam, - VolumeContentSource: &volumecontensource, - } - - expectedErr := fmt.Errorf("protocol nfs is not supported for volume cloning") - err := d.copyVolume(ctx, req, "", "", []string{}, "", &ShareOptions{Protocol: armstorage.EnabledProtocolsNFS}, nil, "core.windows.net") - gomega.Expect(err).To(gomega.Equal(expectedErr)) - }) - }) ginkgo.When("copy volume from volume not found", func() { ginkgo.It("should fail", func(ctx context.Context) { allParam := map[string]string{} diff --git a/test/e2e/dynamic_provisioning_test.go b/test/e2e/dynamic_provisioning_test.go index 47ae420738..040da0210f 100644 --- a/test/e2e/dynamic_provisioning_test.go +++ b/test/e2e/dynamic_provisioning_test.go @@ -101,6 +101,39 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() { test.Run(ctx, cs, snapshotrcs, ns) }) + ginkgo.It("should create a pod, write and read to it, take a nfs volume snapshot, and create another pod from the snapshot [file.csi.azure.com]", func(ctx ginkgo.SpecContext) { + skipIfUsingInTreeVolumePlugin() + skipIfTestingInWindowsCluster() + + pod := testsuites.PodDetails{ + Cmd: "echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data", + Volumes: []testsuites.VolumeDetails{ + { + ClaimSize: "100Gi", + VolumeMount: testsuites.VolumeMountDetails{ + NameGenerate: "test-volume-", + MountPathGenerate: "/mnt/test-", + }, + }, + }, + } + podWithSnapshot := testsuites.PodDetails{ + Cmd: "grep 'hello world' /mnt/test-1/data", + } + test := testsuites.DynamicallyProvisionedVolumeSnapshotTest{ + CSIDriver: testDriver, + Pod: pod, + ShouldOverwrite: false, + ShouldRestore: true, + PodWithSnapshot: podWithSnapshot, + StorageClassParameters: map[string]string{ + "skuName": "Premium_LRS", + "protocol": "nfs", + }, + } + test.Run(ctx, cs, snapshotrcs, ns) + }) + ginkgo.It("should create a pod, write to its pv, take a volume snapshot, overwrite data in original pv, create another pod from the snapshot, use another storage class, and read unaltered original data from original pv[file.csi.azure.com]", func(ctx ginkgo.SpecContext) { skipIfUsingInTreeVolumePlugin() skipIfTestingInWindowsCluster() @@ -1740,7 +1773,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() { test.Run(ctx, cs, ns) }) - ginkgo.It("should clone a large size volume from an existing volume [file.csi.azure.com]", func(ctx ginkgo.SpecContext) { + ginkgo.It("should clone a large size volume from an existing nfs volume [file.csi.azure.com]", func(ctx ginkgo.SpecContext) { skipIfTestingInWindowsCluster() skipIfTestingInMigrationCluster() skipIfUsingInTreeVolumePlugin() @@ -1765,7 +1798,8 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() { Pod: pod, PodWithClonedVolume: podWithClonedVolume, StorageClassParameters: map[string]string{ - "skuName": "Standard_LRS", + "skuName": "Premium_LRS", + "protocol": "nfs", }, } test.Run(ctx, cs, ns)