[pve-devel] avoiding VMID reuse

Lauri Tirkkonen lauri at tuxera.com
Mon Mar 12 15:13:59 CET 2018


Hi,

we'd like to keep VMIDs always unique per node, so that we can use zfs
for backups more easily (ie. avoid dataset name collisions; granted,
this still leaves room for collisions if disks are removed and added to
a VM). We've implemented the following (crappy) PoC that accomplishes
just this by storing the highest allocated VMID and returning that for
/cluster/nextid.

The patches are across four repositories, so I'm attaching four files
named by repository.
-------------- next part --------------
diff --git a/data/PVE/Cluster.pm b/data/PVE/Cluster.pm
index b49fd94..fea0639 100644
--- a/data/PVE/Cluster.pm
+++ b/data/PVE/Cluster.pm
@@ -996,6 +996,19 @@ sub log_msg {
    syslog("err", "writing cluster log failed: $@") if $@;
 }
 
+sub alloc_vmid {
+    my ($vmid) = @_;
+    check_vmid_unused($vmid);
+    open(my $fh, '+<', '/etc/pve/local/nextid');
+    my $next = 0 + readline($fh);
+    if ($vmid >= $next) {
+        $next = 1 + $vmid;
+        seek($fh, 0, 0);
+        print $fh "$next";
+    }
+    close($fh);
+}
+
 sub check_vmid_unused {
     my ($vmid, $noerr) = @_;
 
-------------- next part --------------
diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 733826e..9accfdb 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -337,6 +337,7 @@ __PACKAGE__->register_method({
 		die "Could not reserve ID $vmid, already taken\n" if $@;
 	    }
 
+	    PVE::Cluster::alloc_vmid($vmid);
 	    PVE::Cluster::check_cfs_quorum();
 	    my $vollist = [];
 
-------------- next part --------------
diff --git a/PVE/API2/Cluster.pm b/PVE/API2/Cluster.pm
index 7f38e61c..590f4fb7 100644
--- a/PVE/API2/Cluster.pm
+++ b/PVE/API2/Cluster.pm
@@ -505,11 +505,13 @@ __PACKAGE__->register_method({
 	    raise_param_exc({ vmid => "VM $vmid already exists" });
 	}
 
-	for (my $i = 100; $i < 10000; $i++) {
-	    return $i if !defined($idlist->{$i});
-	}
-
-	die "unable to get any free VMID\n";
+	open(my $fh, '<', '/etc/pve/local/nextid');
+	my $i = 0 + readline($fh);
+	close($fh);
+	if (defined($idlist->{$i})) {
+	    die "unable to get any free VMID\n";
+        }
+	return $i;
     }});
 
 1;
-------------- next part --------------
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 0174feb..358d539 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -558,6 +558,7 @@ __PACKAGE__->register_method({
 
 	    # test after locking
 	    PVE::Cluster::check_vmid_unused($vmid);
+	    PVE::Cluster::alloc_vmid($vmid);
 
 	    # ensure no old replication state are exists
 	    PVE::ReplicationState::delete_guest_states($vmid);


More information about the pve-devel mailing list