optional => 1,
description => "Emulated CPU type.",
type => 'string',
- enum => [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
+ enum => [ qw(486 athlon pentium pentium2 pentium3 coreduo core2duo kvm32 kvm64 qemu32 qemu64 phenom Conroe Penryn Nehalem Westmere SandyBridge Haswell Broadwell Opteron_G1 Opteron_G2 Opteron_G3 Opteron_G4 Opteron_G5 host) ],
default => 'kvm64',
},
parent => get_standard_option('pve-snapshot-name', {
maxLength => 40,
optional => 1,
},
+ smbios1 => {
+ description => "Specify SMBIOS type 1 fields.",
+ type => 'string', format => 'pve-qm-smbios1',
+ typetext => "[manufacturer=str][,product=str][,version=str][,serial=str] [,uuid=uuid][,sku=str][,family=str]",
+ maxLength => 256,
+ optional => 1,
+ },
};
# what about other qemu settings ?
my $MAX_USB_DEVICES = 5;
my $MAX_NETS = 32;
my $MAX_UNUSED_DISKS = 8;
-my $MAX_HOSTPCI_DEVICES = 2;
+my $MAX_HOSTPCI_DEVICES = 4;
my $MAX_SERIAL_PORTS = 4;
my $MAX_PARALLEL_PORTS = 3;
return $key;
}
+my $valid_smbios1_options = {
+ manufacturer => '\S+',
+ product => '\S+',
+ version => '\S+',
+ serial => '\S+',
+ uuid => '[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}',
+ sku => '\S+',
+ family => '\S+',
+};
+
+# smbios: [manufacturer=str][,product=str][,version=str][,serial=str][,uuid=uuid][,sku=str][,family=str]
+sub parse_smbios1 {
+ my ($data) = @_;
+
+ my $res = {};
+
+ foreach my $kvp (split(/,/, $data)) {
+ return undef if $kvp !~ m/^(\S+)=(.+)$/;
+ my ($k, $v) = split(/=/, $kvp);
+ return undef if !defined($k) || !defined($v);
+ return undef if !$valid_smbios1_options->{$k};
+ return undef if $v !~ m/^$valid_smbios1_options->{$k}$/;
+ $res->{$k} = $v;
+ }
+
+ return $res;
+}
+
+sub print_smbios1 {
+ my ($smbios1) = @_;
+
+ my $data = '';
+ foreach my $k (keys %$smbios1) {
+ next if !defined($smbios1->{$k});
+ next if !$valid_smbios1_options->{$k};
+ $data .= ',' if $data;
+ $data .= "$k=$smbios1->{$k}";
+ }
+ return $data;
+}
+
+PVE::JSONSchema::register_format('pve-qm-smbios1', \&verify_smbios1);
+sub verify_smbios1 {
+ my ($value, $noerr) = @_;
+
+ return $value if parse_smbios1($value);
+
+ return undef if $noerr;
+
+ die "unable to parse smbios (type 1) options\n";
+}
+
PVE::JSONSchema::register_format('pve-qm-bootdisk', \&verify_bootdisk);
sub verify_bootdisk {
my ($value, $noerr) = @_;
push @$cmd, '-daemonize';
+ if ($conf->{smbios1}) {
+ push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
+ }
+
if ($q35) {
# the q35 chipset support native usb2, so we enable usb controller
# by default for this machine type
}
push @$devices, '-device', print_tabletdevice_full($conf) if $tablet;
-
+
# host pci devices
for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
my $d = parse_hostpci($conf->{"hostpci$i"});
my $rombar = $d->{rombar} && $d->{rombar} eq 'off' ? ",rombar=0" : "";
my $driver = $d->{driver} && $d->{driver} eq 'vfio' ? "vfio-pci" : "pci-assign";
my $xvga = $d->{'x-vga'} && $d->{'x-vga'} eq 'on' ? ",x-vga=on" : "";
+ if ($xvga && $xvga ne '') {
+ push @$cpuFlags, 'kvm=off';
+ $vga = 'none';
+ }
$driver = "vfio-pci" if $xvga ne '';
my $pcidevices = $d->{pciid};
my $multifunction = 1 if @$pcidevices > 1;
$spice_port = PVE::Tools::next_spice_port();
- push @$cmd, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
+ push @$devices, '-spice', "tls-port=${spice_port},addr=127.0.0.1,tls-ciphers=DES-CBC3-SHA,seamless-migration=on";
- push @$cmd, '-device', "virtio-serial,id=spice$pciaddr";
- push @$cmd, '-chardev', "spicevmc,id=vdagent,name=vdagent";
- push @$cmd, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
+ push @$devices, '-device', "virtio-serial,id=spice$pciaddr";
+ push @$devices, '-chardev', "spicevmc,id=vdagent,name=vdagent";
+ push @$devices, '-device', "virtserialport,chardev=vdagent,name=com.redhat.spice.0";
}
# enable balloon by default, unless explicitly disabled
for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++) {
my $d = parse_hostpci($conf->{"hostpci$i"});
next if !$d;
- my $info = pci_device_info("0000:$d->{pciid}");
- die "IOMMU not present\n" if !check_iommu_support();
- die "no pci device info for device '$d->{pciid}'\n" if !$info;
+ my $pcidevices = $d->{pciid};
+ foreach my $pcidevice (@$pcidevices) {
+ my $pciid = $pcidevice->{id}.".".$pcidevice->{function};
- if ($d->{driver} && $d->{driver} eq "vfio") {
- die "can't unbind/bind pci group to vfio '$d->{pciid}'\n" if !pci_dev_group_bind_to_vfio($d->{pciid});
- } else {
- die "can't unbind/bind to stub pci device '$d->{pciid}'\n" if !pci_dev_bind_to_stub($info);
- }
+ my $info = pci_device_info("0000:$pciid");
+ die "IOMMU not present\n" if !check_iommu_support();
+ die "no pci device info for device '$pciid'\n" if !$info;
- die "can't reset pci device '$d->{pciid}'\n" if !pci_dev_reset($info);
+ if ($d->{driver} && $d->{driver} eq "vfio") {
+ die "can't unbind/bind pci group to vfio '$pciid'\n" if !pci_dev_group_bind_to_vfio($pciid);
+ } else {
+ die "can't unbind/bind to stub pci device '$pciid'\n" if !pci_dev_bind_to_stub($info);
+ }
+
+ die "can't reset pci device '$pciid'\n" if $info->{has_fl_reset} and !pci_dev_reset($info);
+ }
}
PVE::Storage::activate_volumes($storecfg, $vollist);
vga1 => { bus => 0, addr => 24 },
vga2 => { bus => 0, addr => 25 },
vga3 => { bus => 0, addr => 26 },
+ hostpci2 => { bus => 0, addr => 27 },
+ hostpci3 => { bus => 0, addr => 28 },
#addr29 : usb-host (pve-usb.cfg)
'pci.1' => { bus => 0, addr => 30 },
'pci.2' => { bus => 0, addr => 31 },
die "snapshot '$snapname' does not exist\n" if !defined($snap);
# remove parent refs
- &$unlink_parent($conf, $snap->{parent});
- foreach my $sn (keys %{$conf->{snapshots}}) {
- next if $sn eq $snapname;
- &$unlink_parent($conf->{snapshots}->{$sn}, $snap->{parent});
+ if (!$prepare) {
+ &$unlink_parent($conf, $snap->{parent});
+ foreach my $sn (keys %{$conf->{snapshots}}) {
+ next if $sn eq $snapname;
+ &$unlink_parent($conf->{snapshots}->{$sn}, $snap->{parent});
+ }
}
if ($remove_drive) {
if (!$full) {
print "create linked clone of drive $drivename ($drive->{file})\n";
- $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid);
+ $newvolid = PVE::Storage::vdisk_clone($storecfg, $drive->{file}, $newvmid, $snapname);
push @$newvollist, $newvolid;
} else {
my ($storeid, $volname) = PVE::Storage::parse_volume_id($drive->{file});