mirror of
https://git.proxmox.com/git/qemu-server
synced 2025-04-30 07:39:02 +00:00
activate LVM LVs more carefully
And remove syslog whenever possible (we run most commands as tasks, so the output is loged anyways)
This commit is contained in:
parent
48e1a963f4
commit
ff1a2432c8
2
Makefile
2
Makefile
@ -2,7 +2,7 @@ RELEASE=2.0
|
|||||||
|
|
||||||
VERSION=2.0
|
VERSION=2.0
|
||||||
PACKAGE=qemu-server
|
PACKAGE=qemu-server
|
||||||
PKGREL=6
|
PKGREL=7
|
||||||
|
|
||||||
DESTDIR=
|
DESTDIR=
|
||||||
PREFIX=/usr
|
PREFIX=/usr
|
||||||
|
@ -622,6 +622,10 @@ __PACKAGE__->register_method({
|
|||||||
my $storecfg = PVE::Storage::config();
|
my $storecfg = PVE::Storage::config();
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $realcmd = sub {
|
||||||
|
my $upid = shift;
|
||||||
|
|
||||||
|
syslog('info', "destroy VM $vmid: $upid\n");
|
||||||
|
|
||||||
PVE::QemuServer::vm_destroy($storecfg, $vmid, $skiplock);
|
PVE::QemuServer::vm_destroy($storecfg, $vmid, $skiplock);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -807,7 +811,7 @@ __PACKAGE__->register_method({
|
|||||||
# test if VM exists
|
# test if VM exists
|
||||||
my $conf = PVE::QemuServer::load_config($param->{vmid});
|
my $conf = PVE::QemuServer::load_config($param->{vmid});
|
||||||
|
|
||||||
my $vmstatus = PVE::QemuServer::vmstatus($param->{vmid});
|
my $vmstatus = PVE::QemuServer::vmstatus($param->{vmid});
|
||||||
|
|
||||||
return $vmstatus->{$param->{vmid}};
|
return $vmstatus->{$param->{vmid}};
|
||||||
}});
|
}});
|
||||||
@ -850,6 +854,8 @@ __PACKAGE__->register_method({
|
|||||||
raise_param_exc({ skiplock => "Only root may use this option." })
|
raise_param_exc({ skiplock => "Only root may use this option." })
|
||||||
if $skiplock && $user ne 'root@pam';
|
if $skiplock && $user ne 'root@pam';
|
||||||
|
|
||||||
|
die "VM $vmid already running\n" if PVE::QemuServer::check_running($vmid);
|
||||||
|
|
||||||
my $storecfg = PVE::Storage::config();
|
my $storecfg = PVE::Storage::config();
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $realcmd = sub {
|
||||||
@ -904,27 +910,16 @@ __PACKAGE__->register_method({
|
|||||||
raise_param_exc({ skiplock => "Only root may use this option." })
|
raise_param_exc({ skiplock => "Only root may use this option." })
|
||||||
if $skiplock && $user ne 'root@pam';
|
if $skiplock && $user ne 'root@pam';
|
||||||
|
|
||||||
|
die "VM $vmid not running\n" if !PVE::QemuServer::check_running($vmid);
|
||||||
|
|
||||||
|
my $storecfg = PVE::Storage::config();
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $realcmd = sub {
|
||||||
my $upid = shift;
|
my $upid = shift;
|
||||||
|
|
||||||
syslog('info', "stop VM $vmid: $upid\n");
|
syslog('info', "stop VM $vmid: $upid\n");
|
||||||
|
|
||||||
PVE::QemuServer::vm_stop($vmid, $skiplock);
|
PVE::QemuServer::vm_stop($storecfg, $vmid, $skiplock, 0, $param->{timeout});
|
||||||
|
|
||||||
my $pid = PVE::QemuServer::check_running ($vmid);
|
|
||||||
|
|
||||||
if ($pid && $param->{timeout}) {
|
|
||||||
print "waiting until VM $vmid stopps (PID $pid)\n";
|
|
||||||
|
|
||||||
my $count = 0;
|
|
||||||
while (($count < $param->{timeout}) &&
|
|
||||||
PVE::QemuServer::check_running($vmid)) {
|
|
||||||
$count++;
|
|
||||||
sleep 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
die "wait failed - got timeout\n" if PVE::QemuServer::check_running($vmid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -965,11 +960,11 @@ __PACKAGE__->register_method({
|
|||||||
raise_param_exc({ skiplock => "Only root may use this option." })
|
raise_param_exc({ skiplock => "Only root may use this option." })
|
||||||
if $skiplock && $user ne 'root@pam';
|
if $skiplock && $user ne 'root@pam';
|
||||||
|
|
||||||
|
die "VM $vmid not running\n" if !PVE::QemuServer::check_running($vmid);
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $realcmd = sub {
|
||||||
my $upid = shift;
|
my $upid = shift;
|
||||||
|
|
||||||
syslog('info', "reset VM $vmid: $upid\n");
|
|
||||||
|
|
||||||
PVE::QemuServer::vm_reset($vmid, $skiplock);
|
PVE::QemuServer::vm_reset($vmid, $skiplock);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1017,27 +1012,14 @@ __PACKAGE__->register_method({
|
|||||||
raise_param_exc({ skiplock => "Only root may use this option." })
|
raise_param_exc({ skiplock => "Only root may use this option." })
|
||||||
if $skiplock && $user ne 'root@pam';
|
if $skiplock && $user ne 'root@pam';
|
||||||
|
|
||||||
|
die "VM $vmid not running\n" if !PVE::QemuServer::check_running($vmid);
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $realcmd = sub {
|
||||||
my $upid = shift;
|
my $upid = shift;
|
||||||
|
|
||||||
syslog('info', "shutdown VM $vmid: $upid\n");
|
syslog('info', "shutdown VM $vmid: $upid\n");
|
||||||
|
|
||||||
PVE::QemuServer::vm_shutdown($vmid, $skiplock);
|
PVE::QemuServer::vm_shutdown($vmid, $skiplock, $param->{timeout});
|
||||||
|
|
||||||
my $pid = PVE::QemuServer::check_running ($vmid);
|
|
||||||
|
|
||||||
if ($pid && $param->{timeout}) {
|
|
||||||
print "waiting until VM $vmid stopps (PID $pid)\n";
|
|
||||||
|
|
||||||
my $count = 0;
|
|
||||||
while (($count < $param->{timeout}) &&
|
|
||||||
PVE::QemuServer::check_running($vmid)) {
|
|
||||||
$count++;
|
|
||||||
sleep 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
die "wait failed - got timeout\n" if PVE::QemuServer::check_running($vmid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@ -1078,6 +1060,8 @@ __PACKAGE__->register_method({
|
|||||||
raise_param_exc({ skiplock => "Only root may use this option." })
|
raise_param_exc({ skiplock => "Only root may use this option." })
|
||||||
if $skiplock && $user ne 'root@pam';
|
if $skiplock && $user ne 'root@pam';
|
||||||
|
|
||||||
|
die "VM $vmid not running\n" if !PVE::QemuServer::check_running($vmid);
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $realcmd = sub {
|
||||||
my $upid = shift;
|
my $upid = shift;
|
||||||
|
|
||||||
@ -1124,6 +1108,8 @@ __PACKAGE__->register_method({
|
|||||||
raise_param_exc({ skiplock => "Only root may use this option." })
|
raise_param_exc({ skiplock => "Only root may use this option." })
|
||||||
if $skiplock && $user ne 'root@pam';
|
if $skiplock && $user ne 'root@pam';
|
||||||
|
|
||||||
|
die "VM $vmid already running\n" if PVE::QemuServer::check_running($vmid);
|
||||||
|
|
||||||
my $realcmd = sub {
|
my $realcmd = sub {
|
||||||
my $upid = shift;
|
my $upid = shift;
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ use POSIX qw(strftime);
|
|||||||
use IO::File;
|
use IO::File;
|
||||||
use IPC::Open2;
|
use IPC::Open2;
|
||||||
use PVE::Tools qw(run_command);
|
use PVE::Tools qw(run_command);
|
||||||
use PVE::SafeSyslog;
|
|
||||||
use PVE::INotify;
|
use PVE::INotify;
|
||||||
use PVE::Cluster;
|
use PVE::Cluster;
|
||||||
use PVE::Storage;
|
use PVE::Storage;
|
||||||
@ -29,10 +28,12 @@ sub logmsg {
|
|||||||
|
|
||||||
my $tstr = strftime("%b %d %H:%M:%S", localtime);
|
my $tstr = strftime("%b %d %H:%M:%S", localtime);
|
||||||
|
|
||||||
syslog($level, $msg);
|
|
||||||
|
|
||||||
foreach my $line (split (/\n/, $msg)) {
|
foreach my $line (split (/\n/, $msg)) {
|
||||||
print STDOUT "$tstr $line\n";
|
if ($level eq 'err') {
|
||||||
|
print STDOUT "$tstr ERROR: $line\n";
|
||||||
|
} else {
|
||||||
|
print STDOUT "$tstr $line\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
\*STDOUT->flush();
|
\*STDOUT->flush();
|
||||||
}
|
}
|
||||||
@ -43,12 +44,10 @@ sub eval_int {
|
|||||||
eval {
|
eval {
|
||||||
local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
|
local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {
|
||||||
$delayed_interrupt = 0;
|
$delayed_interrupt = 0;
|
||||||
logmsg('err', "received interrupt");
|
|
||||||
die "interrupted by signal\n";
|
die "interrupted by signal\n";
|
||||||
};
|
};
|
||||||
local $SIG{PIPE} = sub {
|
local $SIG{PIPE} = sub {
|
||||||
$delayed_interrupt = 0;
|
$delayed_interrupt = 0;
|
||||||
logmsg('err', "received broken pipe interrupt");
|
|
||||||
die "interrupted by signal\n";
|
die "interrupted by signal\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,13 +210,10 @@ sub migrate {
|
|||||||
# lock config during migration
|
# lock config during migration
|
||||||
eval { PVE::QemuServer::lock_config($vmid, sub {
|
eval { PVE::QemuServer::lock_config($vmid, sub {
|
||||||
|
|
||||||
eval_int(sub { prepare($session); });
|
my $conf;
|
||||||
|
eval_int(sub { $conf = prepare($session); });
|
||||||
die $@ if $@;
|
die $@ if $@;
|
||||||
|
|
||||||
my $conf = PVE::QemuServer::load_config($vmid);
|
|
||||||
|
|
||||||
PVE::QemuServer::check_lock($conf);
|
|
||||||
|
|
||||||
my $running = 0;
|
my $running = 0;
|
||||||
if (my $pid = PVE::QemuServer::check_running($vmid)) {
|
if (my $pid = PVE::QemuServer::check_running($vmid)) {
|
||||||
die "cant migrate running VM without --online\n" if !$online;
|
die "cant migrate running VM without --online\n" if !$online;
|
||||||
@ -232,7 +228,9 @@ sub migrate {
|
|||||||
if ($rhash->{clearlock}) {
|
if ($rhash->{clearlock}) {
|
||||||
my $unset = { lock => 1 };
|
my $unset = { lock => 1 };
|
||||||
eval { PVE::QemuServer::change_config_nolock($session->{vmid}, {}, $unset, 1) };
|
eval { PVE::QemuServer::change_config_nolock($session->{vmid}, {}, $unset, 1) };
|
||||||
logmsg('err', $@) if $@;
|
if (my $tmperr = $@) {
|
||||||
|
logmsg('err', $tmperr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ($rhash->{volumes}) {
|
if ($rhash->{volumes}) {
|
||||||
foreach my $volid (@{$rhash->{volumes}}) {
|
foreach my $volid (@{$rhash->{volumes}}) {
|
||||||
@ -257,16 +255,16 @@ sub migrate {
|
|||||||
# always kill tunnel
|
# always kill tunnel
|
||||||
if ($rhash->{tunnel}) {
|
if ($rhash->{tunnel}) {
|
||||||
eval_int(sub { finish_tunnel($rhash->{tunnel}) });
|
eval_int(sub { finish_tunnel($rhash->{tunnel}) });
|
||||||
if ($@) {
|
if (my $tmperr = $@) {
|
||||||
logmsg('err', "stopping tunnel failed - $@");
|
logmsg('err', "stopping tunnel failed - $tmperr");
|
||||||
$errors = 1;
|
$errors = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# always stop local VM - no interrupts possible
|
# always stop local VM - no interrupts possible
|
||||||
eval { PVE::QemuServer::vm_stop($session->{vmid}, 1, 1); };
|
eval { PVE::QemuServer::vm_stop($session->{storecfg}, $session->{vmid}, 1, 1); };
|
||||||
if ($@) {
|
if (my $tmperr = $@) {
|
||||||
logmsg('err', "stopping vm failed - $@");
|
logmsg('err', "stopping vm failed - $tmperr");
|
||||||
$errors = 1;
|
$errors = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,8 +279,8 @@ sub migrate {
|
|||||||
my $cmd = [ @{$session->{rem_ssh}}, $qm_cmd, 'unlock', $session->{vmid} ];
|
my $cmd = [ @{$session->{rem_ssh}}, $qm_cmd, 'unlock', $session->{vmid} ];
|
||||||
run_command($cmd);
|
run_command($cmd);
|
||||||
});
|
});
|
||||||
if ($@) {
|
if (my $tmperr = $@) {
|
||||||
logmsg('err', "failed to clear migrate lock - $@");
|
logmsg('err', "failed to clear migrate lock - $tmperr");
|
||||||
$errors = 1;
|
$errors = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,6 +296,18 @@ sub migrate {
|
|||||||
last if $err =~ /^interrupted by signal$/;
|
last if $err =~ /^interrupted by signal$/;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# always deactivate volumes - avoid lvm LVs to be active on
|
||||||
|
# several nodes
|
||||||
|
eval {
|
||||||
|
my $vollist = PVE::QemuServer::get_vm_volumes($conf);
|
||||||
|
PVE::Storage::deactivate_volumes($session->{storecfg}, $vollist);
|
||||||
|
};
|
||||||
|
if (my $tmperr = $@) {
|
||||||
|
logmsg('err', $tmperr);
|
||||||
|
$errors = 1;
|
||||||
|
}
|
||||||
|
|
||||||
})};
|
})};
|
||||||
|
|
||||||
my $err = $@;
|
my $err = $@;
|
||||||
@ -311,15 +321,13 @@ sub migrate {
|
|||||||
my $duration = sprintf "%02d:%02d:%02d", $hours, $mins, $secs;
|
my $duration = sprintf "%02d:%02d:%02d", $hours, $mins, $secs;
|
||||||
|
|
||||||
if ($err) {
|
if ($err) {
|
||||||
my $msg = "migration aborted (duration $duration): $err\n";
|
logmsg('err', "migration aborted (duration $duration): $err");
|
||||||
logmsg('err', $msg);
|
die "migration aborted";
|
||||||
die $msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($errors) {
|
if ($errors) {
|
||||||
my $msg = "migration finished with problems (duration $duration)\n";
|
logmsg('err', "migration finished with problems (duration $duration)");
|
||||||
logmsg('err', $msg);
|
die "migration problems"
|
||||||
die $msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logmsg('info', "migration finished successfuly (duration $duration)");
|
logmsg('info', "migration finished successfuly (duration $duration)");
|
||||||
@ -328,13 +336,21 @@ sub migrate {
|
|||||||
sub prepare {
|
sub prepare {
|
||||||
my ($session) = @_;
|
my ($session) = @_;
|
||||||
|
|
||||||
my $conffile = PVE::QemuServer::config_file($session->{vmid});
|
# test is VM exist
|
||||||
die "VM $session->{vmid} does not exist on this node\n" if ! -f $conffile;
|
my $conf = PVE::QemuServer::load_config($session->{vmid});
|
||||||
|
|
||||||
|
PVE::QemuServer::check_lock($conf);
|
||||||
|
|
||||||
|
# activate volumes
|
||||||
|
my $vollist = PVE::QemuServer::get_vm_volumes($conf);
|
||||||
|
PVE::Storage::activate_volumes($session->{storecfg}, $vollist);
|
||||||
|
|
||||||
# test ssh connection
|
# test ssh connection
|
||||||
my $cmd = [ @{$session->{rem_ssh}}, '/bin/true' ];
|
my $cmd = [ @{$session->{rem_ssh}}, '/bin/true' ];
|
||||||
eval { run_command($cmd); };
|
eval { run_command($cmd); };
|
||||||
die "Can't connect to destination address using public key\n" if $@;
|
die "Can't connect to destination address using public key\n" if $@;
|
||||||
|
|
||||||
|
return $conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub sync_disks {
|
sub sync_disks {
|
||||||
@ -478,12 +494,12 @@ sub phase2 {
|
|||||||
|
|
||||||
my $start = time();
|
my $start = time();
|
||||||
|
|
||||||
PVE::QemuServer::vm_monitor_command($session->{vmid}, "migrate -d \"tcp:localhost:$lport\"", 0, 1);
|
PVE::QemuServer::vm_monitor_command($session->{vmid}, "migrate -d \"tcp:localhost:$lport\"", 1);
|
||||||
|
|
||||||
my $lstat = '';
|
my $lstat = '';
|
||||||
while (1) {
|
while (1) {
|
||||||
sleep (2);
|
sleep (2);
|
||||||
my $stat = PVE::QemuServer::vm_monitor_command($session->{vmid}, "info migrate", 1, 1);
|
my $stat = PVE::QemuServer::vm_monitor_command($session->{vmid}, "info migrate", 1);
|
||||||
if ($stat =~ m/^Migration status: (active|completed|failed|cancelled)$/im) {
|
if ($stat =~ m/^Migration status: (active|completed|failed|cancelled)$/im) {
|
||||||
my $ms = $1;
|
my $ms = $1;
|
||||||
|
|
||||||
|
@ -1294,24 +1294,6 @@ sub create_disks {
|
|||||||
return $vollist;
|
return $vollist;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub unlink_image {
|
|
||||||
my ($storecfg, $vmid, $volid) = @_;
|
|
||||||
|
|
||||||
die "reject to unlink absolute path '$volid'"
|
|
||||||
if $volid =~ m|^/|;
|
|
||||||
|
|
||||||
my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
|
|
||||||
|
|
||||||
die "reject to unlink '$volid' - not owned by this VM"
|
|
||||||
if !$owner || ($owner != $vmid);
|
|
||||||
|
|
||||||
syslog('info', "VM $vmid deleting volume '$volid'");
|
|
||||||
|
|
||||||
PVE::Storage::vdisk_free($storecfg, $volid);
|
|
||||||
|
|
||||||
touch_config($vmid);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub destroy_vm {
|
sub destroy_vm {
|
||||||
my ($storecfg, $vmid, $keep_empty_config) = @_;
|
my ($storecfg, $vmid, $keep_empty_config) = @_;
|
||||||
|
|
||||||
@ -1328,10 +1310,10 @@ sub destroy_vm {
|
|||||||
return if drive_is_cdrom($drive);
|
return if drive_is_cdrom($drive);
|
||||||
|
|
||||||
my $volid = $drive->{file};
|
my $volid = $drive->{file};
|
||||||
next if !$volid || $volid =~ m|^/|;
|
return if !$volid || $volid =~ m|^/|;
|
||||||
|
|
||||||
my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
|
my ($path, $owner) = PVE::Storage::path($storecfg, $volid);
|
||||||
next if !$path || !$owner || ($owner != $vmid);
|
return if !$path || !$owner || ($owner != $vmid);
|
||||||
|
|
||||||
PVE::Storage::vdisk_free($storecfg, $volid);
|
PVE::Storage::vdisk_free($storecfg, $volid);
|
||||||
});
|
});
|
||||||
@ -2099,11 +2081,10 @@ sub config_to_command {
|
|||||||
foreach_drive($conf, sub {
|
foreach_drive($conf, sub {
|
||||||
my ($ds, $drive) = @_;
|
my ($ds, $drive) = @_;
|
||||||
|
|
||||||
eval {
|
if (PVE::Storage::parse_volume_id($drive->{file}, 1)) {
|
||||||
PVE::Storage::parse_volume_id($drive->{file});
|
|
||||||
push @$vollist, $drive->{file};
|
push @$vollist, $drive->{file};
|
||||||
}; # ignore errors
|
}
|
||||||
|
|
||||||
$use_virtio = 1 if $ds =~ m/^virtio/;
|
$use_virtio = 1 if $ds =~ m/^virtio/;
|
||||||
if ($drive->{interface} eq 'scsi') {
|
if ($drive->{interface} eq 'scsi') {
|
||||||
my $maxdev = 7;
|
my $maxdev = 7;
|
||||||
@ -2222,7 +2203,7 @@ sub next_migrate_port {
|
|||||||
sub vm_devices_list {
|
sub vm_devices_list {
|
||||||
my ($vmid) = @_;
|
my ($vmid) = @_;
|
||||||
|
|
||||||
my $res = vm_monitor_command ($vmid, "info pci", 1);
|
my $res = vm_monitor_command ($vmid, "info pci");
|
||||||
|
|
||||||
my @lines = split ("\n", $res);
|
my @lines = split ("\n", $res);
|
||||||
my $devices;
|
my $devices;
|
||||||
@ -2253,14 +2234,14 @@ sub vm_deviceadd {
|
|||||||
if($deviceid =~ m/^(virtio)(\d+)$/) {
|
if($deviceid =~ m/^(virtio)(\d+)$/) {
|
||||||
|
|
||||||
my $drive = print_drive_full($storecfg, $vmid, $device);
|
my $drive = print_drive_full($storecfg, $vmid, $device);
|
||||||
my $ret = vm_monitor_command($vmid, "drive_add auto $drive", 1);
|
my $ret = vm_monitor_command($vmid, "drive_add auto $drive");
|
||||||
# If the command succeeds qemu prints: "OK"
|
# If the command succeeds qemu prints: "OK"
|
||||||
if ($ret !~ m/OK/s) {
|
if ($ret !~ m/OK/s) {
|
||||||
die "adding drive failed: $ret";
|
die "adding drive failed: $ret";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
|
my $devicefull = print_drivedevice_full($storecfg, $vmid, $device);
|
||||||
$ret = vm_monitor_command($vmid, "device_add $devicefull", 1);
|
$ret = vm_monitor_command($vmid, "device_add $devicefull");
|
||||||
$ret =~ s/^\s+//;
|
$ret =~ s/^\s+//;
|
||||||
# Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
|
# Otherwise, if the command succeeds, no output is sent. So any non-empty string shows an error
|
||||||
die 'error on hotplug device : $ret' if $ret ne "";
|
die 'error on hotplug device : $ret' if $ret ne "";
|
||||||
@ -2284,7 +2265,7 @@ sub vm_devicedel {
|
|||||||
|
|
||||||
if($deviceid =~ m/^(virtio)(\d+)$/){
|
if($deviceid =~ m/^(virtio)(\d+)$/){
|
||||||
|
|
||||||
my $ret = vm_monitor_command($vmid, "drive_del drive-$deviceid", 1);
|
my $ret = vm_monitor_command($vmid, "drive_del drive-$deviceid");
|
||||||
$ret =~ s/^\s+//;
|
$ret =~ s/^\s+//;
|
||||||
if ($ret =~ m/Device \'.*?\' not found/s) {
|
if ($ret =~ m/Device \'.*?\' not found/s) {
|
||||||
# NB: device not found errors mean the drive was auto-deleted and we ignore the error
|
# NB: device not found errors mean the drive was auto-deleted and we ignore the error
|
||||||
@ -2293,7 +2274,7 @@ sub vm_devicedel {
|
|||||||
die "deleting drive $deviceid failed : $ret";
|
die "deleting drive $deviceid failed : $ret";
|
||||||
}
|
}
|
||||||
|
|
||||||
$ret = vm_monitor_command($vmid, "device_del $deviceid", 1);
|
$ret = vm_monitor_command($vmid, "device_del $deviceid");
|
||||||
$ret =~ s/^\s+//;
|
$ret =~ s/^\s+//;
|
||||||
die 'detaching device $deviceid failed : $ret' if $ret ne "";
|
die 'detaching device $deviceid failed : $ret' if $ret ne "";
|
||||||
|
|
||||||
@ -2318,13 +2299,7 @@ sub vm_start {
|
|||||||
|
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
|
|
||||||
if (check_running($vmid)) {
|
die "VM $vmid already running\n" if check_running($vmid);
|
||||||
my $msg = "VM $vmid already running - start failed\n" ;
|
|
||||||
syslog('err', $msg);
|
|
||||||
die $msg;
|
|
||||||
} else {
|
|
||||||
syslog('info', "VM $vmid start");
|
|
||||||
}
|
|
||||||
|
|
||||||
my $migrate_uri;
|
my $migrate_uri;
|
||||||
my $migrate_port = 0;
|
my $migrate_port = 0;
|
||||||
@ -2359,14 +2334,8 @@ sub vm_start {
|
|||||||
PVE::Storage::activate_volumes($storecfg, $vollist);
|
PVE::Storage::activate_volumes($storecfg, $vollist);
|
||||||
|
|
||||||
eval { run_command($cmd, timeout => $migrate_uri ? undef : 30); };
|
eval { run_command($cmd, timeout => $migrate_uri ? undef : 30); };
|
||||||
|
|
||||||
my $err = $@;
|
my $err = $@;
|
||||||
|
die "start failed: $err" if $err;
|
||||||
if ($err) {
|
|
||||||
my $msg = "start failed: $err";
|
|
||||||
syslog('err', "VM $vmid $msg");
|
|
||||||
die $msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($statefile) {
|
if ($statefile) {
|
||||||
|
|
||||||
@ -2375,7 +2344,7 @@ sub vm_start {
|
|||||||
} else {
|
} else {
|
||||||
unlink $statefile;
|
unlink $statefile;
|
||||||
# fixme: send resume - is that necessary ?
|
# fixme: send resume - is that necessary ?
|
||||||
eval { vm_monitor_command($vmid, "cont", 1) };
|
eval { vm_monitor_command($vmid, "cont"); };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2385,13 +2354,13 @@ sub vm_start {
|
|||||||
$migrate_speed = $conf->{migrate_speed} || $migrate_speed;
|
$migrate_speed = $conf->{migrate_speed} || $migrate_speed;
|
||||||
eval {
|
eval {
|
||||||
my $cmd = "migrate_set_speed ${migrate_speed}m";
|
my $cmd = "migrate_set_speed ${migrate_speed}m";
|
||||||
vm_monitor_command($vmid, $cmd, 1);
|
vm_monitor_command($vmid, $cmd);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (my $migrate_downtime =
|
if (my $migrate_downtime =
|
||||||
$conf->{migrate_downtime} || $defaults->{migrate_downtime}) {
|
$conf->{migrate_downtime} || $defaults->{migrate_downtime}) {
|
||||||
my $cmd = "migrate_set_downtime ${migrate_downtime}";
|
my $cmd = "migrate_set_downtime ${migrate_downtime}";
|
||||||
eval { vm_monitor_command($vmid, $cmd, 1); };
|
eval { vm_monitor_command($vmid, $cmd); };
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_balloonset($vmid, $conf->{balloon}) if $conf->{balloon};
|
vm_balloonset($vmid, $conf->{balloon}) if $conf->{balloon};
|
||||||
@ -2431,14 +2400,12 @@ sub __read_avail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub vm_monitor_command {
|
sub vm_monitor_command {
|
||||||
my ($vmid, $cmdstr, $nolog, $nocheck) = @_;
|
my ($vmid, $cmdstr, $nocheck) = @_;
|
||||||
|
|
||||||
my $res;
|
my $res;
|
||||||
|
|
||||||
syslog("info", "VM $vmid monitor command '$cmdstr'") if !$nolog;
|
|
||||||
|
|
||||||
eval {
|
eval {
|
||||||
die "VM not running\n" if !check_running($vmid, $nocheck);
|
die "VM $vmid not running\n" if !check_running($vmid, $nocheck);
|
||||||
|
|
||||||
my $sname = monitor_socket($vmid);
|
my $sname = monitor_socket($vmid);
|
||||||
|
|
||||||
@ -2525,14 +2492,42 @@ sub vm_reset {
|
|||||||
|
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
|
|
||||||
syslog("info", "VM $vmid sending 'reset'");
|
vm_monitor_command($vmid, "system_reset");
|
||||||
|
|
||||||
vm_monitor_command($vmid, "system_reset", 1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub get_vm_volumes {
|
||||||
|
my ($conf) = @_;
|
||||||
|
|
||||||
|
my $vollist = [];
|
||||||
|
foreach_drive($conf, sub {
|
||||||
|
my ($ds, $drive) = @_;
|
||||||
|
|
||||||
|
my ($sid, $volname) = PVE::Storage::parse_volume_id($drive->{file}, 1);
|
||||||
|
return if !$sid;
|
||||||
|
|
||||||
|
my $volid = $drive->{file};
|
||||||
|
return if !$volid || $volid =~ m|^/|;
|
||||||
|
|
||||||
|
push @$vollist, $volid;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $vollist;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub vm_stop_cleanup {
|
||||||
|
my ($storecfg, $vmid, $conf) = @_;
|
||||||
|
|
||||||
|
fairsched_rmnod($vmid); # try to destroy group
|
||||||
|
|
||||||
|
my $vollist = get_vm_volumes($conf);
|
||||||
|
PVE::Storage::deactivate_volumes($storecfg, $vollist);
|
||||||
|
}
|
||||||
|
|
||||||
sub vm_shutdown {
|
sub vm_shutdown {
|
||||||
my ($vmid, $skiplock) = @_;
|
my ($storecfg, $vmid, $skiplock, $timeout) = @_;
|
||||||
|
|
||||||
|
$timeout = 60 if !$timeout;
|
||||||
|
|
||||||
lock_config($vmid, sub {
|
lock_config($vmid, sub {
|
||||||
|
|
||||||
@ -2540,41 +2535,48 @@ sub vm_shutdown {
|
|||||||
|
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
|
|
||||||
syslog("info", "VM $vmid sending 'shutdown'");
|
vm_monitor_command($vmid, "system_powerdown");
|
||||||
|
|
||||||
vm_monitor_command($vmid, "system_powerdown", 1);
|
my $pid = check_running($vmid);
|
||||||
|
|
||||||
|
if ($pid && $timeout) {
|
||||||
|
print "waiting until VM $vmid stopps (PID $pid)\n";
|
||||||
|
|
||||||
|
my $count = 0;
|
||||||
|
while (($count < $timeout) && check_running($vmid)) {
|
||||||
|
$count++;
|
||||||
|
sleep 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
die "shutdown failed - got timeout\n" if check_running($vmid);
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_stop_cleanup($storecfg, $vmid, $conf);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
# Note: use $nockeck to skip tests if VM configuration file exists.
|
# Note: use $nockeck to skip tests if VM configuration file exists.
|
||||||
# We need that when migration VMs to other nodes (files already moved)
|
# We need that when migration VMs to other nodes (files already moved)
|
||||||
sub vm_stop {
|
sub vm_stop {
|
||||||
my ($vmid, $skiplock, $nocheck) = @_;
|
my ($storecfg, $vmid, $skiplock, $nocheck, $timeout) = @_;
|
||||||
|
|
||||||
|
$timeout = 60 if !$timeout;
|
||||||
|
|
||||||
lock_config($vmid, sub {
|
lock_config($vmid, sub {
|
||||||
|
|
||||||
my $pid = check_running($vmid, $nocheck);
|
my $pid = check_running($vmid, $nocheck);
|
||||||
|
return if !$pid;
|
||||||
|
|
||||||
if (!$pid) {
|
my $conf;
|
||||||
syslog('info', "VM $vmid already stopped");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$nocheck) {
|
if (!$nocheck) {
|
||||||
my $conf = load_config($vmid);
|
$conf = load_config($vmid);
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
}
|
}
|
||||||
|
|
||||||
syslog("info", "VM $vmid stopping");
|
eval { vm_monitor_command($vmid, "quit", $nocheck); };
|
||||||
|
|
||||||
eval { vm_monitor_command($vmid, "quit", 1, $nocheck); };
|
|
||||||
|
|
||||||
my $err = $@;
|
my $err = $@;
|
||||||
|
|
||||||
if (!$err) {
|
if (!$err) {
|
||||||
# wait some time
|
|
||||||
my $timeout = 50; # fixme: how long?
|
|
||||||
|
|
||||||
my $count = 0;
|
my $count = 0;
|
||||||
while (($count < $timeout) && check_running($vmid, $nocheck)) {
|
while (($count < $timeout) && check_running($vmid, $nocheck)) {
|
||||||
$count++;
|
$count++;
|
||||||
@ -2582,16 +2584,16 @@ sub vm_stop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($count >= $timeout) {
|
if ($count >= $timeout) {
|
||||||
syslog('info', "VM $vmid still running - terminating now with SIGTERM");
|
warn "VM still running - terminating now with SIGTERM\n";
|
||||||
kill 15, $pid;
|
kill 15, $pid;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
syslog('info', "VM $vmid quit failed - terminating now with SIGTERM");
|
warn "VM quit failed - terminating now with SIGTERM\n";
|
||||||
kill 15, $pid;
|
kill 15, $pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
# wait again
|
# wait again
|
||||||
my $timeout = 10;
|
$timeout = 10;
|
||||||
|
|
||||||
my $count = 0;
|
my $count = 0;
|
||||||
while (($count < $timeout) && check_running($vmid, $nocheck)) {
|
while (($count < $timeout) && check_running($vmid, $nocheck)) {
|
||||||
@ -2600,12 +2602,13 @@ sub vm_stop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($count >= $timeout) {
|
if ($count >= $timeout) {
|
||||||
syslog('info', "VM $vmid still running - terminating now with SIGKILL\n");
|
warn "VM still running - terminating now with SIGKILL\n";
|
||||||
kill 9, $pid;
|
kill 9, $pid;
|
||||||
|
sleep 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fairsched_rmnod($vmid); # try to destroy group
|
vm_stop_cleanup($storecfg, $vmid, $conf) if $conf;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub vm_suspend {
|
sub vm_suspend {
|
||||||
@ -2617,9 +2620,7 @@ sub vm_suspend {
|
|||||||
|
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
|
|
||||||
syslog("info", "VM $vmid suspend");
|
vm_monitor_command($vmid, "stop");
|
||||||
|
|
||||||
vm_monitor_command($vmid, "stop", 1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2632,9 +2633,7 @@ sub vm_resume {
|
|||||||
|
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
|
|
||||||
syslog("info", "VM $vmid resume");
|
vm_monitor_command($vmid, "cont");
|
||||||
|
|
||||||
vm_monitor_command($vmid, "cont", 1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2647,9 +2646,7 @@ sub vm_sendkey {
|
|||||||
|
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
|
|
||||||
syslog("info", "VM $vmid sending key $key");
|
vm_monitor_command($vmid, "sendkey $key");
|
||||||
|
|
||||||
vm_monitor_command($vmid, "sendkey $key", 1);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2662,78 +2659,71 @@ sub vm_destroy {
|
|||||||
|
|
||||||
check_lock($conf) if !$skiplock;
|
check_lock($conf) if !$skiplock;
|
||||||
|
|
||||||
syslog("info", "VM $vmid destroy called (removing all data)");
|
if (!check_running($vmid)) {
|
||||||
|
fairsched_rmnod($vmid); # try to destroy group
|
||||||
eval {
|
destroy_vm($storecfg, $vmid);
|
||||||
if (!check_running($vmid)) {
|
} else {
|
||||||
fairsched_rmnod($vmid); # try to destroy group
|
die "VM $vmid is running - destroy failed\n";
|
||||||
destroy_vm($storecfg, $vmid);
|
|
||||||
} else {
|
|
||||||
die "VM is running\n";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
my $err = $@;
|
|
||||||
|
|
||||||
if ($err) {
|
|
||||||
syslog("err", "VM $vmid destroy failed - $err");
|
|
||||||
die $err;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
sub vm_stopall {
|
sub vm_stopall {
|
||||||
my ($timeout) = @_;
|
my ($storecfg, $timeout) = @_;
|
||||||
|
|
||||||
$timeout = 3*60 if !$timeout;
|
$timeout = 3*60 if !$timeout;
|
||||||
|
|
||||||
|
my $cleanuphash = {};
|
||||||
|
|
||||||
my $vzlist = vzlist();
|
my $vzlist = vzlist();
|
||||||
my $count = 0;
|
my $count = 0;
|
||||||
foreach my $vmid (keys %$vzlist) {
|
foreach my $vmid (keys %$vzlist) {
|
||||||
next if !$vzlist->{$vmid}->{pid};
|
next if !$vzlist->{$vmid}->{pid};
|
||||||
$count++;
|
$count++;
|
||||||
|
$cleanuphash->{$vmid} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return if !$count;
|
||||||
|
|
||||||
|
my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs\n";
|
||||||
|
syslog('info', $msg);
|
||||||
|
warn $msg;
|
||||||
|
|
||||||
|
foreach my $vmid (keys %$vzlist) {
|
||||||
|
next if !$vzlist->{$vmid}->{pid};
|
||||||
|
eval { vm_shutdown($storecfg, $vmid, 1); };
|
||||||
|
my $err = $@;
|
||||||
|
if ($err) {
|
||||||
|
warn $err;
|
||||||
|
} else {
|
||||||
|
delete $cleanuphash->{$vmid};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $wt = 5;
|
||||||
|
my $maxtries = int(($timeout + $wt -1)/$wt);
|
||||||
|
my $try = 0;
|
||||||
|
while (($try < $maxtries) && $count) {
|
||||||
|
$try++;
|
||||||
|
sleep $wt;
|
||||||
|
|
||||||
|
$vzlist = vzlist();
|
||||||
|
$count = 0;
|
||||||
|
foreach my $vmid (keys %$vzlist) {
|
||||||
|
next if !$vzlist->{$vmid}->{pid};
|
||||||
|
$count++;
|
||||||
|
}
|
||||||
|
last if !$count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($count) {
|
if ($count) {
|
||||||
|
|
||||||
my $msg = "Stopping Qemu Server - sending shutdown requests to all VMs\n";
|
|
||||||
syslog('info', $msg);
|
|
||||||
print STDERR $msg;
|
|
||||||
|
|
||||||
foreach my $vmid (keys %$vzlist) {
|
|
||||||
next if !$vzlist->{$vmid}->{pid};
|
|
||||||
eval { vm_shutdown($vmid, 1); };
|
|
||||||
print STDERR $@ if $@;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $wt = 5;
|
|
||||||
my $maxtries = int(($timeout + $wt -1)/$wt);
|
|
||||||
my $try = 0;
|
|
||||||
while (($try < $maxtries) && $count) {
|
|
||||||
$try++;
|
|
||||||
sleep $wt;
|
|
||||||
|
|
||||||
$vzlist = vzlist();
|
|
||||||
$count = 0;
|
|
||||||
foreach my $vmid (keys %$vzlist) {
|
|
||||||
next if !$vzlist->{$vmid}->{pid};
|
|
||||||
$count++;
|
|
||||||
}
|
|
||||||
last if !$count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return if !$count;
|
|
||||||
|
|
||||||
foreach my $vmid (keys %$vzlist) {
|
foreach my $vmid (keys %$vzlist) {
|
||||||
next if !$vzlist->{$vmid}->{pid};
|
next if !$vzlist->{$vmid}->{pid};
|
||||||
|
|
||||||
$msg = "VM $vmid still running - sending stop now\n";
|
warn "VM $vmid still running - sending stop now\n";
|
||||||
syslog('info', $msg);
|
eval { vm_monitor_command($vmid, "quit"); };
|
||||||
print $msg;
|
warn $@ if $@;
|
||||||
|
|
||||||
eval { vm_monitor_command($vmid, "quit", 1); };
|
|
||||||
print STDERR $@ if $@;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$timeout = 30;
|
$timeout = 30;
|
||||||
@ -2742,7 +2732,7 @@ sub vm_stopall {
|
|||||||
while (($try < $maxtries) && $count) {
|
while (($try < $maxtries) && $count) {
|
||||||
$try++;
|
$try++;
|
||||||
sleep $wt;
|
sleep $wt;
|
||||||
|
|
||||||
$vzlist = vzlist();
|
$vzlist = vzlist();
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach my $vmid (keys %$vzlist) {
|
foreach my $vmid (keys %$vzlist) {
|
||||||
@ -2752,24 +2742,34 @@ sub vm_stopall {
|
|||||||
last if !$count;
|
last if !$count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return if !$count;
|
if ($count) {
|
||||||
|
|
||||||
foreach my $vmid (keys %$vzlist) {
|
foreach my $vmid (keys %$vzlist) {
|
||||||
next if !$vzlist->{$vmid}->{pid};
|
next if !$vzlist->{$vmid}->{pid};
|
||||||
|
|
||||||
$msg = "VM $vmid still running - terminating now with SIGTERM\n";
|
warn "VM $vmid still running - terminating now with SIGTERM\n";
|
||||||
syslog('info', $msg);
|
kill 15, $vzlist->{$vmid}->{pid};
|
||||||
print $msg;
|
}
|
||||||
kill 15, $vzlist->{$vmid}->{pid};
|
sleep 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
# this is called by system shotdown scripts, so remaining
|
# this is called by system shotdown scripts, so remaining
|
||||||
# processes gets killed anyways (no need to send kill -9 here)
|
# processes gets killed anyways (no need to send kill -9 here)
|
||||||
|
|
||||||
$msg = "Qemu Server stopped\n";
|
|
||||||
syslog('info', $msg);
|
|
||||||
print STDERR $msg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$vzlist = vzlist();
|
||||||
|
foreach my $vmid (keys %$cleanuphash) {
|
||||||
|
next if $vzlist->{$vmid}->{pid};
|
||||||
|
eval {
|
||||||
|
my $conf = load_config($vmid);
|
||||||
|
vm_stop_cleanup($storecfg, $vmid, $conf);
|
||||||
|
};
|
||||||
|
warn $@ if $@;
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = "Qemu Server stopped\n";
|
||||||
|
syslog('info', $msg);
|
||||||
|
print $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
# pci helpers
|
# pci helpers
|
||||||
@ -2892,7 +2892,7 @@ sub print_pci_addr {
|
|||||||
sub vm_balloonset {
|
sub vm_balloonset {
|
||||||
my ($vmid, $value) = @_;
|
my ($vmid, $value) = @_;
|
||||||
|
|
||||||
vm_monitor_command($vmid, "balloon $value", 1);
|
vm_monitor_command($vmid, "balloon $value");
|
||||||
}
|
}
|
||||||
|
|
||||||
# vzdump restore implementaion
|
# vzdump restore implementaion
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
qemu-server (2.0-7) unstable; urgency=low
|
||||||
|
|
||||||
|
* activate/deactivate LVs more carefully
|
||||||
|
|
||||||
|
* avoid syslog whenever possible
|
||||||
|
|
||||||
|
* code cleanups
|
||||||
|
|
||||||
|
-- Proxmox Support Team <support@proxmox.com> Fri, 25 Nov 2011 08:08:04 +0100
|
||||||
|
|
||||||
qemu-server (2.0-6) unstable; urgency=low
|
qemu-server (2.0-6) unstable; urgency=low
|
||||||
|
|
||||||
* set correct migrate speed
|
* set correct migrate speed
|
||||||
|
Loading…
Reference in New Issue
Block a user