plugin: add method to get qemu blockdevice options for volume

This is in preparation to switch qemu-server from using '-drive' to
the modern '-blockdev' in the QEMU commandline options as well as for
the qemu-storage-daemon, which only supports '-blockdev'. The plugins
know best what driver and options are needed to access an image, so
a dedicated plugin method returning the necessary parameters for
'-blockdev' is the most straight-forward.

There intentionally is only handling for absolute paths in the default
plugin implementation. Any plugin requiring more needs to implement
the method itself. With PVE 9 being a major release and most popular
plugins not using special protocols like 'rbd://', this seems
acceptable.

For NBD, etc. qemu-server should construct the blockdev object.

Signed-off-by: Fiona Ebner <f.ebner@proxmox.com>
This commit is contained in:
Fiona Ebner
2025-07-02 18:27:38 +02:00
committed by Fabian Grünbichler
parent 823707a7ac
commit 073c5677c7
2 changed files with 73 additions and 0 deletions

View File

@ -719,6 +719,23 @@ sub abs_filesystem_path {
return $path;
}
# see the documentation for the plugin method
sub qemu_blockdev_options {
my ($cfg, $volid) = @_;
my ($storeid, $volname) = parse_volume_id($volid);
my $scfg = storage_config($cfg, $storeid);
my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
my ($vtype) = $plugin->parse_volname($volname);
die "cannot use volume of type '$vtype' as a QEMU blockdevice\n"
if $vtype ne 'images' && $vtype ne 'iso' && $vtype ne 'import';
return $plugin->qemu_blockdev_options($scfg, $storeid, $volname);
}
# used as last resort to adapt volnames when migrating
my $volname_for_storage = sub {
my ($cfg, $storeid, $name, $vmid, $format) = @_;

View File

@ -1961,6 +1961,62 @@ sub rename_volume {
return "${storeid}:${base}${target_vmid}/${target_volname}";
}
=pod
=head3 qemu_blockdev_options
$blockdev = $plugin->qemu_blockdev_options($scfg, $storeid, $volname)
Returns a hash reference with the basic options needed to open the volume via QEMU's C<-blockdev>
API. This at least requires a C<< $blockdev->{driver} >> and a reference to the image, e.g.
C<< $blockdev->{filename} >> for the C<file> driver. For files, the C<file> driver can be used. For
host block devices, the C<host_device> driver can be used. The plugin must not set options like
C<cache> or C<aio>. Those are managed by qemu-server and will be overwritten. For other available
drivers and the exact specification of the options, see
L<https://qemu.readthedocs.io/en/master/interop/qemu-qmp-ref.html#object-QMP-block-core.BlockdevOptions>
While Perl does not have explicit types, the result will need to be converted to JSON later and
match the QMP specification (see link above), so implicit types are important. In the return value,
use C<JSON::true> and C<JSON::false> for booleans, C<"$value"> for strings, and C<int($value)> for
integers.
The volume is activated before the function is called.
Arguments:
=over
=item C<$scfg>: The hash reference with the storage configuration.
=item C<$storeid>: The storage ID.
=item C<$volume>: The volume name.
=back
=cut
sub qemu_blockdev_options {
my ($class, $scfg, $storeid, $volname) = @_;
my $blockdev = {};
my ($path) = $class->filesystem_path($scfg, $volname);
if ($path =~ m|^/|) {
# The 'file' driver only works for regular files. The check below is taken from
# block/file-posix.c:hdev_probe_device() in QEMU. Do not bother with detecting 'host_cdrom'
# devices here, those are not managed by the storage layer.
my $st = File::stat::stat($path) or die "stat for '$path' failed - $!\n";
my $driver = (S_ISCHR($st->mode) || S_ISBLK($st->mode)) ? 'host_device' : 'file';
$blockdev = { driver => $driver, filename => $path };
} else {
die "storage plugin doesn't implement qemu_blockdev_options() method\n";
}
return $blockdev;
}
# Used by storage plugins for external backup providers. See PVE::BackupProvider::Plugin for the API
# the provider needs to implement.
#