mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-12-18 11:00:25 +00:00
rbd: expand filesystem during NodeStageVolume
If the volume with a bigger size is created from a snapshot or from another volume we need to exapand the filesystem also in the csidriver as nodeExpand request is not triggered for this one, During NodeStageVolume we can expand the filesystem by checking filesystem needs expansion or not. If its a encrypted device, check the device size of rbd device and the LUKS device if required the device will be expanded before expanding the filesystem. Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
parent
69ae19e0cb
commit
3169c8e23a
@ -427,26 +427,15 @@ func (ns *NodeServer) stageTransaction(
|
|||||||
}
|
}
|
||||||
transaction.isMounted = true
|
transaction.isMounted = true
|
||||||
|
|
||||||
// resize if its fileSystemType static volume.
|
// As we are supporting the restore of a volume to a bigger size and
|
||||||
if staticVol && !isBlock {
|
// creating bigger size clone from a volume, we need to check filesystem
|
||||||
var ok bool
|
// resize is required, if required resize filesystem.
|
||||||
resizer := mount.NewResizeFs(utilexec.New())
|
// in case of encrypted block PVC resize only the LUKS device.
|
||||||
ok, err = resizer.NeedResize(devicePath, stagingTargetPath)
|
err = resizeNodeStagePath(ctx, isBlock, transaction, req.GetVolumeId(), stagingTargetPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return transaction, status.Errorf(codes.Internal,
|
return transaction, err
|
||||||
"need resize check failed on devicePath %s and staingPath %s, error: %v",
|
|
||||||
devicePath,
|
|
||||||
stagingTargetPath,
|
|
||||||
err)
|
|
||||||
}
|
|
||||||
if ok {
|
|
||||||
ok, err = resizer.Resize(devicePath, stagingTargetPath)
|
|
||||||
if !ok {
|
|
||||||
return transaction, status.Errorf(codes.Internal,
|
|
||||||
"resize failed on path %s, error: %v", stagingTargetPath, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !readOnly {
|
if !readOnly {
|
||||||
// #nosec - allow anyone to write inside the target path
|
// #nosec - allow anyone to write inside the target path
|
||||||
err = os.Chmod(stagingTargetPath, 0o777)
|
err = os.Chmod(stagingTargetPath, 0o777)
|
||||||
@ -455,6 +444,87 @@ func (ns *NodeServer) stageTransaction(
|
|||||||
return transaction, err
|
return transaction, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// resizeNodeStagePath resizes the device if its encrypted and it also resizes
|
||||||
|
// the stagingTargetPath if filesystem needs resize.
|
||||||
|
func resizeNodeStagePath(ctx context.Context,
|
||||||
|
isBlock bool,
|
||||||
|
transaction *stageTransaction,
|
||||||
|
volID,
|
||||||
|
stagingTargetPath string) error {
|
||||||
|
var err error
|
||||||
|
devicePath := transaction.devicePath
|
||||||
|
var ok bool
|
||||||
|
|
||||||
|
// if its a non encrypted block device we dont need any expansion
|
||||||
|
if isBlock && !transaction.isEncrypted {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
resizer := mount.NewResizeFs(utilexec.New())
|
||||||
|
|
||||||
|
if transaction.isEncrypted {
|
||||||
|
devicePath, err = resizeEncryptedDevice(ctx, volID, stagingTargetPath, devicePath)
|
||||||
|
if err != nil {
|
||||||
|
return status.Error(codes.Internal, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check stagingPath needs resize.
|
||||||
|
ok, err = resizer.NeedResize(devicePath, stagingTargetPath)
|
||||||
|
if err != nil {
|
||||||
|
return status.Errorf(codes.Internal,
|
||||||
|
"need resize check failed on devicePath %s and staingPath %s, error: %v",
|
||||||
|
devicePath,
|
||||||
|
stagingTargetPath,
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
// return nil if no resize is required
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ok, err = resizer.Resize(devicePath, stagingTargetPath)
|
||||||
|
if !ok {
|
||||||
|
return status.Errorf(codes.Internal,
|
||||||
|
"resize failed on path %s, error: %v", stagingTargetPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resizeEncryptedDevice(ctx context.Context, volID, stagingTargetPath, devicePath string) (string, error) {
|
||||||
|
rbdDevSize, err := getDeviceSize(ctx, devicePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf(
|
||||||
|
"failed to get device size of %s and staingPath %s, error: %w",
|
||||||
|
devicePath,
|
||||||
|
stagingTargetPath,
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
_, mapperPath := util.VolumeMapper(volID)
|
||||||
|
encDevSize, err := getDeviceSize(ctx, mapperPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf(
|
||||||
|
"failed to get device size of %s and staingPath %s, error: %w",
|
||||||
|
mapperPath,
|
||||||
|
stagingTargetPath,
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
// if the rbd device `/dev/rbd0` size is greater than LUKS device size
|
||||||
|
// we need to resize the LUKS device.
|
||||||
|
if rbdDevSize > encDevSize {
|
||||||
|
// The volume is encrypted, resize an active mapping
|
||||||
|
err = util.ResizeEncryptedVolume(ctx, mapperPath)
|
||||||
|
if err != nil {
|
||||||
|
log.ErrorLog(ctx, "failed to resize device %s: %v",
|
||||||
|
mapperPath, err)
|
||||||
|
|
||||||
|
return "", fmt.Errorf(
|
||||||
|
"failed to resize device %s: %w", mapperPath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapperPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
func flattenImageBeforeMapping(
|
func flattenImageBeforeMapping(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
volOptions *rbdVolume,
|
volOptions *rbdVolume,
|
||||||
@ -1168,3 +1238,22 @@ func blockNodeGetVolumeStats(ctx context.Context, targetPath string) (*csi.NodeG
|
|||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getDeviceSize gets the block device size.
|
||||||
|
func getDeviceSize(ctx context.Context, devicePath string) (uint64, error) {
|
||||||
|
output, _, err := util.ExecCommand(ctx, "blockdev", "--getsize64", devicePath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("blockdev %v returned an error: %w", devicePath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
outStr := strings.TrimSpace(output)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed to read size of device %s: %s: %w", devicePath, outStr, err)
|
||||||
|
}
|
||||||
|
size, err := strconv.ParseUint(outStr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("failed to parse size of device %s %s: %w", devicePath, outStr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return size, nil
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user