add lock around update_vm code

This commit is contained in:
Dietmar Maurer 2012-01-27 09:53:48 +01:00
parent afdb31d5f8
commit 5d39a18227

View File

@ -455,124 +455,124 @@ __PACKAGE__->register_method({
&$resolve_cdrom_alias($param); &$resolve_cdrom_alias($param);
my $conf = PVE::QemuServer::load_config($vmid); my $updatefn = sub {
die "checksum missmatch (file change by other user?)\n" my $conf = PVE::QemuServer::load_config($vmid);
if $digest && $digest ne $conf->{digest};
PVE::QemuServer::check_lock($conf) if !$skiplock; die "checksum missmatch (file change by other user?)\n"
if $digest && $digest ne $conf->{digest};
PVE::Cluster::log_msg('info', $user, "update VM $vmid: " . join (' ', @paramarr)); PVE::QemuServer::check_lock($conf) if !$skiplock;
#delete PVE::Cluster::log_msg('info', $user, "update VM $vmid: " . join (' ', @paramarr));
foreach my $opt (PVE::Tools::split_list($delete)) {
$opt = 'ide2' if $opt eq 'cdrom'; #delete
die "you can't use '-$opt' and '-delete $opt' at the same time\n" foreach my $opt (PVE::Tools::split_list($delete)) {
if defined($param->{$opt});
my $unset = {}; $opt = 'ide2' if $opt eq 'cdrom';
die "you can't use '-$opt' and '-delete $opt' at the same time\n"
if defined($param->{$opt});
if (!PVE::QemuServer::option_exists($opt)) { if (!PVE::QemuServer::option_exists($opt)) {
raise_param_exc({ delete => "unknown option '$opt'" }); raise_param_exc({ delete => "unknown option '$opt'" });
} }
next if !defined($conf->{$opt}); next if !defined($conf->{$opt});
die "error hot-unplug $opt" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt); die "error hot-unplug $opt" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
#drive #drive
if (PVE::QemuServer::valid_drivename($opt)) { if (PVE::QemuServer::valid_drivename($opt)) {
my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt}); my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
#hdd #hdd
if (!PVE::QemuServer::drive_is_cdrom($drive)) { if (!PVE::QemuServer::drive_is_cdrom($drive)) {
my $volid = $drive->{file}; my $volid = $drive->{file};
if ($volid !~ m|^/|) { if ($volid !~ m|^/|) {
my ($path, $owner); my ($path, $owner);
eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); }; eval { ($path, $owner) = PVE::Storage::path($storecfg, $volid); };
if ($owner && ($owner == $vmid)) { if ($owner && ($owner == $vmid)) {
if ($force) { if ($force) {
eval { PVE::Storage::vdisk_free($storecfg, $volid); }; eval { PVE::Storage::vdisk_free($storecfg, $volid); };
# fixme: log ? # fixme: log ?
warn $@ if $@; warn $@ if $@;
} else { } else {
PVE::QemuServer::add_unused_volume($conf, $volid, $vmid); PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
}
} }
} }
} }
} } elsif ($opt =~ m/^unused/) {
} elsif ($opt =~ m/^unused/) {
my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt}); my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
my $volid = $drive->{file}; my $volid = $drive->{file};
eval { PVE::Storage::vdisk_free($storecfg, $volid); }; eval { PVE::Storage::vdisk_free($storecfg, $volid); };
# fixme: log ? # fixme: log ?
warn $@ if $@; warn $@ if $@;
}
PVE::QemuServer::change_config_nolock($vmid, {}, { $opt => 1 }, 1);
} }
$unset->{$opt} = 1; #add
PVE::QemuServer::change_config_nolock($vmid, {}, $unset, 1); foreach my $opt (keys %$param) {
}
#drives
if (PVE::QemuServer::valid_drivename($opt)) {
my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
raise_param_exc({ $opt => "unable to parse drive options" }) if !$drive;
PVE::QemuServer::cleanup_drive_path($opt, $storecfg, $drive);
$param->{$opt} = PVE::QemuServer::print_drive($vmid, $drive);
#add #cdrom
foreach my $opt (keys %$param) { if (PVE::QemuServer::drive_is_cdrom($drive) && PVE::QemuServer::check_running($vmid)) {
if ($drive->{file} eq 'none') {
#drives PVE::QemuServer::vm_monitor_command($vmid, "eject -f drive-$opt", 0);
if (PVE::QemuServer::valid_drivename($opt)) { #delete $param->{$opt};
my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt}); }
raise_param_exc({ $opt => "unable to parse drive options" }) if !$drive; else {
my $path = PVE::QemuServer::get_iso_path($storecfg, $vmid, $drive->{file});
PVE::QemuServer::cleanup_drive_path($opt, $storecfg, $drive); PVE::QemuServer::vm_monitor_command($vmid, "eject -f drive-$opt", 0); #force eject if locked
$param->{$opt} = PVE::QemuServer::print_drive($vmid, $drive); PVE::QemuServer::vm_monitor_command($vmid, "change drive-$opt \"$path\"", 0) if $path;
}
#cdrom
if (PVE::QemuServer::drive_is_cdrom($drive) && PVE::QemuServer::check_running($vmid)) {
if ($drive->{file} eq 'none') {
PVE::QemuServer::vm_monitor_command($vmid, "eject -f drive-$opt", 0);
#delete $param->{$opt};
} }
#hdd
else { else {
my $path = PVE::QemuServer::get_iso_path($storecfg, $vmid, $drive->{file}); #swap drive
PVE::QemuServer::vm_monitor_command($vmid, "eject -f drive-$opt", 0); #force eject if locked if ($conf->{$opt}){
PVE::QemuServer::vm_monitor_command($vmid, "change drive-$opt \"$path\"", 0) if $path; my $old_drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
} if ($drive->{file} ne $old_drive->{file} && !PVE::QemuServer::drive_is_cdrom($old_drive)) {
my ($path, $owner);
eval { ($path, $owner) = PVE::Storage::path($storecfg, $old_drive->{file}); };
if ($owner && ($owner == $vmid)) {
die "error hot-unplug $opt" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
PVE::QemuServer::add_unused_volume($conf, $old_drive->{file}, $vmid);
}
}
}
my $settings = { $opt => $param->{$opt} };
PVE::QemuServer::create_disks($storecfg, $vmid, $settings, $conf);
$param->{$opt} = $settings->{$opt};
#hotplug disks
if(!PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive)) {
PVE::QemuServer::add_unused_volume($conf,$drive->{file},$vmid);
PVE::QemuServer::change_config_nolock($vmid, {}, { $opt => 1 }, 1);
die "error hotplug $opt - put disk in unused";
}
}
}
#nics
if ($opt =~ m/^net(\d+)$/) {
my $net = PVE::QemuServer::parse_net($param->{$opt});
$param->{$opt} = PVE::QemuServer::print_net($net);
} }
#hdd
else {
#swap drive
if ($conf->{$opt}){
my $old_drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
if ($drive->{file} ne $old_drive->{file} && !PVE::QemuServer::drive_is_cdrom($old_drive)) {
my ($path, $owner); PVE::QemuServer::change_config_nolock($vmid, { $opt => $param->{$opt} }, {}, 1);
eval { ($path, $owner) = PVE::Storage::path($storecfg, $old_drive->{file}); }; }
if ($owner && ($owner == $vmid)) { };
die "error hot-unplug $opt" if !PVE::QemuServer::vm_deviceunplug($vmid, $conf, $opt);
PVE::QemuServer::add_unused_volume($conf, $old_drive->{file}, $vmid);
}
}
}
my $settings = { $opt => $param->{$opt} };
PVE::QemuServer::create_disks($storecfg, $vmid, $settings, $conf);
$param->{$opt} = $settings->{$opt};
#hotplug disks
if(!PVE::QemuServer::vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive)) {
PVE::QemuServer::add_unused_volume($conf,$drive->{file},$vmid);
PVE::QemuServer::change_config_nolock($vmid, {}, { $opt => 1 }, 1);
die "error hotplug $opt - put disk in unused";
}
}
}
#nics
if ($opt =~ m/^net(\d+)$/) {
my $net = PVE::QemuServer::parse_net($param->{$opt});
$param->{$opt} = PVE::QemuServer::print_net($net);
}
PVE::QemuServer::change_config_nolock($vmid, { $opt => $param->{$opt} }, {}, 1); PVE::QemuServer::lock_config($vmid, $updatefn);
}
return undef; return undef;
}}); }});