this is the recommended way upstream to pass this information, and all commands
(other than those not operating on images/snapshots) consume them (rbd(8)):

>       image-spec      is [pool-name/[namespace-name/]]image-name
>       snap-spec       is [pool-name/[namespace-name/]]image-name@snap-name
> [..]
> You may specify each name individually, using --pool, --namespace, --image,
> and --snap options, but this is discouraged in favor of the above spec
> syntax.

We already had a few places calling `get_rbd_path` previously (which meant
passing the pool and namespace information twice to Ceph).

It also allows us to replace the custom import and unmap handling with just
custom `ls` handling, reducing the workarounds in rbd_cmd.

Fixes: #6338 , because `rbd import` doesn't handle a separate `--namespace ..`
at all..

Signed-off-by: Fabian Grünbichler <f.gruenbich...@proxmox.com>
---
we could probably switch some more only-technically-public subs over to
take a spec instead of image name or image + snapshot name, if desired..

alternatively, we could also just special case the import call, and/or convince
upstream to implement --namespace handling there as well or send a patch doing
that their way..

 src/PVE/Storage/RBDPlugin.pm | 133 ++++++++++++++++++-----------------
 1 file changed, 69 insertions(+), 64 deletions(-)

diff --git a/src/PVE/Storage/RBDPlugin.pm b/src/PVE/Storage/RBDPlugin.pm
index 8c67a37..3bb5807 100644
--- a/src/PVE/Storage/RBDPlugin.pm
+++ b/src/PVE/Storage/RBDPlugin.pm
@@ -89,22 +89,17 @@ my $rbd_cmd = sub {
     my ($scfg, $storeid, $op, @options) = @_;
 
     my $cmd_option = PVE::CephConfig::ceph_connect_option($scfg, $storeid);
-    my $pool =  $scfg->{pool} ? $scfg->{pool} : 'rbd';
 
     my $cmd = ['/usr/bin/rbd'];
-    if ($op eq 'import') {
-       push $cmd->@*, '--dest-pool', $pool;
-    } else {
+    # `ls` doesn't take an image-spec, otherwise pool and namespace should be 
specified there
+    if ($op eq 'ls') {
+       my $pool = $scfg->{pool} ? $scfg->{pool} : 'rbd';
        push $cmd->@*, '-p', $pool;
+       if (defined($scfg->{namespace})) {
+           push @$cmd, '--namespace', $cfg->{namespace};
+       }
     }
 
-    if (defined(my $namespace = $scfg->{namespace})) {
-       # some subcommands will fail if the --namespace parameter is present
-       my $no_namespace_parameter = {
-           unmap => 1,
-       };
-       push @$cmd, '--namespace', "$namespace" if 
!$no_namespace_parameter->{$op};
-    }
     push @$cmd, '-c', $cmd_option->{ceph_conf} if ($cmd_option->{ceph_conf});
     push @$cmd, '-m', $cmd_option->{mon_host} if ($cmd_option->{mon_host});
     push @$cmd, '--auth_supported', $cmd_option->{auth_supported} if 
($cmd_option->{auth_supported});
@@ -144,9 +139,11 @@ my $krbd_feature_update = sub {
     my $to_disable = join(',', grep {  $active_features->{$_} } @disable);
     my $to_enable  = join(',', grep { !$active_features->{$_} } @enable );
 
+    my $image_spec = get_rbd_path($scfg, $name);
+
     if ($to_disable) {
        print "disable RBD image features this kernel RBD drivers is not 
compatible with: $to_disable\n";
-       my $cmd = $rbd_cmd->($scfg, $storeid, 'feature', 'disable', $name, 
$to_disable);
+       my $cmd = $rbd_cmd->($scfg, $storeid, 'feature', 'disable', 
$image_spec, $to_disable);
        run_rbd_command(
            $cmd,
            errmsg => "could not disable krbd-incompatible image features 
'$to_disable' for rbd image: $name",
@@ -155,7 +152,7 @@ my $krbd_feature_update = sub {
     if ($to_enable) {
        print "enable RBD image features this kernel RBD drivers supports: 
$to_enable\n";
        eval {
-           my $cmd = $rbd_cmd->($scfg, $storeid, 'feature', 'enable', $name, 
$to_enable);
+           my $cmd = $rbd_cmd->($scfg, $storeid, 'feature', 'enable', 
$image_spec, $to_enable);
            run_rbd_command(
                $cmd,
                errmsg => "could not enable krbd-compatible image features 
'$to_enable' for rbd image: $name",
@@ -234,9 +231,9 @@ sub rbd_ls {
 }
 
 sub rbd_ls_snap {
-    my ($scfg, $storeid, $name) = @_;
+    my ($scfg, $storeid, $image_spec) = @_;
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'ls', $name, '--format', 
'json');
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'ls', $image_spec, 
'--format', 'json');
 
     my $raw = '';
     run_rbd_command($cmd, errmsg => "rbd error", errfunc => sub {}, outfunc => 
sub { $raw .= shift; });
@@ -244,9 +241,9 @@ sub rbd_ls_snap {
     my $list;
     if ($raw =~ m/^(\[.*\])$/s) { # untaint
        $list = eval { JSON::decode_json($1) };
-       die "invalid JSON output from 'rbd snap ls $name': $@\n" if $@;
+       die "invalid JSON output from 'rbd snap ls $image_spec': $@\n" if $@;
     } else {
-       die "got unexpected data from 'rbd snap ls $name': '$raw'\n";
+       die "got unexpected data from 'rbd snap ls $image_spec': '$raw'\n";
     }
 
     $list = [] if !defined($list);
@@ -269,11 +266,9 @@ sub rbd_volume_info {
     my ($scfg, $storeid, $volname, $snap) = @_;
 
     my $cmd = undef;
+    my $spec = get_rbd_path($scfg, $volname, $snap);
 
-    my @options = ('info', $volname, '--format', 'json');
-    if ($snap) {
-       push @options, '--snap', $snap;
-    }
+    my @options = ('info', $spec, '--format', 'json');
 
     $cmd = $rbd_cmd->($scfg, $storeid, @options);
 
@@ -300,7 +295,8 @@ sub rbd_volume_info {
 sub rbd_volume_du {
     my ($scfg, $storeid, $volname) = @_;
 
-    my @options = ('du', $volname, '--format', 'json');
+    my $spec = get_rbd_path($scfg, $volname);
+    my @options = ('du', $spec, '--format', 'json');
     my $cmd = $rbd_cmd->($scfg, $storeid, @options);
 
     my $raw = '';
@@ -471,14 +467,13 @@ sub path {
 
     my $cmd_option = PVE::CephConfig::ceph_connect_option($scfg, $storeid);
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
-    $name .= '@'.$snapname if $snapname;
 
     if ($scfg->{krbd}) {
-       my $rbd_dev_path = get_rbd_dev_path($scfg, $storeid, $name);
+       my $rbd_dev_path = get_rbd_dev_path($scfg, $storeid, $name, $snapname);
        return ($rbd_dev_path, $vmid, $vtype);
     }
 
-    my $rbd_path = get_rbd_path($scfg, $name);
+    my $rbd_path = get_rbd_path($scfg, $name, $snapname);
     my $path = "rbd:${rbd_path}";
 
     $path .= ":conf=$cmd_option->{ceph_conf}" if $cmd_option->{ceph_conf};
@@ -560,8 +555,9 @@ sub create_base {
     my (undef, undef, undef, $protected) = rbd_volume_info($scfg, $storeid, 
$newname, $snap);
 
     if (!$protected){
-       my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'protect', $newname, 
'--snap', $snap);
-       run_rbd_command($cmd, errmsg => "rbd protect $newname snap '$snap' 
error");
+       my $snap_spec = get_rbd_path($scfg, $newname, $snap);
+       my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'protect', $snap_spec);
+       run_rbd_command($cmd, errmsg => "rbd protect '$snap_spec' error");
     }
 
     return $newvolname;
@@ -588,8 +584,9 @@ sub clone_image {
        my (undef, undef, undef, $protected) = rbd_volume_info($scfg, $storeid, 
$volname, $snapname);
 
        if (!$protected) {
-           my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'protect', $volname, 
'--snap', $snapname);
-           run_rbd_command($cmd, errmsg => "rbd protect $volname snap 
$snapname error");
+           my $snap_spec = get_rbd_path($scfg, $volname, $snapname);
+           my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'protect', 
$snap_spec);
+           run_rbd_command($cmd, errmsg => "rbd protect '$snap_spec' error");
        }
     }
 
@@ -597,8 +594,7 @@ sub clone_image {
     $newvol = $name if length($snapname);
 
     my @options = (
-       get_rbd_path($scfg, $basename),
-       '--snap', $snap,
+       get_rbd_path($scfg, $basename, $snap),
     );
     push @options, ('--data-pool', $scfg->{'data-pool'}) if 
$scfg->{'data-pool'};
 
@@ -623,7 +619,7 @@ sub alloc_image {
     );
     push @options, ('--data-pool', $scfg->{'data-pool'}) if 
$scfg->{'data-pool'};
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'create', @options, $name);
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'create', @options, 
get_rbd_path($scfg, $name));
     run_rbd_command($cmd, errmsg => "rbd create '$name' error");
 
     return $name;
@@ -635,22 +631,23 @@ sub free_image {
     my ($vtype, $name, $vmid, undef, undef, undef) =
        $class->parse_volname($volname);
 
-
-    my $snaps = rbd_ls_snap($scfg, $storeid, $name);
+    my $image_spec = get_rbd_path($scfg, $name);
+    my $snaps = rbd_ls_snap($scfg, $storeid, $image_spec);
     foreach my $snap (keys %$snaps) {
        if ($snaps->{$snap}->{protected}) {
-           my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'unprotect', $name, 
'--snap', $snap);
-           run_rbd_command($cmd, errmsg => "rbd unprotect $name snap '$snap' 
error");
+           my $snap_spec = get_rbd_path($scfg, $name, $snap);
+           my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'unprotect', 
$snap_spec);
+           run_rbd_command($cmd, errmsg => "rbd unprotect $snap_spec error");
        }
     }
 
     $class->deactivate_volume($storeid, $scfg, $volname);
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'purge',  $name);
-    run_rbd_command($cmd, errmsg => "rbd snap purge '$name' error");
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'purge',  $image_spec);
+    run_rbd_command($cmd, errmsg => "rbd snap purge '$image_spec' error");
 
-    $cmd = $rbd_cmd->($scfg, $storeid, 'rm', $name);
-    run_rbd_command($cmd, errmsg => "rbd rm '$name' error");
+    $cmd = $rbd_cmd->($scfg, $storeid, 'rm', $image_spec);
+    run_rbd_command($cmd, errmsg => "rbd rm '$image_spec' error");
 
     return undef;
 }
@@ -725,20 +722,18 @@ sub deactivate_storage {
 sub map_volume {
     my ($class, $storeid, $scfg, $volname, $snapname) = @_;
 
-    my ($vtype, $img_name, $vmid) = $class->parse_volname($volname);
+    my ($vtype, $name, $vmid) = $class->parse_volname($volname);
 
-    my $name = $img_name;
-    $name .= '@'.$snapname if $snapname;
-
-    my $kerneldev = get_rbd_dev_path($scfg, $storeid, $name);
+    my $kerneldev = get_rbd_dev_path($scfg, $storeid, $name, $snapname);
 
     return $kerneldev if -b $kerneldev; # already mapped
 
     # features can only be enabled/disabled for image, not for snapshot!
-    $krbd_feature_update->($scfg, $storeid, $img_name);
+    $krbd_feature_update->($scfg, $storeid, $name);
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'map', $name);
-    run_rbd_command($cmd, errmsg => "can't map rbd volume $name");
+    my $spec = get_rbd_path($scfg, $name, $snapname);
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'map', $spec);
+    run_rbd_command($cmd, errmsg => "can't map rbd volume '$spec'");
 
     return $kerneldev;
 }
@@ -747,9 +742,8 @@ sub unmap_volume {
     my ($class, $storeid, $scfg, $volname, $snapname) = @_;
 
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
-    $name .= '@'.$snapname if $snapname;
 
-    my $kerneldev = get_rbd_dev_path($scfg, $storeid, $name);
+    my $kerneldev = get_rbd_dev_path($scfg, $storeid, $name, $snapname);
 
     if (-b $kerneldev) {
        my $cmd = $rbd_cmd->($scfg, $storeid, 'unmap', $kerneldev);
@@ -791,8 +785,10 @@ sub volume_resize {
 
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'resize', '--size', 
int(ceil($size/1024/1024)), $name);
-    run_rbd_command($cmd, errmsg => "rbd resize '$volname' error");
+    my $image_spec = get_rbd_path($scfg, $volname);
+    $size = int(ceil($size/1024/1024));
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'resize', '--size', $size, 
$image_spec);
+    run_rbd_command($cmd, errmsg => "rbd resize '$image_spec' error");
     return undef;
 }
 
@@ -801,8 +797,9 @@ sub volume_snapshot {
 
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'create', '--snap', $snap, 
$name);
-    run_rbd_command($cmd, errmsg => "rbd snapshot '$volname' error");
+    my $snap_spec = get_rbd_path($scfg, $name, $snap);
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'create', $snap_spec);
+    run_rbd_command($cmd, errmsg => "rbd snapshot '$snap_spec' error");
     return undef;
 }
 
@@ -811,8 +808,9 @@ sub volume_snapshot_rollback {
 
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'rollback', '--snap', $snap, 
$name);
-    run_rbd_command($cmd, errmsg => "rbd snapshot $volname to '$snap' error");
+    my $snap_spec = get_rbd_path($scfg, $name, $snap);
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'rollback', $snap_spec);
+    run_rbd_command($cmd, errmsg => "rbd snapshot rollback to '$snap_spec' 
error");
 }
 
 sub volume_snapshot_delete {
@@ -823,14 +821,16 @@ sub volume_snapshot_delete {
     my ($vtype, $name, $vmid) = $class->parse_volname($volname);
 
     my (undef, undef, undef, $protected) = rbd_volume_info($scfg, $storeid, 
$name, $snap);
+    my $snap_spec = get_rbd_path($scfg, $volname, $snap);
+
     if ($protected){
-       my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'unprotect', $name, 
'--snap', $snap);
-       run_rbd_command($cmd, errmsg => "rbd unprotect $name snap '$snap' 
error");
+       my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'unprotect', $snap_spec);
+       run_rbd_command($cmd, errmsg => "rbd unprotect '$snap_spec' error");
     }
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'rm', '--snap', $snap, 
$name);
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'snap', 'rm', $snap_spec);
 
-    run_rbd_command($cmd, errmsg => "rbd snapshot '$volname' error");
+    run_rbd_command($cmd, errmsg => "rbd snapshot delete '$snap_spec' error");
 
     return undef;
 }
@@ -890,7 +890,9 @@ sub volume_export {
 
     my ($size) = $class->volume_size_info($scfg, $storeid, $volname);
     PVE::Storage::Plugin::write_common_header($fh, $size);
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'export', '--export-format', '1', 
$volname, '-');
+
+    my $snap_spec = get_rbd_path($scfg, $volname, $snapshot);
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'export', '--export-format', '1', 
$snap_spec, '-');
     run_rbd_command(
        $cmd,
        errmsg => 'could not export image',
@@ -938,8 +940,9 @@ sub volume_import {
     my ($size) = PVE::Storage::Plugin::read_common_header($fh);
     $size = PVE::Storage::Common::align_size_up($size, 1024) / 1024;
 
+    my $image_spec = get_rbd_path($scfg, $volname);
     eval {
-       my $cmd = $rbd_cmd->($scfg, $storeid, 'import', '--export-format', '1', 
'-', $volname);
+       my $cmd = $rbd_cmd->($scfg, $storeid, 'import', '--export-format', '1', 
'-', $image_spec);
        run_rbd_command(
            $cmd,
            errmsg => 'could not import image',
@@ -976,11 +979,13 @@ sub rename_volume {
     die "target volume '${target_volname}' already exists\n"
        if rbd_volume_exists($scfg, $storeid, $target_volname);
 
-    my $cmd = $rbd_cmd->($scfg, $storeid, 'rename', $source_image, 
$target_volname);
+    my $source_spec = get_rbd_path($scfg, $source_volname);
+    my $target_spec = get_rbd_path($scfg, $target_volname);
+    my $cmd = $rbd_cmd->($scfg, $storeid, 'rename', $source_spec, 
$target_spec);
 
     run_rbd_command(
        $cmd,
-       errmsg => "could not rename image '${source_image}' to 
'${target_volname}'",
+       errmsg => "could not rename image '${source_spec}' to '${target_spec}'",
     );
 
     eval { $class->unmap_volume($storeid, $scfg, $source_volname); };
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to