]> git.proxmox.com Git - qemu-server.git/commitdiff
fix #1908: add vmgenid config/device
authorDominik Csapak <d.csapak@proxmox.com>
Wed, 19 Sep 2018 09:35:11 +0000 (11:35 +0200)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Wed, 19 Sep 2018 10:23:24 +0000 (12:23 +0200)
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@proxmox.com>
PVE/API2/Qemu.pm
PVE/CLI/qm.pm
PVE/QemuConfig.pm
PVE/QemuServer.pm

index c1cc01b4dc7a979b7323fed07db80d0d859ccd45..52f4a5fd518e0a1d630ff4966648a2a5d7357171 100644 (file)
@@ -599,6 +599,10 @@ __PACKAGE__->register_method({
                        $conf->{smbios1} = PVE::QemuServer::generate_smbios1_uuid();
                    }
 
+                   if (!defined($conf->{vmgenid}) || $conf->{vmgenid} eq '1') {
+                       $conf->{vmgenid} = PVE::QemuServer::generate_uuid();
+                   }
+
                    PVE::QemuConfig->write_config($vmid, $conf);
 
                };
@@ -1091,6 +1095,10 @@ my $update_vm_api  = sub {
            # add macaddr
            my $net = PVE::QemuServer::parse_net($param->{$opt});
            $param->{$opt} = PVE::QemuServer::print_net($net);
+       } elsif ($opt eq 'vmgenid') {
+           if ($param->{$opt} eq '1') {
+               $param->{$opt} = PVE::QemuServer::generate_uuid();
+           }
        }
     }
 
@@ -2725,13 +2733,15 @@ __PACKAGE__->register_method({
            }
 
             # auto generate a new uuid
-            my ($uuid, $uuid_str);
-            UUID::generate($uuid);
-            UUID::unparse($uuid, $uuid_str);
            my $smbios1 = PVE::QemuServer::parse_smbios1($newconf->{smbios1} || '');
-           $smbios1->{uuid} = $uuid_str;
+           $smbios1->{uuid} = PVE::QemuServer::generate_uuid();
            $newconf->{smbios1} = PVE::QemuServer::print_smbios1($smbios1);
 
+           # auto generate a new vmgenid if the option was set
+           if ($newconf->{vmgenid}) {
+               $newconf->{vmgenid} = PVE::QemuServer::generate_uuid();
+           }
+
            delete $newconf->{template};
 
            if ($param->{name}) {
index 84b8531cccf3fd14adf8490812568c158d8a7853..46a7e2fd5beb9f54ba7849512e7fc3a95c4dde8b 100755 (executable)
@@ -621,6 +621,7 @@ __PACKAGE__->register_method ({
 
            eval {
                # order matters, as do_import() will load_config() internally
+               $conf->{vmgenid} = PVE::QemuServer::generate_uuid();
                $conf->{smbios1} = PVE::QemuServer::generate_smbios1_uuid();
                PVE::QemuConfig->write_config($vmid, $conf);
 
index cd116bd46fd84790dca577554a6c5474f1a6a8ef..03b2a70c7860cffdc28aa393fbf8cec65606aba1 100644 (file)
@@ -300,6 +300,10 @@ sub __snapshot_rollback_hook {
            # in the original config.
            delete $conf->{machine} if $snap->{vmstate} && !defined($data->{oldmachine});
        }
+
+       if ($conf->{vmgenid}) {
+           $conf->{vmgenid} = PVE::QemuServer::generate_uuid();
+       }
     }
 
     return;
index af0631dcde0d42c54bef8ea28fb859d185350fcb..6785b027f29ae2ff6679e124f67049e7b8f58e69 100644 (file)
@@ -559,6 +559,13 @@ EODESCR
        description => "Select BIOS implementation.",
        default => 'seabios',
     },
+    vmgenid => {
+       type => 'string',
+       pattern => '(?:[a-fA-F0-9]{8}(?:-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12}|[01])',
+       format_description => 'UUID',
+        description => "Set VM Generation ID UUID. Use special value 1 to autogenerate one (API only). Use special value 0 to disable explicitly.",
+       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, '-device', 'vmgenid,guid='.$conf->{vmgenid};
+    }
+
     if ($conf->{bios} && $conf->{bios} eq 'ovmf') {
        die "uefi base image not found\n" if ! -f $OVMF_CODE;
 
@@ -5554,6 +5565,13 @@ sub restore_update_config_line {
        } else {
            print $outfd $line;
        }
+    } elsif (($line =~ m/^(vmgenid: )(.*)/)) {
+       # always generate a new vmgenid
+       my $vmgenid = $2;
+       if ($vmgenid ne '0') {
+           $vmgenid = generate_uuid();
+       }
+       print $outfd $1.$vmgenid."\n";
     } elsif (($line =~ m/^(smbios1: )(.*)/) && $unique) {
        my ($uuid, $uuid_str);
        UUID::generate($uuid);
@@ -6756,11 +6774,15 @@ sub resolve_first_disk {
     return $firstdisk;
 }
 
-sub generate_smbios1_uuid {
+sub generate_uuid {
     my ($uuid, $uuid_str);
     UUID::generate($uuid);
     UUID::unparse($uuid, $uuid_str);
-    return "uuid=$uuid_str";
+    return $uuid_str;
+}
+
+sub generate_smbios1_uuid {
+    return "uuid=".generate_uuid();
 }
 
 # bash completion helper