PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
description => "Specifies the Qemu machine type.",
type => 'string',
- pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\.pxe)?|virt(?:-\d+(\.\d+)+)?)',
+ pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)',
maxLength => 40,
optional => 1,
});
description => "Configure additional enhancements for SPICE.",
optional => 1
},
+ tags => {
+ type => 'string', format => 'pve-tag-list',
+ description => 'Tags of the VM. This is only meta information.',
+ optional => 1,
+ },
};
my $cicustom_fmt = {
}
sub print_drive {
- my ($vmid, $drive) = @_;
+ my ($drive) = @_;
my $data = { %$drive };
delete $data->{$_} for qw(index interface);
return PVE::JSONSchema::print_property_string($data, $alldrive_fmt);
}
# for compatibility only, we prefer scsi-hd (#2408, #2355, #2380)
- my $version = PVE::QemuServer::Machine::extract_version($machine_type) // kvm_user_version();
+ my $version = PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
if ($path =~ m/^iscsi\:\/\// &&
!min_version($version, 4, 1)) {
$devicetype = 'generic';
my @idlist = split(/;/, $res->{host});
delete $res->{host};
foreach my $id (@idlist) {
- if ($id =~ m/\./) { # full id 00:00.1
- push @{$res->{pciid}}, {
- id => $id,
- };
- } else { # partial id 00:00
- $res->{pciid} = PVE::SysFSTools::lspci($id);
- }
+ my $devs = PVE::SysFSTools::lspci($id);
+ die "no PCI device found for '$id'\n" if !scalar(@$devs);
+ push @{$res->{pciid}}, @$devs;
}
return $res;
}
my $v = parse_drive($key, $value);
if (my $volid = filename_to_volume_id($vmid, $v->{file}, $v->{media})) {
$v->{file} = $volid;
- $value = print_drive($vmid, $v);
+ $value = print_drive($v);
} else {
warn "vm $vmid - unable to parse value of '$key'\n";
next;
&$cleanup_config($conf->{pending}, 1);
foreach my $snapname (keys %{$conf->{snapshots}}) {
- die "internal error" if $snapname eq 'pending';
+ die "internal error: snapshot name '$snapname' is forbidden" if lc($snapname) eq 'pending';
&$cleanup_config($conf->{snapshots}->{$snapname}, undef, $snapname);
}
description => "The current config lock, if any.",
type => 'string',
optional => 1,
- }
+ },
+ tags => {
+ description => "The current configured tags, if any",
+ type => 'string',
+ optional => 1,
+ },
};
my $last_proc_pid_stat;
$d->{serial} = 1 if conf_has_serial($conf);
$d->{lock} = $conf->{lock} if $conf->{lock};
+ $d->{tags} = $conf->{tags} if defined($conf->{tags});
$res->{$vmid} = $d;
}
return get_host_arch() eq $arch;
}
+sub get_vm_arch {
+ my ($conf) = @_;
+ return $conf->{arch} // get_host_arch();
+}
+
my $default_machines = {
x86_64 => 'pc',
aarch64 => 'virt',
};
-sub get_basic_machine_info {
- my ($conf, $forcemachine) = @_;
+sub get_vm_machine {
+ my ($conf, $forcemachine, $arch, $add_pve_version) = @_;
+
+ my $machine = $forcemachine || $conf->{machine};
+
+ if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) {
+ $arch //= 'x86_64';
+ $machine ||= $default_machines->{$arch};
+ $machine .= "+pve$PVE::QemuServer::Machine::PVE_MACHINE_VERSION" if $add_pve_version;
+ }
- my $arch = $conf->{arch} // get_host_arch();
- my $machine = $forcemachine || $conf->{machine} || $default_machines->{$arch};
- return ($arch, $machine);
+ return $machine;
}
sub get_ovmf_files($) {
my $winversion = windows_version($ostype);
my $kvm = $conf->{kvm};
- my ($arch, $machine_type) = get_basic_machine_info($conf, $forcemachine);
+ my $arch = get_vm_arch($conf);
my $kvm_binary = get_command_for_arch($arch);
my $kvmver = kvm_user_version($kvm_binary);
- my $machine_version = PVE::QemuServer::Machine::extract_version($machine_type) // $kvmver;
+
+ my $add_pve_version = min_version($kvmver, 4, 1);
+
+ my $machine_type = get_vm_machine($conf, $forcemachine, $arch, $add_pve_version);
+ my $machine_version = PVE::QemuServer::Machine::extract_version($machine_type, $kvmver);
$kvm //= 1 if is_native($arch);
if ($kvm) {
my $statepath = PVE::Storage::path($storecfg, $vmstate);
push @$vollist, $vmstate;
push @$cmd, '-loadstate', $statepath;
+ print "activating and using '$vmstate' as vmstate\n";
}
# add custom args
'protection' => 1,
'vmstatestorage' => 1,
'hookscript' => 1,
+ 'tags' => 1,
};
# hotplug changes in [PENDING]
my ($vmid, $conf, $storecfg, $selection, $errors) = @_;
my $defaults = load_defaults();
- my ($arch, $machine_type) = get_basic_machine_info($conf, undef);
+ my $arch = get_vm_arch($conf);
+ my $machine_type = get_vm_machine($conf, undef, $arch);
# commit values which do not have any impact on running VM first
# Note: those option cannot raise errors, we we do not care about
vmconfig_update_net($storecfg, $conf, $hotplug_features->{network},
$vmid, $opt, $value, $arch, $machine_type);
} elsif (is_valid_drivename($opt)) {
+ die "skip\n" if $opt eq 'efidisk0';
# some changes can be done without hotplug
my $drive = parse_drive($opt, $value);
if (drive_is_cloudinit($drive)) {
my $newdrive = $drive;
$newdrive->{format} = $format;
$newdrive->{file} = $newvolid;
- my $drivestr = PVE::QemuServer::print_drive($vmid, $newdrive);
+ my $drivestr = print_drive($newdrive);
$local_volumes->{$opt} = $drivestr;
#pass drive to conf for command line
$conf->{$opt} = $drivestr;
property => "guest-stats-polling-interval",
value => 2) if (!defined($conf->{balloon}) || $conf->{balloon});
- if ($is_suspended && (my $vmstate = $conf->{vmstate})) {
+ if ($is_suspended) {
print "Resumed VM, removing state\n";
+ if (my $vmstate = $conf->{vmstate}) {
+ PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
+ PVE::Storage::vdisk_free($storecfg, $vmstate);
+ }
delete $conf->@{qw(lock vmstate runningmachine)};
- PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
- PVE::Storage::vdisk_free($storecfg, $vmstate);
PVE::QemuConfig->write_config($vmid, $conf);
}
} elsif ($map->{$virtdev}) {
delete $di->{format}; # format can change on restore
$di->{file} = $map->{$virtdev};
- $value = print_drive($vmid, $di);
+ $value = print_drive($di);
print $outfd "$virtdev: $value\n";
} else {
print $outfd $line;
next if !$volid_hash->{$volid};
$drive->{size} = $volid_hash->{$volid}->{size};
- my $new = print_drive($vmid, $drive);
+ my $new = print_drive($drive);
if ($new ne $conf->{$opt}) {
$changes = 1;
$conf->{$opt} = $new;
my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
$drive->{file} = $voliddst;
- $conf->{$ds} = print_drive($vmid, $drive);
+ $conf->{$ds} = print_drive($drive);
PVE::QemuConfig->write_config($vmid, $conf);
});
}
my $cachemode;
my $src_path;
my $src_is_iscsi = 0;
- my $src_format = 'raw';
+ my $src_format;
if ($src_storeid) {
PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
my $cmd = [];
push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
- push @$cmd, '-l', "snapshot.name=$snapname" if($snapname && $src_format eq "qcow2");
+ push @$cmd, '-l', "snapshot.name=$snapname"
+ if $snapname && $src_format && $src_format eq "qcow2";
push @$cmd, '-t', 'none' if $dst_scfg->{type} eq 'zfspool';
push @$cmd, '-T', $cachemode if defined($cachemode);
if ($src_is_iscsi) {
push @$cmd, '--image-opts';
$src_path = convert_iscsi_path($src_path);
- } else {
+ } elsif ($src_format) {
push @$cmd, '-f', $src_format;
}
$machine_type = $1;
$use_old_bios_files = 1;
} else {
- my $version = PVE::QemuServer::Machine::extract_version($machine_type) // kvm_user_version();
+ my $version = PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
# Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
# load new efi bios files on migration. So this hack is required to allow
# live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
PVE::Storage::activate_volumes($storecfg, [$volid]);
qemu_img_convert($ovmf_vars, $volid, $vars_size_b, undef, 0);
+ my ($size) = PVE::Storage::volume_size_info($storecfg, $volid, 3);
- return ($volid, $vars_size);
+ return ($volid, $size/1024);
}
sub vm_iothreads_list {