Skip to content

Commit 6895ab0

Browse files
committed
Add support for raw block devices and enable block device tests on external k8s testing
1 parent a438a15 commit 6895ab0

File tree

5 files changed

+104
-41
lines changed

5 files changed

+104
-41
lines changed

pkg/gce-pd-csi-driver/controller_test.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ func TestCreateVolumeArguments(t *testing.T) {
617617
},
618618
},
619619
{
620-
name: "fail with block volume capability",
620+
name: "success with block volume capability",
621621
req: &csi.CreateVolumeRequest{
622622
Name: name,
623623
CapacityRange: stdCapRange,
@@ -632,7 +632,12 @@ func TestCreateVolumeArguments(t *testing.T) {
632632
},
633633
},
634634
},
635-
expErrCode: codes.InvalidArgument,
635+
expVol: &csi.Volume{
636+
CapacityBytes: common.GbToBytes(20),
637+
VolumeId: testVolumeId,
638+
VolumeContext: nil,
639+
AccessibleTopology: stdTopology,
640+
},
636641
},
637642
{
638643
name: "fail with both mount and block volume capability",

pkg/gce-pd-csi-driver/node.go

+74-20
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,60 @@ func (ns *GCENodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePub
9595
return &csi.NodePublishVolumeResponse{}, nil
9696
}
9797

98-
if err := ns.Mounter.Interface.MakeDir(targetPath); err != nil {
99-
glog.Errorf("mkdir failed on disk %s (%v)", targetPath, err)
100-
return nil, err
101-
}
102-
10398
// Perform a bind mount to the full path to allow duplicate mounts of the same PD.
99+
fstype := ""
100+
sourcePath := ""
104101
options := []string{"bind"}
105102
if readOnly {
106103
options = append(options, "ro")
107104
}
108105

109-
err = ns.Mounter.Interface.Mount(stagingTargetPath, targetPath, "ext4", options)
106+
if mnt := volumeCapability.GetMount(); mnt != nil {
107+
if mnt.FsType != "" {
108+
fstype = mnt.FsType
109+
} else {
110+
// Default fstype is ext4
111+
fstype = "ext4"
112+
}
113+
114+
glog.V(4).Infof("NodePublishVolume with filesystem %s", fstype)
115+
116+
for _, flag := range mnt.MountFlags {
117+
options = append(options, flag)
118+
}
119+
120+
sourcePath = stagingTargetPath
121+
122+
if err := ns.Mounter.Interface.MakeDir(targetPath); err != nil {
123+
glog.Errorf("mkdir failed on disk %s (%v)", targetPath, err)
124+
return nil, err
125+
}
126+
} else if blk := volumeCapability.GetBlock(); blk != nil {
127+
glog.V(4).Infof("NodePublishVolume with block volume mode")
128+
129+
partition := ""
130+
if part, ok := req.GetVolumeContext()[common.VolumeAttributePartition]; ok {
131+
partition = part
132+
}
133+
134+
sourcePath, err = ns.getDevicePath(volumeID, partition)
135+
if err != nil {
136+
return nil, status.Error(codes.Internal, fmt.Sprintf("Error when getting device path: %v", err))
137+
}
138+
139+
// Expose block volume as file at target path
140+
err = ns.Mounter.MakeFile(targetPath)
141+
if err != nil {
142+
if removeErr := os.Remove(targetPath); removeErr != nil {
143+
return nil, status.Error(codes.Internal, fmt.Sprintf("Error removing block file at target path %v: %v, mounti error: %v", targetPath, removeErr, err))
144+
}
145+
return nil, status.Error(codes.Internal, fmt.Sprintf("Failed to create block file at target path %v: %v", targetPath, err))
146+
}
147+
} else {
148+
return nil, status.Error(codes.InvalidArgument, fmt.Sprintf("NodePublishVolume volume capability must specify either mount or block mode"))
149+
}
150+
151+
err = ns.Mounter.Interface.Mount(sourcePath, targetPath, fstype, options)
110152
if err != nil {
111153
notMnt, mntErr := ns.Mounter.Interface.IsLikelyNotMountPoint(targetPath)
112154
if mntErr != nil {
@@ -197,19 +239,9 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
197239
partition = part
198240
}
199241

200-
deviceName, err := common.GetDeviceName(volumeKey)
242+
devicePath, err := ns.getDevicePath(volumeID, partition)
201243
if err != nil {
202-
status.Error(codes.Internal, fmt.Sprintf("error getting device name: %v", err))
203-
}
204-
205-
devicePaths := ns.DeviceUtils.GetDiskByIdPaths(deviceName, partition)
206-
devicePath, err := ns.DeviceUtils.VerifyDevicePath(devicePaths)
207-
208-
if err != nil {
209-
return nil, status.Error(codes.Internal, fmt.Sprintf("Error verifying GCE PD (%q) is attached: %v", volumeKey.Name, err))
210-
}
211-
if devicePath == "" {
212-
return nil, status.Error(codes.Internal, fmt.Sprintf("Unable to find device path out of attempted paths: %v", devicePaths))
244+
return nil, status.Error(codes.Internal, fmt.Sprintf("Error when getting device path: %v", err))
213245
}
214246

215247
glog.V(4).Infof("Successfully found attached GCE PD %q at device path %s.", volumeKey.Name, devicePath)
@@ -251,8 +283,8 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
251283
options = append(options, flag)
252284
}
253285
} else if blk := volumeCapability.GetBlock(); blk != nil {
254-
// TODO(#64): Block volume support
255-
return nil, status.Error(codes.Unimplemented, fmt.Sprintf("Block volume support is not yet implemented"))
286+
// Noop for Block NodeStageVolume
287+
return &csi.NodeStageVolumeResponse{}, nil
256288
}
257289

258290
err = ns.Mounter.FormatAndMount(devicePath, stagingTargetPath, fstype, options)
@@ -333,3 +365,25 @@ func (ns *GCENodeServer) GetVolumeLimits() (int64, error) {
333365
}
334366
return volumeLimits, nil
335367
}
368+
369+
func (ns *GCENodeServer) getDevicePath(volumeID string, partition string) (string, error) {
370+
volumeKey, err := common.VolumeIDToKey(volumeID)
371+
if err != nil {
372+
return "", err
373+
}
374+
deviceName, err := common.GetDeviceName(volumeKey)
375+
if err != nil {
376+
return "", fmt.Errorf("error getting device name: %v", err)
377+
}
378+
379+
devicePaths := ns.DeviceUtils.GetDiskByIdPaths(deviceName, partition)
380+
devicePath, err := ns.DeviceUtils.VerifyDevicePath(devicePaths)
381+
382+
if err != nil {
383+
return "", fmt.Errorf("error verifying GCE PD (%q) is attached: %v", volumeKey.Name, err)
384+
}
385+
if devicePath == "" {
386+
return "", fmt.Errorf("unable to find device path out of attempted paths: %v", devicePaths)
387+
}
388+
return devicePath, nil
389+
}

pkg/gce-pd-csi-driver/utils.go

+21-16
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,30 @@ func logGRPC(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, h
6464
}
6565

6666
func validateVolumeCapabilities(vcs []*csi.VolumeCapability) error {
67+
isMnt := false
68+
isBlk := false
69+
6770
if vcs == nil {
6871
return errors.New("volume capabilities is nil")
6972
}
73+
74+
m := map[csi.VolumeCapability_AccessMode_Mode]bool{}
75+
7076
for _, vc := range vcs {
7177
if err := validateVolumeCapability(vc); err != nil {
7278
return err
7379
}
80+
if blk := vc.GetBlock(); blk != nil {
81+
isBlk = true
82+
}
83+
if mnt := vc.GetMount(); mnt != nil {
84+
isMnt = true
85+
}
86+
m[vc.GetAccessMode().GetMode()] = true
7487
}
75-
if err := crossValidateAccessModes(vcs); err != nil {
76-
return err
77-
}
78-
return nil
79-
}
8088

81-
func crossValidateAccessModes(vcs []*csi.VolumeCapability) error {
82-
m := map[csi.VolumeCapability_AccessMode_Mode]bool{}
83-
84-
for _, vc := range vcs {
85-
m[vc.GetAccessMode().GetMode()] = true
89+
if isBlk && isMnt {
90+
return errors.New("both mount and block volume capabilities specified")
8691
}
8792

8893
hasWriter := m[csi.VolumeCapability_AccessMode_SINGLE_NODE_WRITER]
@@ -104,13 +109,13 @@ func validateVolumeCapability(vc *csi.VolumeCapability) error {
104109
if err := validateAccessMode(vc.GetAccessMode()); err != nil {
105110
return err
106111
}
107-
if blk := vc.GetBlock(); blk != nil {
108-
// TODO(#64): Block volume support
109-
return errors.New("Block volume support is not yet implemented")
112+
blk := vc.GetBlock()
113+
mnt := vc.GetMount()
114+
if mnt == nil && blk == nil {
115+
return errors.New("must specify an access type")
110116
}
111-
if mnt := vc.GetMount(); mnt == nil {
112-
// TODO(#64): Change error message after block volume support
113-
return errors.New("Must specify an access type of Mount")
117+
if mnt != nil && blk != nil {
118+
return errors.New("specified both Mount and Block access types")
114119
}
115120
return nil
116121
}

pkg/gce-pd-csi-driver/utils_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func TestValidateVolumeCapabilities(t *testing.T) {
126126
expErr: true,
127127
},
128128
{
129-
name: "fail with block capabilities",
129+
name: "success with block capabilities",
130130
vc: []*csi.VolumeCapability{
131131
{
132132
AccessType: &csi.VolumeCapability_Block{
@@ -137,7 +137,6 @@ func TestValidateVolumeCapabilities(t *testing.T) {
137137
},
138138
},
139139
},
140-
expErr: true,
141140
},
142141
{
143142
name: "fail with reader + writer capabilities",

test/k8s-integration/config/test-config-template.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ DriverInfo:
1616
multipods: true
1717
fsGroup: true
1818
exec: true
19-
# block: true
19+
block: true
2020
# dataSource: true
2121
# RWX: true

0 commit comments

Comments
 (0)