From: "Fabian Grünbichler" <f.gruenbichler@proxmox.com>
To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>
Subject: Re: [pve-devel] [PATCH v5 storage 1/5] add disk reassign feature
Date: Wed, 31 Mar 2021 11:34:36 +0200 [thread overview]
Message-ID: <1617182685.l2t08rgixe.astroid@nora.none> (raw)
In-Reply-To: <20201215124840.29914-2-a.lauterer@proxmox.com>
maybe I am missing something, but AFAICT the volume_has_feature check
for the dir based plugins could also be moved to Plugin.pm, since it is
always identical:
> +sub volume_has_feature {
> + my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running, $opts) = @_;
> +
> + my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
> + $class->parse_volname($volname);
> +
> + if ($feature eq 'reassign') {
> + return 1 if !$isBase && $format =~ /^raw$|^qcow2$|^vmdk$/;
> + return undef;
> + } else {
> + return $class->SUPER::volume_has_feature($scfg, $feature, $storeid, $volname, $snapname, $running, $opts);
> + }
> +}
could then become
sub volume_has_feature {
my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running, $opts) = @_;
return $class->file_can_reassign_volume(@_)
if $feature eq 'reassign';
return $class->SUPER::volume_has_feature(@_);
}
with file_can_reassign_volume calling parse_volname (which is shared for
all dir based plugins!).
I guess theoretically we could also support renaming subvols (it's just
a dir rename?), but it's a pretty legacy usecase anyway so we can not
include it until someone complains.
On December 15, 2020 1:48 pm, Aaron Lauterer wrote:
> Functionality has been added for the following storage types:
>
> * dir based ones
> * directory
> * NFS
> * CIFS
> * gluster
> * ZFS
> * (thin) LVM
> * Ceph
>
> A new feature `reassign` has been introduced to mark which storage
> plugin supports the feature.
>
> Version API and AGE have been bumped.
>
> Signed-off-by: Aaron Lauterer <a.lauterer@proxmox.com>
> ---
> v4 -> v5:
> * rebased on master
> * bumped api ver and api age
> * rephrased "not implemented" message as suggested [0].
>
> v3 -> v4:
> * revert intermediate storage plugin for directory based plugins
> * add a `die "not supported"` method in Plugin.pm
> * dir based plugins now call the file_reassign_volume method in
> Plugin.pm as the generic file/directory based method
> * restored old `volume_has_feature` method in Plugin.pm and override it
> in directory based plugins to check against the new `reassign` feature
> (not too happy about the repetition for each plugin)
>
> v2 -> v3:
> * added feature flags instead of dummy "not implemented" methods in
> plugins which do not support it as that would break compatibility with
> 3rd party plugins.
> Had to make $features available outside the `has_features` method in
> Plugins.pm in order to be able to individually add features in the
> `BaseDirPlugin.pm`.
> * added the BaseDirPlugin.pm to maintain compat with 3rd party plugins,
> this is explained in the commit message
> * moved the actual renaming from the `reassign_volume` to a dedicated
> `rename_volume` method to make this functionality available to other
> possible uses in the future.
> * added support for linked clones ($base)
>
>
> rfc -> v1 -> v2: nothing changed
>
> [0] https://lists.proxmox.com/pipermail/pve-devel/2020-November/046031.html
>
> PVE/Storage.pm | 15 ++++++++--
> PVE/Storage/CIFSPlugin.pm | 19 +++++++++++++
> PVE/Storage/DirPlugin.pm | 19 +++++++++++++
> PVE/Storage/GlusterfsPlugin.pm | 19 +++++++++++++
> PVE/Storage/LVMPlugin.pm | 24 ++++++++++++++++
> PVE/Storage/LvmThinPlugin.pm | 1 +
> PVE/Storage/NFSPlugin.pm | 19 +++++++++++++
> PVE/Storage/Plugin.pm | 51 ++++++++++++++++++++++++++++++++++
> PVE/Storage/RBDPlugin.pm | 31 +++++++++++++++++++++
> PVE/Storage/ZFSPoolPlugin.pm | 26 +++++++++++++++++
> 10 files changed, 222 insertions(+), 2 deletions(-)
>
> diff --git a/PVE/Storage.pm b/PVE/Storage.pm
> index aded60e..ca3b7bd 100755
> --- a/PVE/Storage.pm
> +++ b/PVE/Storage.pm
> @@ -41,11 +41,11 @@ use PVE::Storage::DRBDPlugin;
> use PVE::Storage::PBSPlugin;
>
> # Storage API version. Increment it on changes in storage API interface.
> -use constant APIVER => 8;
> +use constant APIVER => 9;
> # Age is the number of versions we're backward compatible with.
> # This is like having 'current=APIVER' and age='APIAGE' in libtool,
> # see https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
> -use constant APIAGE => 7;
> +use constant APIAGE => 8;
>
> # load standard plugins
> PVE::Storage::DirPlugin->register();
> @@ -351,6 +351,7 @@ sub volume_snapshot_needs_fsfreeze {
> # snapshot - taking a snapshot is possible
> # sparseinit - volume is sparsely initialized
> # template - conversion to base image is possible
> +# reassign - reassigning disks to other guest is possible
> # $snap - check if the feature is supported for a given snapshot
> # $running - if the guest owning the volume is running
> # $opts - hash with further options:
> @@ -1843,6 +1844,16 @@ sub complete_volume {
> return $res;
> }
>
> +sub reassign_volume {
> + my ($cfg, $volid, $target_vmid) = @_;
> +
> + my ($storeid, $volname) = parse_volume_id($volid);
> + my $scfg = storage_config($cfg, $storeid);
> + my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
> +
> + return $plugin->reassign_volume($scfg, $storeid, $volname, $target_vmid);
> +}
> +
> # Various io-heavy operations require io/bandwidth limits which can be
> # configured on multiple levels: The global defaults in datacenter.cfg, and
> # per-storage overrides. When we want to do a restore from storage A to storage
> diff --git a/PVE/Storage/CIFSPlugin.pm b/PVE/Storage/CIFSPlugin.pm
> index be06cc7..f2ff5b4 100644
> --- a/PVE/Storage/CIFSPlugin.pm
> +++ b/PVE/Storage/CIFSPlugin.pm
> @@ -293,4 +293,23 @@ sub update_volume_notes {
> PVE::Storage::DirPlugin::update_volume_notes($class, @_);
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> + return $class->file_reassign_volume($scfg, $storeid, $volname, $target_vmid);
> +}
> +
> +sub volume_has_feature {
> + my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running, $opts) = @_;
> +
> + my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
> + $class->parse_volname($volname);
> +
> + if ($feature eq 'reassign') {
> + return 1 if !$isBase && $format =~ /^raw$|^qcow2$|^vmdk$/;
> + return undef;
> + } else {
> + return $class->SUPER::volume_has_feature($scfg, $feature, $storeid, $volname, $snapname, $running, $opts);
> + }
> +}
> +
> 1;
> diff --git a/PVE/Storage/DirPlugin.pm b/PVE/Storage/DirPlugin.pm
> index 2267f11..f4cb4bb 100644
> --- a/PVE/Storage/DirPlugin.pm
> +++ b/PVE/Storage/DirPlugin.pm
> @@ -156,4 +156,23 @@ sub check_config {
> return $opts;
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> + return $class->file_reassign_volume($scfg, $storeid, $volname, $target_vmid);
> +}
> +
> +sub volume_has_feature {
> + my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running, $opts) = @_;
> +
> + my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
> + $class->parse_volname($volname);
> +
> + if ($feature eq 'reassign') {
> + return 1 if !$isBase && $format =~ /^raw$|^qcow2$|^vmdk$/;
> + return undef;
> + } else {
> + return $class->SUPER::volume_has_feature($scfg, $feature, $storeid, $volname, $snapname, $running, $opts);
> + }
> +}
> +
> 1;
> diff --git a/PVE/Storage/GlusterfsPlugin.pm b/PVE/Storage/GlusterfsPlugin.pm
> index 2dd414d..5c9fd78 100644
> --- a/PVE/Storage/GlusterfsPlugin.pm
> +++ b/PVE/Storage/GlusterfsPlugin.pm
> @@ -348,4 +348,23 @@ sub check_connection {
> return defined($server) ? 1 : 0;
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> + return $class->file_reassign_volume($scfg, $storeid, $volname, $target_vmid);
> +}
> +
> +sub volume_has_feature {
> + my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running, $opts) = @_;
> +
> + my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
> + $class->parse_volname($volname);
> +
> + if ($feature eq 'reassign') {
> + return 1 if !$isBase && $format =~ /^raw$|^qcow2$|^vmdk$/;
> + return undef;
> + } else {
> + return $class->SUPER::volume_has_feature($scfg, $feature, $storeid, $volname, $snapname, $running, $opts);
> + }
> +}
> +
> 1;
> diff --git a/PVE/Storage/LVMPlugin.pm b/PVE/Storage/LVMPlugin.pm
> index 73e8e48..19898fa 100644
> --- a/PVE/Storage/LVMPlugin.pm
> +++ b/PVE/Storage/LVMPlugin.pm
> @@ -339,6 +339,13 @@ sub lvcreate {
> run_command($cmd, errmsg => "lvcreate '$vg/$name' error");
> }
>
> +sub lvrename {
> + my ($vg, $oldname, $newname) = @_;
> +
> + my $cmd = ['/sbin/lvrename', $vg, $oldname, $newname];
> + run_command($cmd, errmsg => "lvrename '${vg}/${oldname}' to '${newname}' error");
> +}
> +
> sub alloc_image {
> my ($class, $storeid, $scfg, $vmid, $fmt, $name, $size) = @_;
>
> @@ -583,6 +590,7 @@ sub volume_has_feature {
>
> my $features = {
> copy => { base => 1, current => 1},
> + reassign => {current => 1},
> };
>
> my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
> @@ -683,4 +691,20 @@ sub volume_import_write {
> input => '<&'.fileno($input_fh));
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> +
> + $class->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
> + my $target_volname = $class->find_free_diskname($storeid, $scfg, $target_vmid);
> + return $class->rename_volume($scfg, $storeid, $volname, $target_volname, $target_vmid);
> + });
> +}
> +
> +sub rename_volume {
> + my ($class, $scfg, $storeid, $source_volname, $target_volname, $vmid) = @_;
> +
> + lvrename($scfg->{vgname}, $source_volname, $target_volname);
> + return "${storeid}:${target_volname}";
> +}
> +
> 1;
> diff --git a/PVE/Storage/LvmThinPlugin.pm b/PVE/Storage/LvmThinPlugin.pm
> index c9e127c..895af8b 100644
> --- a/PVE/Storage/LvmThinPlugin.pm
> +++ b/PVE/Storage/LvmThinPlugin.pm
> @@ -355,6 +355,7 @@ sub volume_has_feature {
> template => { current => 1},
> copy => { base => 1, current => 1, snap => 1},
> sparseinit => { base => 1, current => 1},
> + reassign => {current => 1},
> };
>
> my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
> diff --git a/PVE/Storage/NFSPlugin.pm b/PVE/Storage/NFSPlugin.pm
> index e8e27c0..b5a8f75 100644
> --- a/PVE/Storage/NFSPlugin.pm
> +++ b/PVE/Storage/NFSPlugin.pm
> @@ -180,4 +180,23 @@ sub update_volume_notes {
> PVE::Storage::DirPlugin::update_volume_notes($class, @_);
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> + return $class->file_reassign_volume($scfg, $storeid, $volname, $target_vmid);
> +}
> +
> +sub volume_has_feature {
> + my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running, $opts) = @_;
> +
> + my ($vtype, $name, $vmid, $basename, $basevmid, $isBase, $format) =
> + $class->parse_volname($volname);
> +
> + if ($feature eq 'reassign') {
> + return 1 if !$isBase && $format =~ /^raw$|^qcow2$|^vmdk$/;
> + return undef;
> + } else {
> + return $class->SUPER::volume_has_feature($scfg, $feature, $storeid, $volname, $snapname, $running, $opts);
> + }
> +}
> +
> 1;
> diff --git a/PVE/Storage/Plugin.pm b/PVE/Storage/Plugin.pm
> index 57c58a9..aa496e2 100644
> --- a/PVE/Storage/Plugin.pm
> +++ b/PVE/Storage/Plugin.pm
> @@ -925,6 +925,7 @@ sub storage_can_replicate {
> return 0;
> }
>
> +
> sub volume_has_feature {
> my ($class, $scfg, $feature, $storeid, $volname, $snapname, $running, $opts) = @_;
>
> @@ -1454,4 +1455,54 @@ sub volume_import_formats {
> return ();
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> + die "not implemented in storage plugin '$class'\n";
> +}
> +
> +# general reassignment method for file/directory based storages
> +sub file_reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> +
> + my $base;
> + my $base_vmid;
> + my $format;
> + my $source_vmid;
> +
> + (undef, $volname, $source_vmid, $base, $base_vmid, undef, $format) = $class->parse_volname($volname);
> +
> + # parse_volname strips the directory from volname
> + my $source_volname = "${source_vmid}/${volname}";
> +
> + if ($base) {
> + $base = "${base_vmid}/${base}/";
> + } else {
> + $base = '';
> + }
> +
> + $class->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
> + my $target_volname = $class->find_free_diskname($storeid, $scfg, $target_vmid, $format, 1);
> +
> + return $class->rename_volume($scfg, $storeid, $source_volname, $target_volname, $target_vmid, $base);
> + });
> +}
> +
> +sub rename_volume {
> + my ($class, $scfg, $storeid, $source_volname, $target_volname, $vmid, $base) = @_;
> +
> + my $basedir = $class->get_subdir($scfg, 'images');
> + my $imagedir = "${basedir}/${vmid}";
> +
> + mkpath $imagedir;
> +
> + my $old_path = "${basedir}/${source_volname}";
> + my $new_path = "${imagedir}/${target_volname}";
> +
> + rename($old_path, $new_path) ||
> + die "rename '$old_path' to '$new_path' failed - $!\n";
> +
> + return "${storeid}:${base}${vmid}/${target_volname}";
> +}
> +
> +
> 1;
> diff --git a/PVE/Storage/RBDPlugin.pm b/PVE/Storage/RBDPlugin.pm
> index fab6d57..86a9a0d 100644
> --- a/PVE/Storage/RBDPlugin.pm
> +++ b/PVE/Storage/RBDPlugin.pm
> @@ -712,6 +712,7 @@ sub volume_has_feature {
> template => { current => 1},
> copy => { base => 1, current => 1, snap => 1},
> sparseinit => { base => 1, current => 1},
> + reassign => {current => 1},
> };
>
> my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
> @@ -728,4 +729,34 @@ sub volume_has_feature {
> return undef;
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> +
> + my $base;;
> + (undef, $volname, undef, $base) = $class->parse_volname($volname);
> +
> + if ($base) {
> + $base = $base . '/';
> + } else {
> + $base = '';
> + }
> +
> + $class->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
> + my $target_volname = $class->find_free_diskname($storeid, $scfg, $target_vmid);
> + return $class->rename_volume($scfg, $storeid, $volname, $target_volname, $target_vmid, $base);
> + });
> +}
> +
> +sub rename_volume {
> + my ($class, $scfg, $storeid, $source_volname, $target_volname, $vmid, $base) = @_;
> +
> + my $cmd = $rbd_cmd->($scfg, $storeid, 'rename', $source_volname, $target_volname);
> +
> + run_rbd_command(
> + $cmd,
> + errmsg => "could not rename image '${source_volname}' to '${target_volname}'",
> + );
> + return "${storeid}:${base}${target_volname}";
> +}
> +
> 1;
> diff --git a/PVE/Storage/ZFSPoolPlugin.pm b/PVE/Storage/ZFSPoolPlugin.pm
> index 3054331..adccddf 100644
> --- a/PVE/Storage/ZFSPoolPlugin.pm
> +++ b/PVE/Storage/ZFSPoolPlugin.pm
> @@ -659,6 +659,7 @@ sub volume_has_feature {
> copy => { base => 1, current => 1},
> sparseinit => { base => 1, current => 1},
> replicate => { base => 1, current => 1},
> + reassign => {current => 1},
> };
>
> my ($vtype, $name, $vmid, $basename, $basevmid, $isBase) =
> @@ -761,4 +762,29 @@ sub volume_import_formats {
> return $class->volume_export_formats($scfg, $storeid, $volname, undef, $base_snapshot, $with_snapshots);
> }
>
> +sub reassign_volume {
> + my ($class, $scfg, $storeid, $volname, $target_vmid) = @_;
> +
> + my $base;;
> + (undef, $volname, undef, $base) = $class->parse_volname($volname);
> +
> + if ($base) {
> + $base = $base . '/';
> + } else {
> + $base = '';
> + }
> +
> + $class->cluster_lock_storage($storeid, $scfg->{shared}, undef, sub {
> + my $target_volname = $class->find_free_diskname($storeid, $scfg, $target_vmid);
> + return $class->rename_volume($scfg, $storeid, $volname, $target_volname, $target_vmid, $base);
> + });
> +}
> +
> +sub rename_volume {
> + my ($class, $scfg, $storeid, $source_volname, $target_volname, $vmid, $base) = @_;
> +
> + $class->zfs_request($scfg, 5, 'rename', "$scfg->{pool}/$source_volname", "$scfg->{pool}/$target_volname");
> + return "${storeid}:${base}${target_volname}";
> +}
> +
> 1;
> --
> 2.20.1
>
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
>
>
>
next prev parent reply other threads:[~2021-03-31 9:34 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-15 12:48 [pve-devel] [PATCH v5 series 0/5] disk reassign: add new feature Aaron Lauterer
2020-12-15 12:48 ` [pve-devel] [PATCH v5 storage 1/5] add disk reassign feature Aaron Lauterer
2021-03-31 9:34 ` Fabian Grünbichler [this message]
2020-12-15 12:48 ` [pve-devel] [PATCH v5 qemu-server 2/5] disk reassign: add API endpoint Aaron Lauterer
2021-03-31 9:23 ` Fabian Grünbichler
2021-04-01 14:24 ` Aaron Lauterer
2020-12-15 12:48 ` [pve-devel] [PATCH v5 qemu-server 3/5] cli: disk reassign: add reassign_disk to qm command Aaron Lauterer
2020-12-15 12:48 ` [pve-devel] [PATCH v5 guest-common 4/5] Replication: mention disk reassign in comment of possible reasons Aaron Lauterer
2020-12-15 12:48 ` [pve-devel] [PATCH v5 manager 5/5] ui: tasks: add qmreassign task description Aaron Lauterer
2021-02-15 14:59 ` [pve-devel] [PATCH v5 series 0/5] disk reassign: add new feature Aaron Lauterer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1617182685.l2t08rgixe.astroid@nora.none \
--to=f.gruenbichler@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.