Skip to content

Commit

Permalink
support volume partition
Browse files Browse the repository at this point in the history
  • Loading branch information
AndyXiangLi committed Apr 7, 2021
1 parent a5882e3 commit 2ff385f
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 4 deletions.
13 changes: 13 additions & 0 deletions pkg/driver/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ const (
DevicePathKey = "devicePath"
)

// constants of keys in VolumeContext
const (
// VolumeAttributePartition represents key for partition config in VolumeContext
// this represents the partition number on a device used to mount
VolumeAttributePartition = "partition"
)

// constants of disk partition suffix
const (
diskPartitionSuffix = ""
nvmeDiskPartitionSuffix = "p"
)

// constants of keys in volume parameters
const (
// VolumeTypeKey represents key for volume type
Expand Down
14 changes: 12 additions & 2 deletions pkg/driver/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ func (d *nodeService) NodeStageVolume(ctx context.Context, req *csi.NodeStageVol
return nil, status.Error(codes.InvalidArgument, "Device path not provided")
}

source, err := d.findDevicePath(devicePath, volumeID)
partition := ""
if part, ok := req.GetVolumeContext()[VolumeAttributePartition]; ok {
partition = part
}
source, err := d.findDevicePath(devicePath, volumeID, partition)
if err != nil {
return nil, status.Errorf(codes.Internal, "Failed to find device path %s. %v", devicePath, err)
}
Expand Down Expand Up @@ -521,7 +525,13 @@ func (d *nodeService) nodePublishVolumeForBlock(req *csi.NodePublishVolumeReques
if !exists {
return status.Error(codes.InvalidArgument, "Device path not provided")
}
source, err := d.findDevicePath(devicePath, volumeID)

partition := ""
if part, ok := req.GetVolumeContext()[VolumeAttributePartition]; ok {
partition = part
}

source, err := d.findDevicePath(devicePath, volumeID, partition)
if err != nil {
return status.Errorf(codes.Internal, "Failed to find device path %s. %v", devicePath, err)
}
Expand Down
15 changes: 13 additions & 2 deletions pkg/driver/node_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,17 @@ import (
// findDevicePath finds path of device and verifies its existence
// if the device is not nvme, return the path directly
// if the device is nvme, finds and returns the nvme device path eg. /dev/nvme1n1
func (d *nodeService) findDevicePath(devicePath, volumeID string) (string, error) {
func (d *nodeService) findDevicePath(devicePath, volumeID string, partition string) (string, error) {
exists, err := d.mounter.PathExists(devicePath)
if err != nil {
return "", err
}

// If the path exists, assume it is not nvme device
if exists {
if partition != "" {
devicePath = devicePath + diskPartitionSuffix + partition
}
return devicePath, nil
}

Expand All @@ -49,7 +52,15 @@ func (d *nodeService) findDevicePath(devicePath, volumeID string) (string, error
// /dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_vol0fab1d5e3f72a5e23
nvmeName := "nvme-Amazon_Elastic_Block_Store_" + strings.Replace(volumeID, "-", "", -1)

return findNvmeVolume(nvmeName)
nvmeDevicePath, err := findNvmeVolume(nvmeName)
if err != nil {
//Return the nvmeDevicePath just for logging purpose
return nvmeDevicePath, err
}
if partition != "" {
devicePath = devicePath + nvmeDiskPartitionSuffix + partition
}
return nvmeDevicePath, nil
}

// findNvmeVolume looks for the nvme volume with the specified name
Expand Down
68 changes: 68 additions & 0 deletions pkg/driver/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ func TestNodeStageVolume(t *testing.T) {
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
},
}
stdVolContext = map[string]string{"partition": "1"}
devicePathWithPartition = devicePath + "1"
)
testCases := []struct {
name string
Expand Down Expand Up @@ -260,6 +262,25 @@ func TestNodeStageVolume(t *testing.T) {
mockMounter.EXPECT().FormatAndMount(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(0)
},
},
{
name: "success with partition",
request: &csi.NodeStageVolumeRequest{
PublishContext: map[string]string{DevicePathKey: devicePath},
StagingTargetPath: targetPath,
VolumeCapability: stdVolCap,
VolumeContext: stdVolContext,
VolumeId: "vol-test",
},
expectMock: func(mockMounter mocks.MockMounter) {
gomock.InOrder(
mockMounter.EXPECT().PathExists(gomock.Eq(devicePath)).Return(true, nil),
mockMounter.EXPECT().PathExists(gomock.Eq(targetPath)).Return(false, nil),
)
mockMounter.EXPECT().MakeDir(targetPath).Return(nil)
mockMounter.EXPECT().GetDeviceNameFromMount(targetPath).Return("", 1, nil)
mockMounter.EXPECT().FormatAndMount(gomock.Eq(devicePathWithPartition), gomock.Eq(targetPath), gomock.Eq(defaultFsType), gomock.Any())
},
},
{
name: "fail with in-flight request",
request: &csi.NodeStageVolumeRequest{
Expand Down Expand Up @@ -517,6 +538,8 @@ func TestNodePublishVolume(t *testing.T) {
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
},
}
stdVolContext := map[string]string{"partition": "1"}
devicePathWithPartition := devicePath + "1"
testCases := []struct {
name string
testFunc func(t *testing.T)
Expand Down Expand Up @@ -716,6 +739,51 @@ func TestNodePublishVolume(t *testing.T) {
}
},
},
{
name: "success normal with partition [raw block]",
testFunc: func(t *testing.T) {
mockCtl := gomock.NewController(t)
defer mockCtl.Finish()

mockMetadata := mocks.NewMockMetadataService(mockCtl)
mockMounter := mocks.NewMockMounter(mockCtl)

awsDriver := &nodeService{
metadata: mockMetadata,
mounter: mockMounter,
inFlight: internal.NewInFlight(),
}

gomock.InOrder(
mockMounter.EXPECT().PathExists(gomock.Eq(devicePath)).Return(true, nil),
mockMounter.EXPECT().PathExists(gomock.Eq("/test")).Return(false, nil),
)
mockMounter.EXPECT().MakeDir(gomock.Eq("/test")).Return(nil)
mockMounter.EXPECT().MakeFile(targetPath).Return(nil)
mockMounter.EXPECT().Mount(gomock.Eq(devicePathWithPartition), gomock.Eq(targetPath), gomock.Eq(""), gomock.Eq([]string{"bind"})).Return(nil)

req := &csi.NodePublishVolumeRequest{
PublishContext: map[string]string{DevicePathKey: "/dev/fake"},
StagingTargetPath: stagingTargetPath,
TargetPath: targetPath,
VolumeCapability: &csi.VolumeCapability{
AccessType: &csi.VolumeCapability_Block{
Block: &csi.VolumeCapability_BlockVolume{},
},
AccessMode: &csi.VolumeCapability_AccessMode{
Mode: csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER,
},
},
VolumeContext: stdVolContext,
VolumeId: "vol-test",
}

_, err := awsDriver.NodePublishVolume(context.TODO(), req)
if err != nil {
t.Fatalf("Expect no error but got: %v", err)
}
},
},
{
name: "fail no device path [raw block]",
testFunc: func(t *testing.T) {
Expand Down

0 comments on commit 2ff385f

Please sign in to comment.