Skip to content

Commit 7568643

Browse files
authored
Merge pull request #2178 from hajiler/pvc-mount-issue-fix
Add NodeStageVolume disk size validation before mounting
2 parents 0898415 + a6bd669 commit 7568643

File tree

6 files changed

+80
-4
lines changed

6 files changed

+80
-4
lines changed

cmd/gce-pd-csi-driver/main.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ var (
9797

9898
diskTopology = flag.Bool("disk-topology", false, "If set to true, the driver will add a disk-type.gke.io/[disk-type] topology label when the StorageClass has the use-allowed-disk-topology parameter set to true. That topology label is included in the Topologies returned in CreateVolumeResponse. This flag is disabled by default.")
9999

100+
enableDiskSizeValidation = flag.Bool("enable-disk-size-validation", false, "If set to true, the driver will validate that the requested disk size is matches the physical disk size. This flag is disabled by default.")
101+
100102
version string
101103
)
102104

@@ -248,7 +250,8 @@ func handle() {
248250
maxBackoffDuration := time.Duration(*errorBackoffMaxDurationMs) * time.Millisecond
249251
// TODO(2042): Move more of the constructor args into this struct
250252
args := &driver.GCEControllerServerArgs{
251-
EnableDiskTopology: *diskTopology,
253+
EnableDiskTopology: *diskTopology,
254+
EnableDiskSizeValidation: *enableDiskSizeValidation,
252255
}
253256

254257
controllerServer = driver.NewControllerServer(gceDriver, cloudProvider, initialBackoffDuration, maxBackoffDuration, fallbackRequisiteZones, *enableStoragePoolsFlag, *enableDataCacheFlag, multiZoneVolumeHandleConfig, listVolumesConfig, provisionableDisksConfig, *enableHdHAFlag, args)

pkg/common/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const (
4848

4949
ContextDataCacheSize = "data-cache-size"
5050
ContextDataCacheMode = "data-cache-mode"
51+
ContextDiskSizeGB = "disk-size"
5152

5253
// Keys in the publish context
5354
ContexLocalSsdCacheSize = "local-ssd-cache-size"

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"math/rand"
2222
neturl "net/url"
2323
"sort"
24+
"strconv"
2425
"strings"
2526
"time"
2627

@@ -121,11 +122,13 @@ type GCEControllerServer struct {
121122
// new RPC methods that might be introduced in future versions of the spec.
122123
csi.UnimplementedControllerServer
123124

124-
EnableDiskTopology bool
125+
EnableDiskTopology bool
126+
EnableDiskSizeValidation bool
125127
}
126128

127129
type GCEControllerServerArgs struct {
128-
EnableDiskTopology bool
130+
EnableDiskTopology bool
131+
EnableDiskSizeValidation bool
129132
}
130133

131134
type MultiZoneVolumeHandleConfig struct {
@@ -1113,7 +1116,7 @@ func (gceCS *GCEControllerServer) executeControllerPublishVolume(ctx context.Con
11131116
volumeCapability := req.GetVolumeCapability()
11141117

11151118
pubVolResp := &csi.ControllerPublishVolumeResponse{
1116-
PublishContext: nil,
1119+
PublishContext: map[string]string{},
11171120
}
11181121

11191122
// Set data cache publish context
@@ -1162,6 +1165,9 @@ func (gceCS *GCEControllerServer) executeControllerPublishVolume(ctx context.Con
11621165
}
11631166
return nil, common.LoggedError("Failed to getDisk: ", err), disk
11641167
}
1168+
if gceCS.EnableDiskSizeValidation && pubVolResp.GetPublishContext() != nil {
1169+
pubVolResp.PublishContext[common.ContextDiskSizeGB] = strconv.FormatInt(disk.GetSizeGb(), 10)
1170+
}
11651171
instance, err := gceCS.CloudProvider.GetInstanceOrError(ctx, project, instanceZone, instanceName)
11661172
if err != nil {
11671173
if gce.IsGCENotFoundError(err) {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ func NewControllerServer(gceDriver *GCEDriver, cloudProvider gce.GCECompute, err
177177
provisionableDisksConfig: provisionableDisksConfig,
178178
enableHdHA: enableHdHA,
179179
EnableDiskTopology: args.EnableDiskTopology,
180+
EnableDiskSizeValidation: args.EnableDiskSizeValidation,
180181
}
181182
}
182183

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,17 @@ func (ns *GCENodeServer) NodeStageVolume(ctx context.Context, req *csi.NodeStage
446446
klog.V(4).Infof("CSI volume is read-only, mounting with extra option ro")
447447
}
448448

449+
// If a disk size is provided in the publish context, ensure it matches the actual device size.
450+
if expectedSize := req.GetPublishContext()[common.ContextDiskSizeGB]; expectedSize != "" {
451+
actualSize, err := getBlockSizeBytes(devicePath, ns.Mounter)
452+
if err != nil {
453+
return nil, status.Error(codes.Internal, fmt.Sprintf("failed to get block size for '%s': %v", devicePath, err.Error()))
454+
}
455+
if expectedSize != strconv.FormatInt(actualSize, 10) {
456+
return nil, status.Error(codes.Internal, fmt.Sprintf("expected block size %q, got %q", expectedSize, strconv.FormatInt(actualSize, 10)))
457+
}
458+
}
459+
449460
err = ns.formatAndMount(devicePath, stagingTargetPath, fstype, options, ns.Mounter)
450461
if err != nil {
451462
// If a volume is created from a content source like snapshot or cloning, the filesystem might get marked

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"google.golang.org/grpc/codes"
3434
"google.golang.org/grpc/status"
3535
"k8s.io/mount-utils"
36+
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/common"
3637
"sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/deviceutils"
3738
metadataservice "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/gce-cloud-provider/metadata"
3839
mountmanager "sigs.k8s.io/gcp-compute-persistent-disk-csi-driver/pkg/mount-manager"
@@ -1118,6 +1119,41 @@ func TestNodeStageVolume(t *testing.T) {
11181119
},
11191120
},
11201121
},
1122+
{
1123+
name: "Valid request with disk size check",
1124+
req: &csi.NodeStageVolumeRequest{
1125+
VolumeId: volumeID,
1126+
StagingTargetPath: stagingPath,
1127+
VolumeCapability: stdVolCap,
1128+
PublishContext: map[string]string{common.ContextDiskSizeGB: "1"},
1129+
},
1130+
deviceSize: 1,
1131+
blockExtSize: 1,
1132+
readonlyBit: "1",
1133+
expResize: false,
1134+
expCommandList: []fakeCmd{
1135+
{
1136+
cmd: "blockdev",
1137+
args: "--getsize64 /dev/disk/fake-path",
1138+
stdout: "%v",
1139+
},
1140+
{
1141+
cmd: "blkid",
1142+
args: "-p -s TYPE -s PTTYPE -o export /dev/disk/fake-path",
1143+
stdout: "DEVNAME=/dev/sdb\nTYPE=%v",
1144+
},
1145+
{
1146+
cmd: "fsck",
1147+
args: "-a /dev/disk/fake-path",
1148+
stdout: "",
1149+
},
1150+
{
1151+
cmd: "blockdev",
1152+
args: "--getro /dev/disk/fake-path",
1153+
stdout: "%v",
1154+
},
1155+
},
1156+
},
11211157
{
11221158
name: "Invalid request (Bad Access Mode)",
11231159
req: &csi.NodeStageVolumeRequest{
@@ -1197,6 +1233,24 @@ func TestNodeStageVolume(t *testing.T) {
11971233
},
11981234
expErrCode: codes.InvalidArgument,
11991235
},
1236+
{
1237+
name: "Invalid request, block size mismatch",
1238+
req: &csi.NodeStageVolumeRequest{
1239+
VolumeId: volumeID,
1240+
StagingTargetPath: stagingPath,
1241+
VolumeCapability: stdVolCap,
1242+
PublishContext: map[string]string{common.ContextDiskSizeGB: "10"},
1243+
},
1244+
deviceSize: 5,
1245+
expErrCode: codes.Internal,
1246+
expCommandList: []fakeCmd{
1247+
{
1248+
cmd: "blockdev",
1249+
args: "--getsize64 /dev/disk/fake-path",
1250+
stdout: "%v",
1251+
},
1252+
},
1253+
},
12001254
}
12011255
for _, tc := range testCases {
12021256
t.Run(tc.name, func(t *testing.T) {

0 commit comments

Comments
 (0)