my $cpuinfo = PVE::ProcFSTools::read_cpuinfo();
-# Note about locking: we use flock on the config file protect
+# Note about locking: we use flock on the config file protect
# against concurent actions.
# Aditionaly, we have a 'lock' setting in the config file. This
# can be set to 'migrate' or 'backup'. Most actions are not
# allowed when such lock is set. But you can ignore this kind of
# lock with the --skiplock flag.
-cfs_register_file('/qemu-server/', \&parse_vm_config);
+cfs_register_file('/qemu-server/', \&parse_vm_config);
#no warnings 'redefine';
description => "Enable/disable time drift fix.",
default => 1,
},
- localtime => {
+ localtime => {
optional => 1,
type => 'boolean',
description => "Set the real time clock to local time. This is enabled by default if ostype indicates a Microsoft OS.",
},
startdate => {
optional => 1,
- type => 'string',
+ type => 'string',
typetext => "(now | YYYY-MM-DD | YYYY-MM-DDTHH:MM:SS)",
description => "Set the initial date of the real time clock. Valid format for date are: 'now' or '2006-06-17T16:01:21' or '2006-06-17'.",
pattern => '(now|\d{4}-\d{1,2}-\d{1,2}(T\d{1,2}:\d{1,2}:\d{1,2})?)',
type => 'string', format => 'pve-qm-net',
typetext => "MODEL=XX:XX:XX:XX:XX:XX [,bridge=<dev>][,rate=<mbps>]",
description => <<EODESCR,
-Specify network devices.
+Specify network devices.
MODEL is one of: $nic_model_list_txt
-XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
+XX:XX:XX:XX:XX:XX should be an unique MAC address. This is
automatically generated if not specified.
The bridge parameter can be used to automatically add the interface to a bridge device. The Proxmox VE standard bridge is called 'vmbr0'.
}
my $drivename_hash;
-
+
my $idedesc = {
optional => 1,
type => 'string', format => 'pve-qm-drive',
Configure an USB device (n is 0 to 4). This can be used to
pass-through usb devices to the guest. HOSTUSBDEVICE syntax is:
-'bus-port(.port)*' (decimal numbers) or
+'bus-port(.port)*' (decimal numbers) or
'vendor_id:product_id' (hexadeciaml numbers)
-You can use the 'lsusb -t' command to list existing usb devices.
+You can use the 'lsusb -t' command to list existing usb devices.
Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
type => 'string',
pattern => '/dev/ttyS\d+',
description => <<EODESCR,
-Map host serial devices (n is 0 to 3).
+Map host serial devices (n is 0 to 3).
Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
type => 'string',
pattern => '/dev/parport\d+',
description => <<EODESCR,
-Map host parallel devices (n is 0 to 2).
+Map host parallel devices (n is 0 to 2).
Note: This option allows direct access to host hardware. So it is no longer possible to migrate such machines - use with special care.
$kvm_user_version = 'unknown';
my $tmp = `kvm -help 2>/dev/null`;
-
+
if ($tmp =~ m/^QEMU( PC)? emulator version (\d+\.\d+\.\d+) /) {
$kvm_user_version = $2;
}
sub disknames {
# order is important - used to autoselect boot disk
- return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
+ return ((map { "ide$_" } (0 .. ($MAX_IDE_DISKS - 1))),
(map { "scsi$_" } (0 .. ($MAX_SCSI_DISKS - 1))),
(map { "virtio$_" } (0 .. ($MAX_VIRTIO_DISKS - 1))));
}
sub option_exists {
my $key = shift;
return defined($confdesc->{$key});
-}
+}
sub nic_models {
return $nic_model_list;
win7 => 'Windows 7',
l24 => 'Linux 2.4',
l26 => 'Linux 2.6',
- };
+ };
}
# a clumsy way to split an argument string into an array,
push @$args, $data;
});
};
-
+
my $err = $@;
die "unable to parse args: $str\n" if $err;
}
sub qemu_drive_name {
- my ($dev, $media) = @_;
+ my ($dev, $media) = @_;
my $info = disk_devive_info ($dev);
my $mediastr = '';
if (($info->{bus} eq 'ide') || ($info->{bus} eq 'scsi')) {
$mediastr = ($media eq 'cdrom') ? "-cd" : "-hd";
- return sprintf("%s%i%s%i", $info->{bus}, $info->{controller},
+ return sprintf("%s%i%s%i", $info->{bus}, $info->{controller},
$mediastr, $info->{unit});
} else {
- return sprintf("%s%i", $info->{bus}, $info->{index});
+ return sprintf("%s%i", $info->{bus}, $info->{index});
}
}
if (!($file eq 'none' || $file eq 'cdrom' ||
$file =~ m|^/dev/.+| || $file =~ m/^([^:]+):(.+)$/)) {
-
+
return undef if $file =~ m|/|;
-
+
if ($media && $media eq 'cdrom') {
$file = "local:iso/$file";
} else {
}
return if ($vtype eq $etype);
-
+
raise_param_exc({ $opt => "unexpected media type ($vtype != $etype)" });
}
if (($drive->{file} !~ m/^(cdrom|none)$/) &&
($drive->{file} !~ m|^/dev/.+|) &&
($drive->{file} !~ m/^([^:]+):(.+)$/) &&
- ($drive->{file} !~ m/^\d+$/)) {
+ ($drive->{file} !~ m/^\d+$/)) {
my ($vtype, $volid) = PVE::Storage::path_to_volume_id($storecfg, $drive->{file});
raise_param_exc({ $opt => "unable to associate path '$drive->{file}' to any storage"}) if !$vtype;
$drive->{media} = 'cdrom' if !$drive->{media} && $vtype eq 'iso';
my $filename = config_file ($vmid);
die "configuration file '$filename' already exists\n" if -f $filename;
-
+
my $defaults = load_defaults();
$settings->{name} = "vm$vmid" if !$settings->{name};
my ($key, $data) = @_;
my $res = {};
-
+
# $key may be undefined - used to verify JSON parameters
if (!defined($key)) {
$res->{interface} = 'unknown'; # should not harm when used to verify parameters
$k = 'file' if $k eq 'volume';
return undef if defined $res->{$k};
-
+
$res->{$k} = $v;
} else {
if (!$res->{file} && $p !~ m/=/) {
return undef if !$res->{file};
- return undef if $res->{cache} &&
+ return undef if $res->{cache} &&
$res->{cache} !~ m/^(off|none|writethrough|writeback)$/;
return undef if $res->{snapshot} && $res->{snapshot} !~ m/^(on|off)$/;
return undef if $res->{cyls} && $res->{cyls} !~ m/^\d+$/;
if ($res->{media} && ($res->{media} eq 'cdrom')) {
return undef if $res->{snapshot} || $res->{trans} || $res->{format};
- return undef if $res->{heads} || $res->{secs} || $res->{cyls};
+ return undef if $res->{heads} || $res->{secs} || $res->{cyls};
return undef if $res->{interface} eq 'virtio';
}
my $device = '';
my $maxdev = 0;
-
+
if ($drive->{interface} eq 'virtio') {
- $device="virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=device-$drive->{interface}$drive->{index}";
+ $device="virtio-blk-pci,drive=drive-$drive->{interface}$drive->{index},id=device-$drive->{interface}$drive->{index}";
}
elsif ($drive->{interface} eq 'scsi') {
}
if ($drive->{interface} eq 'usb'){
- # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
+ # -device ide-drive,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0
}
return $device;
my $opts = '';
foreach my $o (@qemu_drive_options) {
$opts .= ",$o=$drive->{$o}" if $drive->{$o};
- }
+ }
# use linux-aio by default (qemu default is threads)
- $opts .= ",aio=native" if !$drive->{aio};
+ $opts .= ",aio=native" if !$drive->{aio};
my $path;
my $volid = $drive->{file};
} else {
return undef;
}
-
+
}
return undef if !$res->{model};
return if $vid eq $volid; # do not add duplicates
} else {
$key = $test;
- }
+ }
}
die "To many unused volume - please delete them first.\n" if !$key;
sub verify_bootdisk {
my ($value, $noerr) = @_;
- return $value if valid_drivename($value);
+ return $value if valid_drivename($value);
return undef if $noerr;
return $value if parse_net($value);
return undef if $noerr;
-
+
die "unable to parse network options\n";
}
return $value if parse_drive (undef, $value);
return undef if $noerr;
-
+
die "unable to parse drive options\n";
}
return $value if parse_watchdog($value);
return undef if $noerr;
-
+
die "unable to parse watchdog options\n";
}
return $res;
}
-
+
PVE::JSONSchema::register_format('pve-qm-usb-device', \&verify_usb_device);
sub verify_usb_device {
my ($value, $noerr) = @_;
return $value if parse_usb_device($value);
return undef if $noerr;
-
+
die "unable to parse usb device\n";
}
}
if ($type eq 'boolean') {
- return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
- return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
- die "type check ('boolean') failed - got '$value'\n";
+ return 1 if ($value eq '1') || ($value =~ m/^(on|yes|true)$/i);
+ return 0 if ($value eq '0') || ($value =~ m/^(off|no|false)$/i);
+ die "type check ('boolean') failed - got '$value'\n";
} elsif ($type eq 'integer') {
return int($1) if $value =~ m/^(\d+)$/;
die "type check ('integer') failed - got '$value'\n";
die "unable to parse drive options\n";
}
PVE::JSONSchema::check_format($fmt, $value);
- return $value;
- }
+ return $value;
+ }
$value =~ s/^\"(.*)\"$/$1/;
- return $value;
+ return $value;
} else {
die "internal error"
}
my $fmt = $disk->{format} || $defformat;
syslog ('info', "VM $vmid creating new disk - size is $size GB");
- my $volid = PVE::Storage::vdisk_alloc ($storecfg, $storeid, $vmid,
+ my $volid = PVE::Storage::vdisk_alloc ($storecfg, $storeid, $vmid,
$fmt, undef, $size*1024*1024);
$disk->{file} = $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"
check_lock ($conf);
- # only remove disks owned by this VM
+ # only remove disks owned by this VM
foreach_drive($conf, sub {
my ($ds, $drive) = @_;
PVE::Storage::vdisk_free ($storecfg, $volid);
});
-
+
unlink $conffile;
# also remove unused disk
eval {
PVE::Storage::foreach_volid ($dl, sub {
my ($volid, $sid, $volname, $d) = @_;
- PVE::Storage::vdisk_free ($storecfg, $volid);
+ PVE::Storage::vdisk_free ($storecfg, $volid);
});
};
warn $@ if $@;
foreach my $ds (keys %$res) {
my $di = $res->{$ds};
- $res->{$ds}->{disksize} = $info->{$di->{file}} ?
+ $res->{$ds}->{disksize} = $info->{$di->{file}} ?
$info->{$di->{file}}->{size} / (1024*1024) : 0;
}
die "no such VM ('$vmid')\n" if !defined($conf);
return $conf;
-}
+}
sub parse_vm_config {
my ($filename, $raw) = @_;
digest => Digest::SHA1::sha1_hex($raw),
};
- $filename =~ m|/qemu-server/(\d+)\.conf$|
+ $filename =~ m|/qemu-server/(\d+)\.conf$|
|| die "got strange filename '$filename'";
my $vmid = $1;
while ($raw && $raw =~ s/^(.*?)(\n|$)//) {
my $line = $1;
-
+
next if $line =~ m/^\#/;
next if $line =~ m/^\s*$/;
# convert old smp to sockets
if ($res->{smp} && !$res->{sockets}) {
$res->{sockets} = $res->{smp};
- }
+ }
delete $res->{smp};
return $res;
# we do not use 'smp' any longer
if ($settings->{sockets}) {
- $unset->{smp} = 1;
+ $unset->{smp} = 1;
} elsif ($settings->{smp}) {
$settings->{sockets} = $settings->{smp};
$unset->{smp} = 1;
my $done;
while (my $line = <$fh>) {
-
+
if (($line =~ m/^\#/) || ($line =~ m/^\s*$/)) {
die $werror unless print $out $line;
next;
}
if (!defined ($unset->{$key})) {
die $werror unless print $out "$key: $value\n";
- }
+ }
next;
}
if (!$out->close()) {
$err = "close failed - $!\n";
unlink $tmpfn;
- die $err;
+ die $err;
}
if (!rename($tmpfn, $filename)) {
}
}
-sub load_defaults {
+sub load_defaults {
my $res = {};
$res->{$key} = $default;
}
}
-
+
my $conf = PVE::Cluster::cfs_read_file('datacenter.cfg');
$res->{keyboard} = $conf->{keyboard} if $conf->{keyboard};
my ($conf, $noerr) = @_;
my $loc_res = 0;
-
+
$loc_res = 1 if $conf->{hostusb}; # old syntax
$loc_res = 1 if $conf->{hostpci}; # old syntax
}
sub vzlist {
-
+
my $vzlist = config_list();
my $fd = IO::Dir->new ($var_run_tmpdir) || return $vzlist;
- while (defined(my $de = $fd->read)) {
+ while (defined(my $de = $fd->read)) {
next if $de !~ m/^(\d+)\.pid$/;
my $vmid = $1;
next if !defined ($vzlist->{$vmid});
my $res = {};
- my $storecfg = PVE::Storage::config();
+ my $storecfg = PVE::Storage::config();
my $list = vzlist();
my ($uptime) = PVE::ProcFSTools::read_proc_uptime();
$d->{cpus} = ($conf->{sockets} || 1) * ($conf->{cores} || 1);
$d->{name} = $conf->{name} || "VM $vmid";
- $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
+ $d->{maxmem} = $conf->{memory} ? $conf->{memory}*(1024*1024) : 0;
$d->{uptime} = 0;
my $vmid = $1;
my $d = $res->{$vmid};
next if !$d;
-
+
$d->{netout} += $netdev->{$dev}->{receive};
$d->{netin} += $netdev->{$dev}->{transmit};
}
} else {
next;
}
-
+
my $used = $utime + $stime;
my $vcpus = $d->{cpus} > $cpucount ? $cpucount : $d->{cpus};
my $old = $last_proc_pid_stat->{$pid};
if (!$old) {
- $last_proc_pid_stat->{$pid} = {
- time => $ctime,
+ $last_proc_pid_stat->{$pid} = {
+ time => $ctime,
used => $used,
cpu => 0,
relcpu => 0,
$d->{cpu} = $dutime/$dtime;
$d->{relcpu} = ($d->{cpu} * $cpucount) / $vcpus;
$last_proc_pid_stat->{$pid} = {
- time => $ctime,
+ time => $ctime,
used => $used,
cpu => $d->{cpu},
relcpu => $d->{relcpu},
push @$cmd, '-vnc', "unix:$socket,x509,password";
push @$cmd, '-pidfile' , pidfile_name ($vmid);
-
+
push @$cmd, '-daemonize';
push @$cmd, '-incoming', $migrate_uri if $migrate_uri;
# include usb device config
push @$cmd, '-readconfig', '/usr/share/qemu-server/pve-usb.cfg';
-
+
# enable absolute mouse coordinates (needed by vnc)
my $tablet = defined ($conf->{tablet}) ? $conf->{tablet} : $defaults->{tablet};
push @$cmd, '-device', 'usb-tablet,bus=ehci.0,port=6' if $tablet;
# serial devices
for (my $i = 0; $i < $MAX_SERIAL_PORTS; $i++) {
if (my $path = $conf->{"serial$i"}) {
- die "no such serial device\n" if ! -c $path;
+ die "no such serial device\n" if ! -c $path;
push @$cmd, '-chardev', "tty,id=serial$i,path=$path";
push @$cmd, '-device', "isa-serial,chardev=serial$i";
}
# parallel devices
for (my $i = 0; $i < $MAX_PARALLEL_PORTS; $i++) {
if (my $path = $conf->{"parallel$i"}) {
- die "no such parallel device\n" if ! -c $path;
+ die "no such parallel device\n" if ! -c $path;
push @$cmd, '-chardev', "parport,id=parallel$i,path=$path";
push @$cmd, '-device', "isa-parallel,chardev=parallel$i";
}
my $vmname = $conf->{name} || "vm$vmid";
push @$cmd, '-name', $vmname;
-
+
my $sockets = 1;
$sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
$sockets = $conf->{sockets} if $conf->{sockets};
$vga = 'cirrus';
}
}
-
+
push @$cmd, '-vga', $vga if $vga; # for kvm 77 and later
# time drift fix
}
# -tdf ?
- # -no-acpi
- # -no-kvm
+ # -no-acpi
+ # -no-kvm
# -win2k-hack ?
}
foreach_drive($conf, sub {
my ($ds, $drive) = @_;
- eval {
+ eval {
PVE::Storage::parse_volume_id ($drive->{file});
push @$vollist, $drive->{file};
}; # ignore errors
});
push @$cmd, '-m', $conf->{memory} || $defaults->{memory};
-
+
my $foundnet = 0;
foreach my $k (sort keys %$conf) {
my $ifname = "tap${vmid}i$i";
# kvm uses TUNSETIFF ioctl, and that limits ifname length
- die "interface name '$ifname' is too long (max 15 character)\n"
+ die "interface name '$ifname' is too long (max 15 character)\n"
if length($ifname) >= 16;
my $device = $net->{model};
"romfile=," : '';
push @$cmd, '-device', "$device,${extra}mac=$net->{macaddr},netdev=${k}";
}
- }
-
+ }
+
push @$cmd, '-net', 'none' if !$foundnet;
# hack: virtio with fairsched is unreliable, so we do not use fairsched
# when the VM uses virtio devices.
- if (!$use_virtio && $have_ovz) {
-
- my $cpuunits = defined ($conf->{cpuunits}) ?
+ if (!$use_virtio && $have_ovz) {
+
+ my $cpuunits = defined ($conf->{cpuunits}) ?
$conf->{cpuunits} : $defaults->{cpuunits};
push @$cmd, '-cpuunits', $cpuunits if $cpuunits;
return wantarray ? ($cmd, $vollist) : $cmd;
}
-
+
sub vnc_socket {
my ($vmid) = @_;
return "${var_run_tmpdir}/$vmid.vnc";
$mac .= ":$ss";
}
}
-
+
return $mac;
}
}
}
- if (my $migrate_speed =
+ if (my $migrate_speed =
$conf->{migrate_speed} || $defaults->{migrate_speed}) {
my $cmd = "migrate_set_speed ${migrate_speed}m";
eval { vm_monitor_command ($vmid, $cmd, 1); };
}
- if (my $migrate_downtime =
+ if (my $migrate_downtime =
$conf->{migrate_downtime} || $defaults->{migrate_downtime}) {
my $cmd = "migrate_set_downtime ${migrate_downtime}";
eval { vm_monitor_command ($vmid, $cmd, 1); };
my $timeout = 3;
- # hack: migrate sometime blocks the monitor (when migrate_downtime
+ # hack: migrate sometime blocks the monitor (when migrate_downtime
# is set)
if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
$timeout = 60*60; # 1 hour
# read banner;
my $data = __read_avail ($sock, $timeout);
-
+
if ($data !~ m/^QEMU\s+(\S+)\s+monitor\s/) {
die "got unexpected qemu monitor banner\n";
}
return if ($cmdstr eq 'q') || ($cmdstr eq 'quit');
- $timeout = 20;
+ $timeout = 20;
if ($cmdstr =~ m/^(info\s+migrate|migrate\s)/) {
$timeout = 60*60; # 1 hour
$timeout = 60; # note: cdrom mount command is slow
}
if ($res = __read_avail ($sock, $timeout)) {
-
+
my @lines = split ("\r?\n", $res);
shift @lines if $lines[0] !~ m/^unknown command/; # skip echo
-
+
$res = join ("\n", @lines);
$res .= "\n";
}
my $conf = load_config ($vmid);
check_lock ($conf) if !$skiplock;
-
+
syslog ("info", "VM $vmid stopping");
eval { vm_monitor_command ($vmid, "quit", 1); };
check_lock ($conf) if !$skiplock;
syslog ("info", "VM $vmid sending cntl-alt-delete");
-
+
vm_monitor_command ($vmid, "sendkey ctrl-alt-delete", 1);
});
}
foreach my $vmid (keys %$vzlist) {
next if !$vzlist->{$vmid}->{pid};
-
+
$msg = "VM $vmid still running - sending stop now\n";
syslog ('info', $msg);
print $msg;
foreach my $vmid (keys %$vzlist) {
next if !$vzlist->{$vmid}->{pid};
-
+
$msg = "VM $vmid still running - terminating now with SIGTERM\n";
syslog ('info', $msg);
print $msg;
PVE::Cluster::cfs_update();
# global vars, initialized later
-my @rem_ssh;
+my @rem_ssh;
my $vmid;
my $node;
my $nodeip;
-my $storecfg = PVE::Storage::config();
+my $storecfg = PVE::Storage::config();
my $delayed_interrupt = 0;
# we only use RESTHandler for automatic parameter verification
__PACKAGE__->register_method({
- name => 'qmigrate',
- path => 'qmigrate',
+ name => 'qmigrate',
+ path => 'qmigrate',
method => 'POST',
description => "Migrate VMs to other cluster nodes.",
parameters => {
$nodeip = PVE::Cluster::remote_node_ip($node);
@rem_ssh = (@ssh_cmd, "root\@$nodeip");
- # lock config during migration
+ # lock config during migration
PVE::QemuServer::lock_config($vmid, sub {
eval_int(\&prepare);
my $conf = PVE::QemuServer::load_config($vmid);
PVE::QemuServer::check_lock($conf);
-
+
my $running = 0;
if (PVE::QemuServer::check_running($vmid)) {
die "cant migrate running VM without --online\n" if !$param->{online};
# vm is now owned by other node
my $volids = $rhash->{volumes};
-
+
if ($running) {
-
+
$rhash = {};
eval_int(sub { phase2($conf, $rhash); });
my $err = $@;
# finalize -- clear migrate lock
eval_int(sub {
- my $cmd = [ @rem_ssh, $qm_cmd, 'unlock', $vmid ];
+ my $cmd = [ @rem_ssh, $qm_cmd, 'unlock', $vmid ];
run_command($cmd);
});
if ($@) {
logmsg('err', "failed to clear migrate lock - $@");
$errors = 1;
}
-
+
# destroy local copies
foreach my $volid (@$volids) {
eval_int(sub { PVE::Storage::vdisk_free($storecfg, $volid); });
if ($err) {
logmsg('err', "removing local copy of '$volid' failed - $err");
$errors = 1;
-
+
last if $err =~ /^interrupted by signal$/;
}
}
$volhash->{$volid} = 1;
});
- # and add used,owned/non-shared disks (just to be sure we have all)
+ # and add used,owned/non-shared disks (just to be sure we have all)
my $sharedvm = 1;
PVE::QemuServer::foreach_drive($conf, sub {
}
my ($sid, $volname) = PVE::Storage::parse_volume_id($volid);
-
+
my $scfg = PVE::Storage::storage_config($storecfg, $sid);
return if $scfg->{shared};
sub fork_command_pipe {
my ($cmd) = @_;
-
+
my $reader = IO::File->new();
my $writer = IO::File->new();
# catch exec errors
if ($orig_pid != $$) {
logmsg('err', "can't fork command pipe\n");
- POSIX::_exit(1);
- kill('KILL', $$);
+ POSIX::_exit(1);
+ kill('KILL', $$);
}
die $err if $err;
return { writer => $writer, reader => $reader, pid => $cpid };
}
-sub finish_command_pipe {
+sub finish_command_pipe {
my $cmdpipe = shift;
my $writer = $cmdpipe->{writer};
};
my $err = $@;
-
+
alarm($prev_alarm) if defined($prev_alarm);
die "unknown error" if $sigcount && !$err; # seems to happen sometimes
my $cmd = [@ssh_cmd, '-o', 'BatchMode=yes',
'-L', "$lport:localhost:$rport", $nodeip,
'qm', 'mtunnel' ];
-
+
my $tunnel = fork_command_pipe($cmd);
my $reader = $tunnel->{reader};
my $helo;
- eval {
- run_with_timeout(60, sub { $helo = <$reader>; });
+ eval {
+ run_with_timeout(60, sub { $helo = <$reader>; });
die "no reply\n" if !$helo;
die "no quorum on target node\n" if $helo =~ m/^no quorum$/;
- die "got strange reply from mtunnel ('$helo')\n"
+ die "got strange reply from mtunnel ('$helo')\n"
if $helo !~ m/^tunnel online$/;
};
my $err = $@;
return $tunnel;
}
-sub finish_tunnel {
+sub finish_tunnel {
my $tunnel = shift;
my $writer = $tunnel->{writer};
- eval {
+ eval {
run_with_timeout(30, sub {
print $writer "quit\n";
$writer->flush();
- });
+ });
};
my $err = $@;
-
+
finish_command_pipe($tunnel);
-
+
die $err if $err;
}
my $rport;
- ## start on remote node
+ ## start on remote node
my $cmd = [@rem_ssh, $qm_cmd, '--skiplock', 'start', $vmid, '--incoming', 'tcp'];
run_command($cmd, outfunc => sub {