use Cwd 'abs_path';
use Net::SSLeay;
use UUID;
+use POSIX;
+use IO::Socket::IP;
use PVE::Cluster qw (cfs_read_file cfs_write_file);;
use PVE::SafeSyslog;
my $vollist = [];
my $res = {};
- PVE::QemuServer::foreach_drive($settings, sub {
+
+ my $code = sub {
my ($ds, $disk) = @_;
my $volid = $disk->{file};
if (!$volid || $volid eq 'none' || $volid eq 'cdrom') {
delete $disk->{size};
$res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
- } elsif ($volid =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
+ } elsif ($volid =~ m!^(([^/:\s]+):)?(\d+(\.\d+)?)$!) {
my ($storeid, $size) = ($2 || $default_storage, $3);
die "no storage ID specified (and no default storage)\n" if !$storeid;
my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
$res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
}
- });
+ };
+
+ eval { PVE::QemuServer::foreach_drive($settings, $code); };
# free allocated images on error
if (my $err = $@) {
foreach my $opt (@delete) {
$modified->{$opt} = 1;
$conf = PVE::QemuConfig->load_config($vmid); # update/reload
+ if (!defined($conf->{$opt})) {
+ warn "cannot delete '$opt' - not set in current configuration!\n";
+ $modified->{$opt} = 0;
+ next;
+ }
+
if ($opt =~ m/^unused/) {
my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
PVE::QemuConfig->check_protection($conf, "can't remove unused disk '$drive->{file}'");
if defined($conf->{pending}->{$opt});
&$create_disks($rpcenv, $authuser, $conf->{pending}, $storecfg, $vmid, undef, {$opt => $param->{$opt}});
+ } elsif ($opt eq "replicate") {
+ # check if all volumes have replicate feature
+ PVE::QemuConfig->get_replicatable_volumes($storecfg, $conf);
+ my $repl = PVE::JSONSchema::check_format('pve-replicate', $param->{opt});
+ PVE::Cluster::check_node_exists($repl->{target});
+ $conf->{$opt} = $param->{$opt};
} else {
$conf->{pending}->{$opt} = $param->{$opt};
}
$cmd = ['/usr/bin/vncterm', '-rfbport', $port,
'-timeout', $timeout, '-authpath', $authpath,
'-perm', 'Sys.Console', '-c', @$remcmd, @$termcmd];
+ PVE::Tools::run_command($cmd);
} else {
$ENV{LC_PVE_TICKET} = $ticket if $websocket; # set ticket with "qm vncproxy"
- my $qmcmd = [@$remcmd, "/usr/sbin/qm", 'vncproxy', $vmid];
-
- my $qmstr = join(' ', @$qmcmd);
-
- # also redirect stderr (else we get RFB protocol errors)
- $cmd = ['/bin/nc6', '-l', '-p', $port, '-w', $timeout, '-e', "$qmstr 2>/dev/null"];
+ $cmd = [@$remcmd, "/usr/sbin/qm", 'vncproxy', $vmid];
+
+ my $sock = IO::Socket::IP->new(
+ ReuseAddr => 1,
+ Listen => 1,
+ LocalPort => $port,
+ Proto => 'tcp',
+ GetAddrInfoFlags => 0,
+ ) or die "failed to create socket: $!\n";
+ # Inside the worker we shouldn't have any previous alarms
+ # running anyway...:
+ alarm(0);
+ local $SIG{ALRM} = sub { die "connection timed out\n" };
+ alarm $timeout;
+ accept(my $cli, $sock) or die "connection failed: $!\n";
+ alarm(0);
+ close($sock);
+ if (PVE::Tools::run_command($cmd,
+ output => '>&'.fileno($cli),
+ input => '<&'.fileno($cli),
+ noerr => 1) != 0)
+ {
+ die "Failed to run vncproxy.\n";
+ }
}
- PVE::Tools::run_command($cmd);
-
return;
};
- my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd);
+ my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd, 1);
PVE::Tools::wait_for_vnc_port($port);
$newconf->{$opt} = $value; # simply copy configuration
} else {
if ($param->{full}) {
- die "Full clone feature is not available"
+ die "Full clone feature is not supported for drive '$opt'\n"
if !PVE::Storage::volume_has_feature($storecfg, 'copy', $drive->{file}, $snapname, $running);
$fullclone->{$opt} = 1;
} else {
# not full means clone instead of copy
- die "Linked clone feature is not available"
+ die "Linked clone feature is not supported for drive '$opt'\n"
if !PVE::Storage::volume_has_feature($storecfg, 'clone', $drive->{file}, $snapname, $running);
}
$drives->{$opt} = $drive;
}
my $storecfg = PVE::Storage::config();
- PVE::QemuServer::check_storage_availability($storecfg, $conf, $target);
+
+ if( $param->{targetstorage}) {
+ PVE::Storage::storage_check_node($storecfg, $param->{targetstorage}, $target);
+ } else {
+ PVE::QemuServer::check_storage_availability($storecfg, $conf, $target);
+ }
if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
size => {
type => 'string',
pattern => '\+?\d+(\.\d+)?[KMGT]?',
- description => "The new size. With the '+' sign the value is added to the actual size of the volume and without it, the value is taken as an absolute one. Shrinking disk size is not supported.",
+ description => "The new size. With the `+` sign the value is added to the actual size of the volume and without it, the value is taken as an absolute one. Shrinking disk size is not supported.",
},
digest => {
type => 'string',