mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-17 20:00:23 +00:00
rbd: add support for block-devices in NodeGetVolumeStats()
The NodeGetVolumeStats procedure can now be used to fetch the capacity of the RBD block-device. By default this is a thin-provisioned device, which means that the capacity is not reserved in the Ceph cluster. This makes it possible to over-provision the cluster. In order to detect the amount of storage used by the RBD block-device (when thin-provisioned), it is required to connect to the Ceph cluster. Unfortunately, the NodeGetVolumeStats CSI procedure does not provide enough parameters to connect to the Ceph cluster and fetch more details about the RBD image. Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
parent
c0ab4c03e6
commit
25d0a1cfc0
@ -875,3 +875,58 @@ func (ns *NodeServer) xfsSupportsReflink() bool {
|
||||
xfsHasReflink = xfsReflinkNoSupport
|
||||
return false
|
||||
}
|
||||
|
||||
// NodeGetVolumeStats returns volume stats.
|
||||
func (ns *NodeServer) NodeGetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) {
|
||||
var err error
|
||||
targetPath := req.GetVolumePath()
|
||||
if targetPath == "" {
|
||||
err = fmt.Errorf("targetpath %v is empty", targetPath)
|
||||
return nil, status.Error(codes.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
stat, err := os.Stat(targetPath)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "failed to get stat for targetpath %q: %v", targetPath, err)
|
||||
}
|
||||
|
||||
if stat.Mode().IsDir() {
|
||||
return csicommon.FilesystemNodeGetVolumeStats(ctx, targetPath)
|
||||
} else if (stat.Mode() & os.ModeDevice) == os.ModeDevice {
|
||||
return blockNodeGetVolumeStats(ctx, targetPath)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("targetpath %q is not a block device", targetPath)
|
||||
}
|
||||
|
||||
// blockNodeGetVolumeStats gets the metrics for a `volumeMode: Block` type of
|
||||
// volume. At the moment, only the size of the block-device can be returned, as
|
||||
// there are no secrets in the NodeGetVolumeStats request that enables us to
|
||||
// connect to the Ceph cluster.
|
||||
//
|
||||
// TODO: https://github.com/container-storage-interface/spec/issues/371#issuecomment-756834471
|
||||
func blockNodeGetVolumeStats(ctx context.Context, targetPath string) (*csi.NodeGetVolumeStatsResponse, error) {
|
||||
args := []string{"--noheadings", "--bytes", "--output=SIZE", targetPath}
|
||||
lsblkSize, _, err := util.ExecCommand(ctx, "/bin/lsblk", args...)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("lsblk %v returned an error: %w", args, err)
|
||||
util.ErrorLog(ctx, err.Error())
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
size, err := strconv.ParseInt(strings.TrimSpace(lsblkSize), 10, 64)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to convert %q to bytes: %w", lsblkSize, err)
|
||||
util.ErrorLog(ctx, err.Error())
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
}
|
||||
|
||||
return &csi.NodeGetVolumeStatsResponse{
|
||||
Usage: []*csi.VolumeUsage{
|
||||
{
|
||||
Total: size,
|
||||
Unit: csi.VolumeUsage_BYTES,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user