[pve-devel] [PATCH qemu-server] fix #1908: add vmgenid config/device
Dominik Csapak
d.csapak at proxmox.com
Tue Sep 18 10:19:11 CEST 2018
this adds a VM Generation ID device uses by Windows (Server) to determine
some specific actions that may have happened with the vm
such as rollback, restore, etc.
see:
https://docs.microsoft.com/en-us/windows/desktop/hyperv_v2/virtual-machine-generation-identifier
for details on how it works and when it should change
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
PVE/API2/Qemu.pm | 5 +++++
PVE/QemuConfig.pm | 4 ++++
PVE/QemuServer.pm | 23 +++++++++++++++++++++++
PVE/QemuServer/Makefile | 1 +
PVE/QemuServer/VMGenID.pm | 29 +++++++++++++++++++++++++++++
5 files changed, 62 insertions(+)
create mode 100644 PVE/QemuServer/VMGenID.pm
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index c1cc01b..6ac3110 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -2732,6 +2732,11 @@ __PACKAGE__->register_method({
$smbios1->{uuid} = $uuid_str;
$newconf->{smbios1} = PVE::QemuServer::print_smbios1($smbios1);
+ # auto generate a new vmgenid
+ if ($oldconf->{vmgenid}) {
+ $newconf->{vmgenid} = 'auto';
+ }
+
delete $newconf->{template};
if ($param->{name}) {
diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
index cd116bd..5a05c1b 100644
--- a/PVE/QemuConfig.pm
+++ b/PVE/QemuConfig.pm
@@ -300,6 +300,10 @@ sub __snapshot_rollback_hook {
# in the original config.
delete $conf->{machine} if $snap->{vmstate} && !defined($data->{oldmachine});
}
+
+ if (defined($conf->{vmgenid})) {
+ $conf->{vmgenid} = 'auto';
+ }
}
return;
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index af0631d..1b68ddd 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -34,6 +34,7 @@ use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr);
use PVE::QemuServer::Memory;
use PVE::QemuServer::USB qw(parse_usb_device);
use PVE::QemuServer::Cloudinit;
+use PVE::QemuServer::VMGenID;
use PVE::Systemd;
use Time::HiRes qw(gettimeofday);
use File::Copy qw(copy);
@@ -559,6 +560,12 @@ EODESCR
description => "Select BIOS implementation.",
default => 'seabios',
},
+ vmgenid => {
+ type => 'string',
+ pattern => '(?:auto)|(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12})',
+ description => "The VM Generation ID. Use the special value 'auto' to autogenerate one",
+ optional => 1,
+ },
};
my $confdesc_cloudinit = {
@@ -3191,6 +3198,10 @@ sub config_to_command {
push @$cmd, '-smbios', "type=1,$conf->{smbios1}";
}
+ if ($conf->{vmgenid}) {
+ push @$devices, PVE::QemuServer::VMGenID::create_device($conf->{vmgenid}, 0);
+ }
+
if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
die "uefi base image not found\n" if ! -f $OVMF_CODE;
@@ -4593,6 +4604,14 @@ sub vmconfig_apply_pending {
}
}
+sub vmconfig_apply_vmgenid_generation {
+ my ($vmid, $conf) = @_;
+ if ($conf->{vmgenid}) {
+ $conf->{vmgenid} = PVE::QemuServer::VMGenID::create_or_parse($conf->{vmgenid});
+ }
+ PVE::QemuConfig->write_config($vmid, $conf);
+}
+
my $safe_num_ne = sub {
my ($a, $b) = @_;
@@ -4779,6 +4798,8 @@ sub vm_start {
die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
+ vmconfig_apply_vmgenid_generation($vmid, $conf);
+
if (!$statefile && scalar(keys %{$conf->{pending}})) {
vmconfig_apply_pending($vmid, $conf, $storecfg);
$conf = PVE::QemuConfig->load_config($vmid); # update/reload
@@ -5554,6 +5575,8 @@ sub restore_update_config_line {
} else {
print $outfd $line;
}
+ } elsif (($line =~ m/^(vmgenid: )(.*)/)) {
+ print $outfd $1.'auto';
} elsif (($line =~ m/^(smbios1: )(.*)/) && $unique) {
my ($uuid, $uuid_str);
UUID::generate($uuid);
diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile
index afc39a3..06f359b 100644
--- a/PVE/QemuServer/Makefile
+++ b/PVE/QemuServer/Makefile
@@ -5,6 +5,7 @@ SOURCES=PCI.pm \
OVF.pm \
Cloudinit.pm \
Agent.pm \
+ VMGenID.pm \
.PHONY: install
install: ${SOURCES}
diff --git a/PVE/QemuServer/VMGenID.pm b/PVE/QemuServer/VMGenID.pm
new file mode 100644
index 0000000..c1aa3e4
--- /dev/null
+++ b/PVE/QemuServer/VMGenID.pm
@@ -0,0 +1,29 @@
+package PVE::QemuServer::VMGenID;
+
+use strict;
+use warnings;
+
+use UUID;
+
+sub create_device {
+ my ($uuid) = @_;
+
+ my $id = create_or_parse($uuid);
+
+ return ('-device', "vmgenid,guid=$id");
+}
+
+sub create_or_parse {
+ my ($uuid) = @_;
+
+ my $id;
+ if ($uuid eq 'auto') {
+ return UUID::uuid();
+ } elsif (UUID::parse($uuid, $id) == 0) {
+ return $uuid;
+ }
+
+ die "invalid VM Generation ID\n";
+}
+
+1;
--
2.11.0
More information about the pve-devel
mailing list