move_vm: make it work with PVE::QemuServer:::clone_disk

- use POST instead of PUT (this is not idempotent).
- return task ID
- use declarative permission check
This commit is contained in:
Dietmar Maurer 2013-05-29 12:07:56 +02:00
parent 586bfa78d1
commit e2cd75fa65
2 changed files with 30 additions and 33 deletions

View File

@ -2075,28 +2075,30 @@ __PACKAGE__->register_method({
__PACKAGE__->register_method({ __PACKAGE__->register_method({
name => 'move_vm', name => 'move_vm',
path => '{vmid}/move', path => '{vmid}/move',
method => 'PUT', method => 'POST',
protected => 1, protected => 1,
proxyto => 'node', proxyto => 'node',
description => "Move volume to different storage.", description => "Move volume to different storage.",
permissions => { permissions => {
check => ['perm', '/vms/{vmid}', [ 'VM.Config.Disk' ]], description => "You need 'VM.Config.Disk' permissions on /vms/{vmid}, " .
"and 'Datastore.AllocateSpace' permissions on the storage.",
check =>
[ 'and',
['perm', '/vms/{vmid}', [ 'VM.Config.Disk' ]],
['perm', '/storage/{storage}', [ 'Datastore.AllocateSpace' ]],
],
}, },
parameters => { parameters => {
additionalProperties => 0, additionalProperties => 0,
properties => { properties => {
node => get_standard_option('pve-node'), node => get_standard_option('pve-node'),
vmid => get_standard_option('pve-vmid'), vmid => get_standard_option('pve-vmid'),
skiplock => get_standard_option('skiplock'),
disk => { disk => {
type => 'string', type => 'string',
description => "The disk you want to move.", description => "The disk you want to move.",
enum => [ PVE::QemuServer::disknames() ], enum => [ PVE::QemuServer::disknames() ],
}, },
storage => { storage => get_standard_option('pve-storage-id', { description => "Target Storage." }),
type => 'string',
description => "Target Storage.",
},
format => { format => {
type => 'string', type => 'string',
description => "Target Format.", description => "Target Format.",
@ -2111,7 +2113,10 @@ __PACKAGE__->register_method({
}, },
}, },
}, },
returns => { type => 'null'}, returns => {
type => 'string',
description => "the task ID.",
},
code => sub { code => sub {
my ($param) = @_; my ($param) = @_;
@ -2131,10 +2136,6 @@ __PACKAGE__->register_method({
my $format = extract_param($param, 'format'); my $format = extract_param($param, 'format');
my $skiplock = extract_param($param, 'skiplock');
raise_param_exc({ skiplock => "Only root may use this option." })
if $skiplock && $authuser ne 'root@pam';
my $storecfg = PVE::Storage::config(); my $storecfg = PVE::Storage::config();
my $updatefn = sub { my $updatefn = sub {
@ -2143,39 +2144,30 @@ __PACKAGE__->register_method({
die "checksum missmatch (file change by other user?)\n" die "checksum missmatch (file change by other user?)\n"
if $digest && $digest ne $conf->{digest}; if $digest && $digest ne $conf->{digest};
PVE::QemuServer::check_lock($conf) if !$skiplock;
die "disk '$disk' does not exist\n" if !$conf->{$disk}; die "disk '$disk' does not exist\n" if !$conf->{$disk};
my $drive = PVE::QemuServer::parse_drive($disk, $conf->{$disk}); my $drive = PVE::QemuServer::parse_drive($disk, $conf->{$disk});
my $volid = $drive->{file}; my $volid = $drive->{file} || die "disk '$disk' has no associated volume\n";
die "disk '$disk' has no associated volume\n" if !$volid;
die "you can't move a cdrom\n" if PVE::QemuServer::drive_is_cdrom($drive); die "you can't move a cdrom\n" if PVE::QemuServer::drive_is_cdrom($drive);
my $oldfmt = undef; my $oldfmt;
my ($oldstoreid, $oldvolname) = PVE::Storage::parse_volume_id($volid); my ($oldstoreid, $oldvolname) = PVE::Storage::parse_volume_id($volid);
if ($oldvolname =~ m/\.(raw|qcow2|vmdk)$/){ if ($oldvolname =~ m/\.(raw|qcow2|vmdk)$/){
$oldfmt = $1; $oldfmt = $1;
} }
die "you can't move on the same storage with same format" if ($oldstoreid eq $storeid && (!$format || $oldfmt eq $format)); die "you can't move on the same storage with same format\n" if $oldstoreid eq $storeid &&
(!$format || !$oldfmt || $oldfmt eq $format);
$rpcenv->check($authuser, "/storage/$storeid", ['Datastore.AllocateSpace']);
$drive->{full} = 1;
my $drives = {};
my $vollist = [];
$drives->{$disk} = $drive;
push @$vollist, $drive->{file};
PVE::Cluster::log_msg('info', $authuser, "move disk VM $vmid: move --disk $disk --storage $storeid"); PVE::Cluster::log_msg('info', $authuser, "move disk VM $vmid: move --disk $disk --storage $storeid");
my $running = PVE::QemuServer::check_running($vmid); my $running = PVE::QemuServer::check_running($vmid);
PVE::Storage::activate_volumes($storecfg, [ $drive->{file} ]);
my $realcmd = sub { my $realcmd = sub {
my $newvollist = []; my $newvollist = [];
@ -2183,7 +2175,12 @@ __PACKAGE__->register_method({
eval { eval {
local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub { die "interrupted by signal\n"; }; local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub { die "interrupted by signal\n"; };
&$clone_disks($storecfg, $storeid, $vollist, $newvollist, $drives, undef, $format, $vmid, $vmid, $conf, $running); my $newdrive = PVE::QemuServer::clone_disk($storecfg, $vmid, $running, $disk, $drive, undef,
$vmid, $storeid, $format, 1, $newvollist);
$conf->{$disk} = PVE::QemuServer::print_drive($vmid, $newdrive);
PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
}; };
if (my $err = $@) { if (my $err = $@) {
@ -2197,8 +2194,8 @@ __PACKAGE__->register_method({
return $rpcenv->fork_worker('qmmove', $vmid, $authuser, $realcmd); return $rpcenv->fork_worker('qmmove', $vmid, $authuser, $realcmd);
}; };
PVE::QemuServer::lock_config($vmid, $updatefn);
return undef; return PVE::QemuServer::lock_config($vmid, $updatefn);
}}); }});
__PACKAGE__->register_method({ __PACKAGE__->register_method({

2
qm
View File

@ -359,7 +359,7 @@ my $cmddef = {
resize => [ "PVE::API2::Qemu", 'resize_vm', ['vmid', 'disk', 'size'], { node => $nodename } ], resize => [ "PVE::API2::Qemu", 'resize_vm', ['vmid', 'disk', 'size'], { node => $nodename } ],
move => [ "PVE::API2::Qemu", 'move_vm', ['vmid', 'disk', 'storage'], { node => $nodename } ], move => [ "PVE::API2::Qemu", 'move_vm', ['vmid', 'disk', 'storage'], { node => $nodename }, $upid_exit ],
unlink => [ "PVE::API2::Qemu", 'unlink', ['vmid', 'idlist'], { node => $nodename } ], unlink => [ "PVE::API2::Qemu", 'unlink', ['vmid', 'idlist'], { node => $nodename } ],