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;
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,
&$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});
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) {
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') {
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";
(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);
}
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,