mirror of
https://git.proxmox.com/git/qemu-server
synced 2025-08-14 12:30:17 +00:00
api: move disk: fork before locking
using the familiar early+repeated checks pattern from other API calls. Only intended functional changes are with regard to locking/forking. Signed-off-by: Fabian Ebner <f.ebner@proxmox.com>
This commit is contained in:
parent
dbecb46f2a
commit
bdf6ba1e7d
160
PVE/API2/Qemu.pm
160
PVE/API2/Qemu.pm
@ -3396,7 +3396,7 @@ __PACKAGE__->register_method({
|
|||||||
|
|
||||||
my $storecfg = PVE::Storage::config();
|
my $storecfg = PVE::Storage::config();
|
||||||
|
|
||||||
my $move_updatefn = sub {
|
my $load_and_check_move = sub {
|
||||||
my $conf = PVE::QemuConfig->load_config($vmid);
|
my $conf = PVE::QemuConfig->load_config($vmid);
|
||||||
PVE::QemuConfig->check_lock($conf);
|
PVE::QemuConfig->check_lock($conf);
|
||||||
|
|
||||||
@ -3416,8 +3416,8 @@ __PACKAGE__->register_method({
|
|||||||
$oldfmt = $1;
|
$oldfmt = $1;
|
||||||
}
|
}
|
||||||
|
|
||||||
die "you can't move to the same storage with same format\n" if $oldstoreid eq $storeid &&
|
die "you can't move to the same storage with same format\n"
|
||||||
(!$format || !$oldfmt || $oldfmt eq $format);
|
if $oldstoreid eq $storeid && (!$format || !$oldfmt || $oldfmt eq $format);
|
||||||
|
|
||||||
# this only checks snapshots because $disk is passed!
|
# this only checks snapshots because $disk is passed!
|
||||||
my $snapshotted = PVE::QemuServer::Drive::is_volume_in_use(
|
my $snapshotted = PVE::QemuServer::Drive::is_volume_in_use(
|
||||||
@ -3429,6 +3429,13 @@ __PACKAGE__->register_method({
|
|||||||
die "you can't move a disk with snapshots and delete the source\n"
|
die "you can't move a disk with snapshots and delete the source\n"
|
||||||
if $snapshotted && $param->{delete};
|
if $snapshotted && $param->{delete};
|
||||||
|
|
||||||
|
return ($conf, $drive, $oldstoreid, $snapshotted);
|
||||||
|
};
|
||||||
|
|
||||||
|
my $move_updatefn = sub {
|
||||||
|
my ($conf, $drive, $oldstoreid, $snapshotted) = $load_and_check_move->();
|
||||||
|
my $old_volid = $drive->{file};
|
||||||
|
|
||||||
PVE::Cluster::log_msg(
|
PVE::Cluster::log_msg(
|
||||||
'info',
|
'info',
|
||||||
$authuser,
|
$authuser,
|
||||||
@ -3439,83 +3446,79 @@ __PACKAGE__->register_method({
|
|||||||
|
|
||||||
PVE::Storage::activate_volumes($storecfg, [ $drive->{file} ]);
|
PVE::Storage::activate_volumes($storecfg, [ $drive->{file} ]);
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $newvollist = [];
|
||||||
my $newvollist = [];
|
|
||||||
|
eval {
|
||||||
|
local $SIG{INT} =
|
||||||
|
local $SIG{TERM} =
|
||||||
|
local $SIG{QUIT} =
|
||||||
|
local $SIG{HUP} = sub { die "interrupted by signal\n"; };
|
||||||
|
|
||||||
|
warn "moving disk with snapshots, snapshots will not be moved!\n"
|
||||||
|
if $snapshotted;
|
||||||
|
|
||||||
|
my $bwlimit = extract_param($param, 'bwlimit');
|
||||||
|
my $movelimit = PVE::Storage::get_bandwidth_limit(
|
||||||
|
'move',
|
||||||
|
[$oldstoreid, $storeid],
|
||||||
|
$bwlimit
|
||||||
|
);
|
||||||
|
|
||||||
|
my $newdrive = PVE::QemuServer::clone_disk(
|
||||||
|
$storecfg,
|
||||||
|
$vmid,
|
||||||
|
$running,
|
||||||
|
$disk,
|
||||||
|
$drive,
|
||||||
|
undef,
|
||||||
|
$vmid,
|
||||||
|
$storeid,
|
||||||
|
$format,
|
||||||
|
1,
|
||||||
|
$newvollist,
|
||||||
|
undef,
|
||||||
|
undef,
|
||||||
|
undef,
|
||||||
|
$movelimit,
|
||||||
|
$conf,
|
||||||
|
);
|
||||||
|
$conf->{$disk} = PVE::QemuServer::print_drive($newdrive);
|
||||||
|
|
||||||
|
PVE::QemuConfig->add_unused_volume($conf, $old_volid) if !$param->{delete};
|
||||||
|
|
||||||
|
# convert moved disk to base if part of template
|
||||||
|
PVE::QemuServer::template_create($vmid, $conf, $disk)
|
||||||
|
if PVE::QemuConfig->is_template($conf);
|
||||||
|
|
||||||
|
PVE::QemuConfig->write_config($vmid, $conf);
|
||||||
|
|
||||||
|
my $do_trim = PVE::QemuServer::get_qga_key($conf, 'fstrim_cloned_disks');
|
||||||
|
if ($running && $do_trim && PVE::QemuServer::qga_check_running($vmid)) {
|
||||||
|
eval { mon_cmd($vmid, "guest-fstrim") };
|
||||||
|
}
|
||||||
|
|
||||||
eval {
|
eval {
|
||||||
local $SIG{INT} =
|
# try to deactivate volumes - avoid lvm LVs to be active on several nodes
|
||||||
local $SIG{TERM} =
|
PVE::Storage::deactivate_volumes($storecfg, [ $newdrive->{file} ])
|
||||||
local $SIG{QUIT} =
|
if !$running;
|
||||||
local $SIG{HUP} = sub { die "interrupted by signal\n"; };
|
|
||||||
|
|
||||||
warn "moving disk with snapshots, snapshots will not be moved!\n"
|
|
||||||
if $snapshotted;
|
|
||||||
|
|
||||||
my $bwlimit = extract_param($param, 'bwlimit');
|
|
||||||
my $movelimit = PVE::Storage::get_bandwidth_limit(
|
|
||||||
'move',
|
|
||||||
[$oldstoreid, $storeid],
|
|
||||||
$bwlimit
|
|
||||||
);
|
|
||||||
|
|
||||||
my $newdrive = PVE::QemuServer::clone_disk(
|
|
||||||
$storecfg,
|
|
||||||
$vmid,
|
|
||||||
$running,
|
|
||||||
$disk,
|
|
||||||
$drive,
|
|
||||||
undef,
|
|
||||||
$vmid,
|
|
||||||
$storeid,
|
|
||||||
$format,
|
|
||||||
1,
|
|
||||||
$newvollist,
|
|
||||||
undef,
|
|
||||||
undef,
|
|
||||||
undef,
|
|
||||||
$movelimit,
|
|
||||||
$conf,
|
|
||||||
);
|
|
||||||
$conf->{$disk} = PVE::QemuServer::print_drive($newdrive);
|
|
||||||
|
|
||||||
PVE::QemuConfig->add_unused_volume($conf, $old_volid) if !$param->{delete};
|
|
||||||
|
|
||||||
# convert moved disk to base if part of template
|
|
||||||
PVE::QemuServer::template_create($vmid, $conf, $disk)
|
|
||||||
if PVE::QemuConfig->is_template($conf);
|
|
||||||
|
|
||||||
PVE::QemuConfig->write_config($vmid, $conf);
|
|
||||||
|
|
||||||
my $do_trim = PVE::QemuServer::get_qga_key($conf, 'fstrim_cloned_disks');
|
|
||||||
if ($running && $do_trim && PVE::QemuServer::qga_check_running($vmid)) {
|
|
||||||
eval { mon_cmd($vmid, "guest-fstrim") };
|
|
||||||
}
|
|
||||||
|
|
||||||
eval {
|
|
||||||
# try to deactivate volumes - avoid lvm LVs to be active on several nodes
|
|
||||||
PVE::Storage::deactivate_volumes($storecfg, [ $newdrive->{file} ])
|
|
||||||
if !$running;
|
|
||||||
};
|
|
||||||
warn $@ if $@;
|
|
||||||
};
|
};
|
||||||
if (my $err = $@) {
|
warn $@ if $@;
|
||||||
foreach my $volid (@$newvollist) {
|
};
|
||||||
eval { PVE::Storage::vdisk_free($storecfg, $volid) };
|
if (my $err = $@) {
|
||||||
warn $@ if $@;
|
foreach my $volid (@$newvollist) {
|
||||||
}
|
eval { PVE::Storage::vdisk_free($storecfg, $volid) };
|
||||||
die "storage migration failed: $err";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($param->{delete}) {
|
|
||||||
eval {
|
|
||||||
PVE::Storage::deactivate_volumes($storecfg, [$old_volid]);
|
|
||||||
PVE::Storage::vdisk_free($storecfg, $old_volid);
|
|
||||||
};
|
|
||||||
warn $@ if $@;
|
warn $@ if $@;
|
||||||
}
|
}
|
||||||
};
|
die "storage migration failed: $err";
|
||||||
|
}
|
||||||
|
|
||||||
return $rpcenv->fork_worker('qmmove', $vmid, $authuser, $realcmd);
|
if ($param->{delete}) {
|
||||||
|
eval {
|
||||||
|
PVE::Storage::deactivate_volumes($storecfg, [$old_volid]);
|
||||||
|
PVE::Storage::vdisk_free($storecfg, $old_volid);
|
||||||
|
};
|
||||||
|
warn $@ if $@;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
my $load_and_check_reassign_configs = sub {
|
my $load_and_check_reassign_configs = sub {
|
||||||
@ -3695,7 +3698,14 @@ __PACKAGE__->register_method({
|
|||||||
|
|
||||||
die "cannot move disk '$disk', only configured disks can be moved to another storage\n"
|
die "cannot move disk '$disk', only configured disks can be moved to another storage\n"
|
||||||
if $disk =~ m/^unused\d+$/;
|
if $disk =~ m/^unused\d+$/;
|
||||||
return PVE::QemuConfig->lock_config($vmid, $move_updatefn);
|
|
||||||
|
$load_and_check_move->(); # early checks before forking/locking
|
||||||
|
|
||||||
|
my $realcmd = sub {
|
||||||
|
PVE::QemuConfig->lock_config($vmid, $move_updatefn);
|
||||||
|
};
|
||||||
|
|
||||||
|
return $rpcenv->fork_worker('qmmove', $vmid, $authuser, $realcmd);
|
||||||
} else {
|
} else {
|
||||||
my $msg = "both 'storage' and 'target-vmid' missing, either needs to be set";
|
my $msg = "both 'storage' and 'target-vmid' missing, either needs to be set";
|
||||||
raise_param_exc({ 'target-vmid' => $msg, 'storage' => $msg });
|
raise_param_exc({ 'target-vmid' => $msg, 'storage' => $msg });
|
||||||
|
Loading…
Reference in New Issue
Block a user