]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/API2/Qemu.pm
fix #2787: properly parse 'vga' for vncproxy
[qemu-server.git] / PVE / API2 / Qemu.pm
index 9fb886b4600eb367d49bee5a86c804476122d392..9cfaa29fdaa0ee393227ffa45d839c2916e47fd7 100644 (file)
@@ -21,6 +21,7 @@ use PVE::GuestHelpers;
 use PVE::QemuConfig;
 use PVE::QemuServer;
 use PVE::QemuServer::Drive;
+use PVE::QemuServer::CPUConfig;
 use PVE::QemuServer::Monitor qw(mon_cmd);
 use PVE::QemuMigrate;
 use PVE::RPCEnvironment;
@@ -236,6 +237,26 @@ my $create_disks = sub {
     return $vollist;
 };
 
+my $check_cpu_model_access = sub {
+    my ($rpcenv, $authuser, $new, $existing) = @_;
+
+    return if !defined($new->{cpu});
+
+    my $cpu = PVE::JSONSchema::check_format('pve-vm-cpu-conf', $new->{cpu});
+    return if !$cpu || !$cpu->{cputype}; # always allow default
+    my $cputype = $cpu->{cputype};
+
+    if ($existing && $existing->{cpu}) {
+       # changing only other settings doesn't require permissions for CPU model
+       my $existingCpu = PVE::JSONSchema::check_format('pve-vm-cpu-conf', $existing->{cpu});
+       return if $existingCpu->{cputype} eq $cputype;
+    }
+
+    if (PVE::QemuServer::CPUConfig::is_custom_model($cputype)) {
+       $rpcenv->check($authuser, "/nodes", ['Sys.Audit']);
+    }
+};
+
 my $cpuoptions = {
     'cores' => 1,
     'cpu' => 1,
@@ -543,6 +564,8 @@ __PACKAGE__->register_method({
 
            &$check_vm_modify_config_perm($rpcenv, $authuser, $vmid, $pool, [ keys %$param]);
 
+           &$check_cpu_model_access($rpcenv, $authuser, $param);
+
            foreach my $opt (keys %$param) {
                if (PVE::QemuServer::is_valid_drivename($opt)) {
                    my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
@@ -1072,7 +1095,10 @@ my $update_vm_api  = sub {
        return if PVE::QemuServer::drive_is_cdrom($drive);
 
        my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
-       return if $volname eq 'cloudinit';
+       die "cannot add non-managed/pass-through volume to a replicated VM\n"
+           if !defined($storeid);
+
+       return if defined($volname) && $volname eq 'cloudinit';
 
        my $format;
        if ($volid =~ $NEW_DISK_RE) {
@@ -1122,6 +1148,8 @@ my $update_vm_api  = sub {
        die "checksum missmatch (file change by other user?)\n"
            if $digest && $digest ne $conf->{digest};
 
+       &$check_cpu_model_access($rpcenv, $authuser, $param, $conf);
+
        # FIXME: 'suspended' lock should probabyl be a state or "weak" lock?!
        if (scalar(@delete) && grep { $_ eq 'vmstate'} @delete) {
            if (defined($conf->{lock}) && $conf->{lock} eq 'suspended') {
@@ -1606,7 +1634,12 @@ __PACKAGE__->register_method({
        my $websocket = $param->{websocket};
 
        my $conf = PVE::QemuConfig->load_config($vmid, $node); # check if VM exists
-       my $use_serial = ($conf->{vga} && ($conf->{vga} =~ m/^serial\d+$/));
+       
+       my $serial;
+       if ($conf->{vga}) {
+           my $vga = PVE::QemuServer::parse_vga($conf->{vga});
+           $serial = $vga->{type} if $vga->{type} =~ m/^serial\d+$/;
+       }
 
        my $authpath = "/vms/$vmid";
 
@@ -1622,7 +1655,7 @@ __PACKAGE__->register_method({
            (undef, $family) = PVE::Cluster::remote_node_ip($node);
            my $sshinfo = PVE::SSHInfo::get_ssh_info($node);
            # NOTE: kvm VNC traffic is already TLS encrypted or is known unsecure
-           $remcmd = PVE::SSHInfo::ssh_info_to_command($sshinfo, $use_serial ? '-t' : '-T');
+           $remcmd = PVE::SSHInfo::ssh_info_to_command($sshinfo, defined($serial) ? '-t' : '-T');
        } else {
            $family = PVE::Tools::get_host_address_family($node);
        }
@@ -1638,9 +1671,9 @@ __PACKAGE__->register_method({
 
            my $cmd;
 
-           if ($use_serial) {
+           if (defined($serial)) {
 
-               my $termcmd = [ '/usr/sbin/qm', 'terminal', $vmid, '-iface', $conf->{vga}, '-escape', '0' ];
+               my $termcmd = [ '/usr/sbin/qm', 'terminal', $vmid, '-iface', $serial, '-escape', '0' ];
 
                $cmd = ['/usr/bin/vncterm', '-rfbport', $port,
                        '-timeout', $timeout, '-authpath', $authpath,