[pve-devel] [PATCH qemu-server 1/3] Refactor basic config-related methods

Fabian Grünbichler f.gruenbichler at proxmox.com
Mon Mar 7 12:41:12 CET 2016


Drop load_config, write_config, lock_config[_xx],
check_lock, check_protection, is_template and config_file
in favour of implementions in PVE::AbstractConfig.

Implement guest_type, __config_max_unused_disks,
config_file_lock and cfs_config_path from
PVE::AbstractConfig in PVE::QemuConfig.
---
 PVE/API2/Qemu.pm         | 127 ++++++++++++------------
 PVE/CLI/qm.pm            |  10 +-
 PVE/Makefile             |   3 +-
 PVE/QemuConfig.pm        |  46 +++++++++
 PVE/QemuMigrate.pm       |  16 ++--
 PVE/QemuServer.pm        | 244 ++++++++++++++++-------------------------------
 PVE/VZDump/QemuServer.pm |   4 +-
 pve-bridge               |   2 +-
 test/snapshot-test.pm    |  21 ++--
 9 files changed, 221 insertions(+), 252 deletions(-)
 create mode 100644 PVE/QemuConfig.pm

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 39deb07..e4956cb 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -13,6 +13,7 @@ use PVE::Exception qw(raise raise_param_exc raise_perm_exc);
 use PVE::Storage;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::RESTHandler;
+use PVE::QemuConfig;
 use PVE::QemuServer;
 use PVE::QemuMigrate;
 use PVE::RPCEnvironment;
@@ -205,14 +206,6 @@ my $check_vm_modify_config_perm = sub {
     return 1;
 };
 
-my $check_protection = sub {
-    my ($vm_conf, $err_msg) = @_;
-
-    if ($vm_conf->{protection}) {
-	die "$err_msg - protection mode enabled\n";
-    }
-};
-
 __PACKAGE__->register_method({
     name => 'vmlist',
     path => '',
@@ -339,7 +332,7 @@ __PACKAGE__->register_method({
 
 	my $pool = extract_param($param, 'pool');
 
-	my $filename = PVE::QemuServer::config_file($vmid);
+	my $filename = PVE::QemuConfig->config_file($vmid);
 
 	my $storecfg = PVE::Storage::config();
 
@@ -399,9 +392,9 @@ __PACKAGE__->register_method({
 	    if ($vmlist->{ids}->{$vmid}) {
 		my $current_node = $vmlist->{ids}->{$vmid}->{node};
 		if ($current_node eq $node) {
-		    my $conf = PVE::QemuServer::load_config($vmid);
+		    my $conf = PVE::QemuConfig->load_config($vmid);
 
-		    &$check_protection($conf, "unable to restore VM $vmid");
+		    PVE::QemuConfig->check_protection($conf, "unable to restore VM $vmid");
 
 		    die "unable to restore vm $vmid - config file already exists\n"
 			if !$force;
@@ -462,7 +455,7 @@ __PACKAGE__->register_method({
 			$conf->{smbios1} = "uuid=$uuid_str";
 		    }
 
-		    PVE::QemuServer::write_config($vmid, $conf);
+		    PVE::QemuConfig->write_config($vmid, $conf);
 
 		};
 		my $err = $@;
@@ -481,7 +474,7 @@ __PACKAGE__->register_method({
 	    return $rpcenv->fork_worker('qmcreate', $vmid, $authuser, $realcmd);
 	};
 
-	return PVE::QemuServer::lock_config_full($vmid, 1, $archive ? $restorefn : $createfn);
+	return PVE::QemuConfig->lock_config_full($vmid, 1, $archive ? $restorefn : $createfn);
     }});
 
 __PACKAGE__->register_method({
@@ -661,7 +654,7 @@ __PACKAGE__->register_method({
     code => sub {
 	my ($param) = @_;
 
-	my $conf = PVE::QemuServer::load_config($param->{vmid});
+	my $conf = PVE::QemuConfig->load_config($param->{vmid});
 
 	delete $conf->{snapshots};
 
@@ -732,7 +725,7 @@ __PACKAGE__->register_method({
     code => sub {
 	my ($param) = @_;
 
-	my $conf = PVE::QemuServer::load_config($param->{vmid});
+	my $conf = PVE::QemuConfig->load_config($param->{vmid});
 
 	my $pending_delete_hash = PVE::QemuServer::split_flagged_list($conf->{pending}->{delete});
 
@@ -871,12 +864,12 @@ my $update_vm_api  = sub {
 
     my $updatefn =  sub {
 
-	my $conf = PVE::QemuServer::load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	die "checksum missmatch (file change by other user?)\n"
 	    if $digest && $digest ne $conf->{digest};
 
-	PVE::QemuServer::check_lock($conf) if !$skiplock;
+	PVE::QemuConfig->check_lock($conf) if !$skiplock;
 
 	foreach my $opt (keys %$revert) {
 	    if (defined($conf->{$opt})) {
@@ -906,31 +899,31 @@ my $update_vm_api  = sub {
 
 	    foreach my $opt (@delete) {
 		$modified->{$opt} = 1;
-		$conf = PVE::QemuServer::load_config($vmid); # update/reload
+		$conf = PVE::QemuConfig->load_config($vmid); # update/reload
 		if ($opt =~ m/^unused/) {
 		    my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
-		    &$check_protection($conf, "can't remove unused disk '$drive->{file}'");
+		    PVE::QemuConfig->check_protection($conf, "can't remove unused disk '$drive->{file}'");
 		    $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
 		    if (PVE::QemuServer::try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser)) {
 			delete $conf->{$opt};
-			PVE::QemuServer::write_config($vmid, $conf);
+			PVE::QemuConfig->write_config($vmid, $conf);
 		    }
 		} elsif (PVE::QemuServer::is_valid_drivename($opt)) {
-		    &$check_protection($conf, "can't remove drive '$opt'");
+		    PVE::QemuConfig->check_protection($conf, "can't remove drive '$opt'");
 		    $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
 		    PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
 			if defined($conf->{pending}->{$opt});
 		    PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
-		    PVE::QemuServer::write_config($vmid, $conf);
+		    PVE::QemuConfig->write_config($vmid, $conf);
 		} else {
 		    PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
-		    PVE::QemuServer::write_config($vmid, $conf);
+		    PVE::QemuConfig->write_config($vmid, $conf);
 		}
 	    }
 
 	    foreach my $opt (keys %$param) { # add/change
 		$modified->{$opt} = 1;
-		$conf = PVE::QemuServer::load_config($vmid); # update/reload
+		$conf = PVE::QemuConfig->load_config($vmid); # update/reload
 		next if defined($conf->{pending}->{$opt}) && ($param->{$opt} eq $conf->{pending}->{$opt}); # skip if nothing changed
 
 		if (PVE::QemuServer::is_valid_drivename($opt)) {
@@ -948,13 +941,13 @@ my $update_vm_api  = sub {
 		    $conf->{pending}->{$opt} = $param->{$opt};
 		}
 		PVE::QemuServer::vmconfig_undelete_pending_option($conf, $opt);
-		PVE::QemuServer::write_config($vmid, $conf);
+		PVE::QemuConfig->write_config($vmid, $conf);
 	    }
 
 	    # remove pending changes when nothing changed
-	    $conf = PVE::QemuServer::load_config($vmid); # update/reload
+	    $conf = PVE::QemuConfig->load_config($vmid); # update/reload
 	    my $changes = PVE::QemuServer::vmconfig_cleanup_pending($conf);
-	    PVE::QemuServer::write_config($vmid, $conf) if $changes;
+	    PVE::QemuConfig->write_config($vmid, $conf) if $changes;
 
 	    return if !scalar(keys %{$conf->{pending}});
 
@@ -962,7 +955,7 @@ my $update_vm_api  = sub {
 
 	    # apply pending changes
 
-	    $conf = PVE::QemuServer::load_config($vmid); # update/reload
+	    $conf = PVE::QemuConfig->load_config($vmid); # update/reload
 
 	    if ($running) {
 		my $errors = {};
@@ -1008,7 +1001,7 @@ my $update_vm_api  = sub {
 	}
     };
 
-    return PVE::QemuServer::lock_config($vmid, $updatefn);
+    return PVE::QemuConfig->lock_config($vmid, $updatefn);
 };
 
 my $vm_config_perm_list = [
@@ -1161,11 +1154,11 @@ __PACKAGE__->register_method({
 	    if $skiplock && $authuser ne 'root at pam';
 
 	# test if VM exists
-	my $conf = PVE::QemuServer::load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	my $storecfg = PVE::Storage::config();
 
-	&$check_protection($conf, "can't remove VM $vmid");
+	PVE::QemuConfig->check_protection($conf, "can't remove VM $vmid");
 
 	die "unable to remove VM $vmid - used in HA resources\n"
 	    if PVE::HA::Config::vm_is_ha_managed($vmid);
@@ -1270,7 +1263,7 @@ __PACKAGE__->register_method({
 	my $node = $param->{node};
 	my $websocket = $param->{websocket};
 
-	my $conf = PVE::QemuServer::load_config($vmid, $node); # check if VM exists
+	my $conf = PVE::QemuConfig->load_config($vmid, $node); # check if VM exists
 
 	my $authpath = "/vms/$vmid";
 
@@ -1387,7 +1380,7 @@ __PACKAGE__->register_method({
 
 	PVE::AccessControl::verify_vnc_ticket($param->{vncticket}, $authuser, $authpath);
 
-	my $conf = PVE::QemuServer::load_config($vmid, $node); # VM exists ?
+	my $conf = PVE::QemuConfig->load_config($vmid, $node); # VM exists ?
 
 	# Note: VNC ports are acessible from outside, so we do not gain any
 	# security if we verify that $param->{port} belongs to VM $vmid. This
@@ -1428,7 +1421,7 @@ __PACKAGE__->register_method({
 	my $node = $param->{node};
 	my $proxy = $param->{proxy};
 
-	my $conf = PVE::QemuServer::load_config($vmid, $node);
+	my $conf = PVE::QemuConfig->load_config($vmid, $node);
 	my $title = "VM $vmid";
 	$title .= " - ". $conf->{name} if $conf->{name};
 
@@ -1473,7 +1466,7 @@ __PACKAGE__->register_method({
 	my ($param) = @_;
 
 	# test if VM exists
-	my $conf = PVE::QemuServer::load_config($param->{vmid});
+	my $conf = PVE::QemuConfig->load_config($param->{vmid});
 
 	my $res = [
 	    { subdir => 'current' },
@@ -1506,7 +1499,7 @@ __PACKAGE__->register_method({
 	my ($param) = @_;
 
 	# test if VM exists
-	my $conf = PVE::QemuServer::load_config($param->{vmid});
+	my $conf = PVE::QemuConfig->load_config($param->{vmid});
 
 	my $vmstatus = PVE::QemuServer::vmstatus($param->{vmid}, 1);
 	my $status = $vmstatus->{$param->{vmid}};
@@ -2039,7 +2032,7 @@ __PACKAGE__->register_method({
 
 	my $running = PVE::QemuServer::check_running($vmid);
 
-	my $conf = PVE::QemuServer::load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	if($snapname){
 	    my $snap = $conf->{snapshots}->{$snapname};
@@ -2188,9 +2181,9 @@ __PACKAGE__->register_method({
 	    # do all tests after lock
 	    # we also try to do all tests before we fork the worker
 
-	    my $conf = PVE::QemuServer::load_config($vmid);
+	    my $conf = PVE::QemuConfig->load_config($vmid);
 
-	    PVE::QemuServer::check_lock($conf);
+	    PVE::QemuConfig->check_lock($conf);
 
 	    my $verify_running = PVE::QemuServer::check_running($vmid) || 0;
 
@@ -2205,7 +2198,7 @@ __PACKAGE__->register_method({
 
 	    die "can't clone VM to node '$target' (VM uses local storage)\n" if $target && !$sharedvm;
 
-	    my $conffile = PVE::QemuServer::config_file($newid);
+	    my $conffile = PVE::QemuConfig->config_file($newid);
 
 	    die "unable to create VM $newid: config file already exists\n"
 		if -f $conffile;
@@ -2299,17 +2292,17 @@ __PACKAGE__->register_method({
 
 			$newconf->{$opt} = PVE::QemuServer::print_drive($vmid, $newdrive);
 
-			PVE::QemuServer::write_config($newid, $newconf);
+			PVE::QemuConfig->write_config($newid, $newconf);
 		    }
 
 		    delete $newconf->{lock};
-		    PVE::QemuServer::write_config($newid, $newconf);
+		    PVE::QemuConfig->write_config($newid, $newconf);
 
                     if ($target) {
 			# always deactivate volumes - avoid lvm LVs to be active on several nodes
 			PVE::Storage::deactivate_volumes($storecfg, $vollist, $snapname) if !$running;
 
-			my $newconffile = PVE::QemuServer::config_file($newid, $target);
+			my $newconffile = PVE::QemuConfig->config_file($newid, $target);
 			die "Failed to move config to node '$target' - rename failed: $!\n"
 			    if !rename($conffile, $newconffile);
 		    }
@@ -2336,9 +2329,9 @@ __PACKAGE__->register_method({
 	    return $rpcenv->fork_worker('qmclone', $vmid, $authuser, $realcmd);
 	};
 
-	return PVE::QemuServer::lock_config_mode($vmid, 1, $shared_lock, sub {
+	return PVE::QemuConfig->lock_config_mode($vmid, 1, $shared_lock, sub {
 	    # Aquire exclusive lock lock for $newid
-	    return PVE::QemuServer::lock_config_full($newid, 1, $clonefn);
+	    return PVE::QemuConfig->lock_config_full($newid, 1, $clonefn);
 	});
 
     }});
@@ -2420,7 +2413,7 @@ __PACKAGE__->register_method({
 
 	my $updatefn =  sub {
 
-	    my $conf = PVE::QemuServer::load_config($vmid);
+	    my $conf = PVE::QemuConfig->load_config($vmid);
 
 	    die "checksum missmatch (file change by other user?)\n"
 		if $digest && $digest ne $conf->{digest};
@@ -2462,7 +2455,7 @@ __PACKAGE__->register_method({
 
 		    PVE::QemuServer::add_unused_volume($conf, $old_volid) if !$param->{delete};
 
-		    PVE::QemuServer::write_config($vmid, $conf);
+		    PVE::QemuConfig->write_config($vmid, $conf);
 
 		    eval {
 			# try to deactivate volumes - avoid lvm LVs to be active on several nodes
@@ -2484,7 +2477,7 @@ __PACKAGE__->register_method({
                     if (PVE::QemuServer::is_volume_in_use($storecfg, $conf, undef, $old_volid)) {
 			warn "volume $old_volid still has snapshots, can't delete it\n";
 			PVE::QemuServer::add_unused_volume($conf, $old_volid);
-			PVE::QemuServer::write_config($vmid, $conf);
+			PVE::QemuConfig->write_config($vmid, $conf);
 		    } else {
 			eval { PVE::Storage::vdisk_free($storecfg, $old_volid); };
 			warn $@ if $@;
@@ -2495,7 +2488,7 @@ __PACKAGE__->register_method({
             return $rpcenv->fork_worker('qmmove', $vmid, $authuser, $realcmd);
 	};
 
-	return PVE::QemuServer::lock_config($vmid, $updatefn);
+	return PVE::QemuConfig->lock_config($vmid, $updatefn);
     }});
 
 __PACKAGE__->register_method({
@@ -2557,11 +2550,11 @@ __PACKAGE__->register_method({
 	    if $param->{force} && $authuser ne 'root at pam';
 
 	# test if VM exists
-	my $conf = PVE::QemuServer::load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	# try to detect errors early
 
-	PVE::QemuServer::check_lock($conf);
+	PVE::QemuConfig->check_lock($conf);
 
 	if (PVE::QemuServer::check_running($vmid)) {
 	    die "cant migrate running VM without --online\n"
@@ -2629,7 +2622,7 @@ __PACKAGE__->register_method({
 
 	my $vmid = $param->{vmid};
 
-	my $conf = PVE::QemuServer::load_config ($vmid); # check if VM exists
+	my $conf = PVE::QemuConfig->load_config ($vmid); # check if VM exists
 
 	my $res = '';
 	eval {
@@ -2700,11 +2693,11 @@ __PACKAGE__->register_method({
 
         my $updatefn =  sub {
 
-            my $conf = PVE::QemuServer::load_config($vmid);
+            my $conf = PVE::QemuConfig->load_config($vmid);
 
             die "checksum missmatch (file change by other user?)\n"
                 if $digest && $digest ne $conf->{digest};
-            PVE::QemuServer::check_lock($conf) if !$skiplock;
+            PVE::QemuConfig->check_lock($conf) if !$skiplock;
 
 	    die "disk '$disk' does not exist\n" if !$conf->{$disk};
 
@@ -2755,10 +2748,10 @@ __PACKAGE__->register_method({
 	    $drive->{size} = $newsize;
 	    $conf->{$disk} = PVE::QemuServer::print_drive($vmid, $drive);
 
-	    PVE::QemuServer::write_config($vmid, $conf);
+	    PVE::QemuConfig->write_config($vmid, $conf);
 	};
 
-        PVE::QemuServer::lock_config($vmid, $updatefn);
+        PVE::QemuConfig->lock_config($vmid, $updatefn);
         return undef;
     }});
 
@@ -2792,7 +2785,7 @@ __PACKAGE__->register_method({
 
 	my $vmid = $param->{vmid};
 
-	my $conf = PVE::QemuServer::load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 	my $snaphash = $conf->{snapshots} || {};
 
 	my $res = [];
@@ -2950,9 +2943,9 @@ __PACKAGE__->register_method({
 
 	my $updatefn =  sub {
 
-	    my $conf = PVE::QemuServer::load_config($vmid);
+	    my $conf = PVE::QemuConfig->load_config($vmid);
 
-	    PVE::QemuServer::check_lock($conf);
+	    PVE::QemuConfig->check_lock($conf);
 
 	    my $snap = $conf->{snapshots}->{$snapname};
 
@@ -2960,10 +2953,10 @@ __PACKAGE__->register_method({
 
 	    $snap->{description} = $param->{description} if defined($param->{description});
 
-	     PVE::QemuServer::write_config($vmid, $conf);
+	     PVE::QemuConfig->write_config($vmid, $conf);
 	};
 
-	PVE::QemuServer::lock_config($vmid, $updatefn);
+	PVE::QemuConfig->lock_config($vmid, $updatefn);
 
 	return undef;
     }});
@@ -2997,7 +2990,7 @@ __PACKAGE__->register_method({
 
 	my $snapname = extract_param($param, 'snapname');
 
-	my $conf = PVE::QemuServer::load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	my $snap = $conf->{snapshots}->{$snapname};
 
@@ -3138,15 +3131,15 @@ __PACKAGE__->register_method({
 
 	my $updatefn =  sub {
 
-	    my $conf = PVE::QemuServer::load_config($vmid);
+	    my $conf = PVE::QemuConfig->load_config($vmid);
 
-	    PVE::QemuServer::check_lock($conf);
+	    PVE::QemuConfig->check_lock($conf);
 
 	    die "unable to create template, because VM contains snapshots\n"
 		if $conf->{snapshots} && scalar(keys %{$conf->{snapshots}});
 
 	    die "you can't convert a template to a template\n"
-		if PVE::QemuServer::is_template($conf) && !$disk;
+		if PVE::QemuConfig->is_template($conf) && !$disk;
 
 	    die "you can't convert a VM to template if VM is running\n"
 		if PVE::QemuServer::check_running($vmid);
@@ -3156,12 +3149,12 @@ __PACKAGE__->register_method({
 	    };
 
 	    $conf->{template} = 1;
-	    PVE::QemuServer::write_config($vmid, $conf);
+	    PVE::QemuConfig->write_config($vmid, $conf);
 
 	    return $rpcenv->fork_worker('qmtemplate', $vmid, $authuser, $realcmd);
 	};
 
-	PVE::QemuServer::lock_config($vmid, $updatefn);
+	PVE::QemuConfig->lock_config($vmid, $updatefn);
 	return undef;
     }});
 
diff --git a/PVE/CLI/qm.pm b/PVE/CLI/qm.pm
index 0dd8159..676c5dc 100755
--- a/PVE/CLI/qm.pm
+++ b/PVE/CLI/qm.pm
@@ -117,7 +117,7 @@ __PACKAGE__->register_method ({
 	my ($param) = @_;
 
 	# test if VM exists
-	my $conf = PVE::QemuServer::load_config ($param->{vmid});
+	my $conf = PVE::QemuConfig->load_config ($param->{vmid});
 
 	my $vmstatus = PVE::QemuServer::vmstatus($param->{vmid}, 1);
 	my $stat = $vmstatus->{$param->{vmid}};
@@ -185,10 +185,10 @@ __PACKAGE__->register_method ({
 	my $vmid = $param->{vmid};
 
 	PVE::QemuServer::lock_config ($vmid, sub {
-	    my $conf = PVE::QemuServer::load_config($vmid);
+	    my $conf = PVE::QemuConfig->load_config($vmid);
 	    delete $conf->{lock};
 	    delete $conf->{pending}->{lock} if $conf->{pending}; # just to be sure
-	    PVE::QemuServer::write_config($vmid, $conf);
+	    PVE::QemuConfig->write_config($vmid, $conf);
 	});
 
 	return undef;
@@ -280,7 +280,7 @@ __PACKAGE__->register_method ({
 
 	my $vmid = $param->{vmid};
 
-	my $conf = PVE::QemuServer::load_config ($vmid); # check if VM exists
+	my $conf = PVE::QemuConfig->load_config ($vmid); # check if VM exists
 
 	print "Entering Qemu Monitor for VM $vmid - type 'help' for help\n";
 
@@ -350,7 +350,7 @@ __PACKAGE__->register_method ({
 
 	my $vmid = $param->{vmid};
 
-	my $conf = PVE::QemuServer::load_config ($vmid); # check if VM exists
+	my $conf = PVE::QemuConfig->load_config ($vmid); # check if VM exists
 
 	my $iface = $param->{iface};
 
diff --git a/PVE/Makefile b/PVE/Makefile
index 3cda4dd..fc880d8 100644
--- a/PVE/Makefile
+++ b/PVE/Makefile
@@ -1,7 +1,8 @@
 PERLSOURCE = 			\
 	QemuServer.pm		\
 	QemuMigrate.pm		\
-	QMPClient.pm
+	QMPClient.pm		\
+	QemuConfig.pm
 
 .PHONY: install
 install:
diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
new file mode 100644
index 0000000..219f3c3
--- /dev/null
+++ b/PVE/QemuConfig.pm
@@ -0,0 +1,46 @@
+package PVE::QemuConfig;
+
+use strict;
+use warnings;
+
+use base qw(PVE::AbstractConfig);
+
+my $nodename = PVE::INotify::nodename();
+
+mkdir "/etc/pve/nodes/$nodename";
+my $confdir = "/etc/pve/nodes/$nodename/qemu-server";
+mkdir $confdir;
+
+my $lock_dir = "/var/lock/qemu-server";
+mkdir $lock_dir;
+
+my $MAX_UNUSED_DISKS = 8;
+
+# BEGIN implemented abstract methods from PVE::AbstractConfig
+
+sub guest_type {
+    return "VM";
+}
+
+sub __config_max_unused_disks {
+    my ($class) =@_;
+
+    return $MAX_UNUSED_DISKS;
+}
+
+sub config_file_lock {
+    my ($class, $vmid) = @_;
+
+    return "$lock_dir/lock-$vmid.conf";
+}
+
+sub cfs_config_path {
+    my ($class, $vmid, $node) = @_;
+
+    $node = $nodename if !$node;
+    return "nodes/$node/qemu-server/$vmid.conf";
+}
+
+# END implemented abstract methods from PVE::AbstractConfig
+
+1;
diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
index 973b6ee..6c734ca 100644
--- a/PVE/QemuMigrate.pm
+++ b/PVE/QemuMigrate.pm
@@ -122,7 +122,7 @@ sub finish_tunnel {
 sub lock_vm {
     my ($self, $vmid, $code, @param) = @_;
 
-    return PVE::QemuServer::lock_config($vmid, $code, @param);
+    return PVE::QemuConfig->lock_config($vmid, $code, @param);
 }
 
 sub prepare {
@@ -133,9 +133,9 @@ sub prepare {
     $self->{storecfg} = PVE::Storage::config();
 
     # test is VM exist
-    my $conf = $self->{vmconf} = PVE::QemuServer::load_config($vmid);
+    my $conf = $self->{vmconf} = PVE::QemuConfig->load_config($vmid);
 
-    PVE::QemuServer::check_lock($conf);
+    PVE::QemuConfig->check_lock($conf);
 
     my $running = 0;
     if (my $pid = PVE::QemuServer::check_running($vmid)) {
@@ -277,7 +277,7 @@ sub phase1 {
 
     # set migrate lock in config file
     $conf->{lock} = 'migrate';
-    PVE::QemuServer::write_config($vmid, $conf);
+    PVE::QemuConfig->write_config($vmid, $conf);
 
     sync_disks($self, $vmid);
 
@@ -290,7 +290,7 @@ sub phase1_cleanup {
 
     my $conf = $self->{vmconf};
     delete $conf->{lock};
-    eval { PVE::QemuServer::write_config($vmid, $conf) };
+    eval { PVE::QemuConfig->write_config($vmid, $conf) };
     if (my $err = $@) {
 	$self->log('err', $err);
     }
@@ -546,7 +546,7 @@ sub phase2_cleanup {
 
     my $conf = $self->{vmconf};
     delete $conf->{lock};
-    eval { PVE::QemuServer::write_config($vmid, $conf) };
+    eval { PVE::QemuConfig->write_config($vmid, $conf) };
     if (my $err = $@) {
         $self->log('err', $err);
     }
@@ -594,8 +594,8 @@ sub phase3_cleanup {
     return if $self->{phase2errors};
 
     # move config to remote node
-    my $conffile = PVE::QemuServer::config_file($vmid);
-    my $newconffile = PVE::QemuServer::config_file($vmid, $self->{node});
+    my $conffile = PVE::QemuConfig->config_file($vmid);
+    my $newconffile = PVE::QemuConfig->config_file($vmid, $self->{node});
 
     die "Failed to move config to node '$self->{node}' - rename failed: $!\n"
         if !rename($conffile, $newconffile);
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 17b43d2..d68872b 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -27,6 +27,7 @@ use PVE::JSONSchema qw(get_standard_option);
 use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
 use PVE::INotify;
 use PVE::ProcFSTools;
+use PVE::QemuConfig;
 use PVE::QMPClient;
 use PVE::RPCEnvironment;
 use Time::HiRes qw(gettimeofday);
@@ -1891,43 +1892,6 @@ sub check_type {
     }
 }
 
-sub lock_config_full {
-    my ($vmid, $timeout, $code, @param) = @_;
-
-    my $filename = config_file_lock($vmid);
-
-    my $res = lock_file($filename, $timeout, $code, @param);
-
-    die $@ if $@;
-
-    return $res;
-}
-
-sub lock_config_mode {
-    my ($vmid, $timeout, $shared, $code, @param) = @_;
-
-    my $filename = config_file_lock($vmid);
-
-    my $res = lock_file_full($filename, $timeout, $shared, $code, @param);
-
-    die $@ if $@;
-
-    return $res;
-}
-
-sub lock_config {
-    my ($vmid, $code, @param) = @_;
-
-    return lock_config_full($vmid, 10, $code, @param);
-}
-
-sub cfs_config_path {
-    my ($vmid, $node) = @_;
-
-    $node = $nodename if !$node;
-    return "nodes/$node/qemu-server/$vmid.conf";
-}
-
 sub check_iommu_support{
     #fixme : need to check IOMMU support
     #http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM
@@ -1937,34 +1901,21 @@ sub check_iommu_support{
 
 }
 
-sub config_file {
-    my ($vmid, $node) = @_;
-
-    my $cfspath = cfs_config_path($vmid, $node);
-    return "/etc/pve/$cfspath";
-}
-
-sub config_file_lock {
-    my ($vmid) = @_;
-
-    return "$lock_dir/lock-$vmid.conf";
-}
-
 sub touch_config {
     my ($vmid) = @_;
 
-    my $conf = config_file($vmid);
+    my $conf = PVE::QemuConfig->config_file($vmid);
     utime undef, undef, $conf;
 }
 
 sub destroy_vm {
     my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
 
-    my $conffile = config_file($vmid);
+    my $conffile = PVE::QemuConfig->config_file($vmid);
 
-    my $conf = load_config($vmid);
+    my $conf = PVE::QemuConfig->load_config($vmid);
 
-    check_lock($conf) if !$skiplock;
+    PVE::QemuConfig->check_lock($conf) if !$skiplock;
 
     # only remove disks owned by this VM
     foreach_drive($conf, sub {
@@ -2004,18 +1955,6 @@ sub destroy_vm {
     warn $@ if $@;
 }
 
-sub load_config {
-    my ($vmid, $node) = @_;
-
-    my $cfspath = cfs_config_path($vmid, $node);
-
-    my $conf = PVE::Cluster::cfs_read_file($cfspath);
-
-    die "no such VM ('$vmid')\n" if !defined($conf);
-
-    return $conf;
-}
-
 sub parse_vm_config {
     my ($filename, $raw) = @_;
 
@@ -2222,14 +2161,6 @@ sub write_vm_config {
     return $raw;
 }
 
-sub write_config {
-    my ($vmid, $conf) = @_;
-
-    my $cfspath = cfs_config_path($vmid);
-
-    PVE::Cluster::cfs_write_file($cfspath, $conf);
-}
-
 sub load_defaults {
 
     my $res = {};
@@ -2336,12 +2267,6 @@ sub shared_nodes {
     return $nodehash
 }
 
-sub check_lock {
-    my ($conf) = @_;
-
-    die "VM is locked ($conf->{lock})\n" if $conf->{lock};
-}
-
 sub check_cmdline {
     my ($pidfile, $pid) = @_;
 
@@ -2371,7 +2296,7 @@ sub check_cmdline {
 sub check_running {
     my ($vmid, $nocheck, $node) = @_;
 
-    my $filename = config_file($vmid, $node);
+    my $filename = PVE::QemuConfig->config_file($vmid, $node);
 
     die "unable to find configuration file for VM $vmid - no such machine\n"
 	if !$nocheck && ! -f $filename;
@@ -2459,7 +2384,7 @@ sub vmstatus {
     foreach my $vmid (keys %$list) {
 	next if $opt_vmid && ($vmid ne $opt_vmid);
 
-	my $cfspath = cfs_config_path($vmid);
+	my $cfspath = PVE::QemuConfig->cfs_config_path($vmid);
 	my $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
 
 	my $d = {};
@@ -2499,7 +2424,7 @@ sub vmstatus {
 	$d->{diskread} = 0;
 	$d->{diskwrite} = 0;
 
-        $d->{template} = is_template($conf);
+        $d->{template} = PVE::QemuConfig->is_template($conf);
 
 	$res->{$vmid} = $d;
     }
@@ -3196,7 +3121,7 @@ sub config_to_command {
 	    #if dimm_memory is not aligned to dimm map
 	    if($current_size > $memory) {
 	         $conf->{memory} = $current_size;
-	         write_config($vmid, $conf);
+	         PVE::QemuConfig->write_config($vmid, $conf);
 	    }
 	});
     }
@@ -3853,7 +3778,7 @@ sub qemu_memory_hotplug {
 		}
 		#update conf after each succesful module hotplug
 		$conf->{memory} = $current_size;
-		write_config($vmid, $conf);
+		PVE::QemuConfig->write_config($vmid, $conf);
 	});
 
     } else {
@@ -3878,7 +3803,7 @@ sub qemu_memory_hotplug {
 		$conf->{memory} = $current_size;
 
 		eval { qemu_objectdel($vmid, "mem-$name"); };
-		write_config($vmid, $conf);
+		PVE::QemuConfig->write_config($vmid, $conf);
 	});
     }
 }
@@ -4131,8 +4056,8 @@ sub vmconfig_hotplug_pending {
     }
 
     if ($changes) {
-	write_config($vmid, $conf);
-	$conf = load_config($vmid); # update/reload
+	PVE::QemuConfig->write_config($vmid, $conf);
+	$conf = PVE::QemuConfig->load_config($vmid); # update/reload
     }
 
     my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
@@ -4182,8 +4107,8 @@ sub vmconfig_hotplug_pending {
 	    # save new config if hotplug was successful
 	    delete $conf->{$opt};
 	    vmconfig_undelete_pending_option($conf, $opt);
-	    write_config($vmid, $conf);
-	    $conf = load_config($vmid); # update/reload
+	    PVE::QemuConfig->write_config($vmid, $conf);
+	    $conf = PVE::QemuConfig->load_config($vmid); # update/reload
 	}
     }
 
@@ -4240,8 +4165,8 @@ sub vmconfig_hotplug_pending {
 	    # save new config if hotplug was successful
 	    $conf->{$opt} = $value;
 	    delete $conf->{pending}->{$opt};
-	    write_config($vmid, $conf);
-	    $conf = load_config($vmid); # update/reload
+	    PVE::QemuConfig->write_config($vmid, $conf);
+	    $conf = PVE::QemuConfig->load_config($vmid); # update/reload
 	}
     }
 }
@@ -4293,26 +4218,26 @@ sub vmconfig_apply_pending {
     my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
     while (my ($opt, $force) = each %$pending_delete_hash) {
 	die "internal error" if $opt =~ m/^unused/;
-	$conf = load_config($vmid); # update/reload
+	$conf = PVE::QemuConfig->load_config($vmid); # update/reload
 	if (!defined($conf->{$opt})) {
 	    vmconfig_undelete_pending_option($conf, $opt);
-	    write_config($vmid, $conf);
+	    PVE::QemuConfig->write_config($vmid, $conf);
 	} elsif (is_valid_drivename($opt)) {
 	    vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
 	    vmconfig_undelete_pending_option($conf, $opt);
 	    delete $conf->{$opt};
-	    write_config($vmid, $conf);
+	    PVE::QemuConfig->write_config($vmid, $conf);
 	} else {
 	    vmconfig_undelete_pending_option($conf, $opt);
 	    delete $conf->{$opt};
-	    write_config($vmid, $conf);
+	    PVE::QemuConfig->write_config($vmid, $conf);
 	}
     }
 
-    $conf = load_config($vmid); # update/reload
+    $conf = PVE::QemuConfig->load_config($vmid); # update/reload
 
     foreach my $opt (keys %{$conf->{pending}}) { # add/change
-	$conf = load_config($vmid); # update/reload
+	$conf = PVE::QemuConfig->load_config($vmid); # update/reload
 
 	if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
 	    # skip if nothing changed
@@ -4325,7 +4250,7 @@ sub vmconfig_apply_pending {
 	}
 
 	delete $conf->{pending}->{$opt};
-	write_config($vmid, $conf);
+	PVE::QemuConfig->write_config($vmid, $conf);
     }
 }
 
@@ -4491,18 +4416,18 @@ sub vm_start {
     my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
 	$forcemachine, $spice_ticket) = @_;
 
-    lock_config($vmid, sub {
-	my $conf = load_config($vmid, $migratedfrom);
+    PVE::QemuConfig->lock_config($vmid, sub {
+	my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
 
-	die "you can't start a vm if it's a template\n" if is_template($conf);
+	die "you can't start a vm if it's a template\n" if PVE::QemuConfig->is_template($conf);
 
-	check_lock($conf) if !$skiplock;
+	PVE::QemuConfig->check_lock($conf) if !$skiplock;
 
 	die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
 
 	if (!$statefile && scalar(keys %{$conf->{pending}})) {
 	    vmconfig_apply_pending($vmid, $conf, $storecfg);
-	    $conf = load_config($vmid); # update/reload
+	    $conf = PVE::QemuConfig->load_config($vmid); # update/reload
 	}
 
 	my $defaults = load_defaults();
@@ -4670,7 +4595,7 @@ sub vm_human_monitor_command {
 sub vm_commandline {
     my ($storecfg, $vmid) = @_;
 
-    my $conf = load_config($vmid);
+    my $conf = PVE::QemuConfig->load_config($vmid);
 
     my $defaults = load_defaults();
 
@@ -4682,11 +4607,11 @@ sub vm_commandline {
 sub vm_reset {
     my ($vmid, $skiplock) = @_;
 
-    lock_config($vmid, sub {
+    PVE::QemuConfig->lock_config($vmid, sub {
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
-	check_lock($conf) if !$skiplock;
+	PVE::QemuConfig->check_lock($conf) if !$skiplock;
 
 	vm_mon_cmd($vmid, "system_reset");
     });
@@ -4740,20 +4665,20 @@ sub vm_stop {
     if ($migratedfrom){
 	my $pid = check_running($vmid, $nocheck, $migratedfrom);
 	kill 15, $pid if $pid;
-	my $conf = load_config($vmid, $migratedfrom);
+	my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
 	vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 0);
 	return;
     }
 
-    lock_config($vmid, sub {
+    PVE::QemuConfig->lock_config($vmid, sub {
 
 	my $pid = check_running($vmid, $nocheck);
 	return if !$pid;
 
 	my $conf;
 	if (!$nocheck) {
-	    $conf = load_config($vmid);
-	    check_lock($conf) if !$skiplock;
+	    $conf = PVE::QemuConfig->load_config($vmid);
+	    PVE::QemuConfig->check_lock($conf) if !$skiplock;
 	    if (!defined($timeout) && $shutdown && $conf->{startup}) {
 		my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup});
 		$timeout = $opts->{down} if $opts->{down};
@@ -4824,11 +4749,11 @@ sub vm_stop {
 sub vm_suspend {
     my ($vmid, $skiplock) = @_;
 
-    lock_config($vmid, sub {
+    PVE::QemuConfig->lock_config($vmid, sub {
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
-	check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
+	PVE::QemuConfig->check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
 
 	vm_mon_cmd($vmid, "stop");
     });
@@ -4837,13 +4762,13 @@ sub vm_suspend {
 sub vm_resume {
     my ($vmid, $skiplock, $nocheck) = @_;
 
-    lock_config($vmid, sub {
+    PVE::QemuConfig->lock_config($vmid, sub {
 
 	if (!$nocheck) {
 
-	    my $conf = load_config($vmid);
+	    my $conf = PVE::QemuConfig->load_config($vmid);
 
-	    check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
+	    PVE::QemuConfig->check_lock($conf) if !($skiplock || ($conf->{lock} && $conf->{lock} eq 'backup'));
 
 	    vm_mon_cmd($vmid, "cont");
 
@@ -4856,9 +4781,9 @@ sub vm_resume {
 sub vm_sendkey {
     my ($vmid, $skiplock, $key) = @_;
 
-    lock_config($vmid, sub {
+    PVE::QemuConfig->lock_config($vmid, sub {
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	# there is no qmp command, so we use the human monitor command
 	vm_human_monitor_command($vmid, "sendkey $key");
@@ -4868,9 +4793,9 @@ sub vm_sendkey {
 sub vm_destroy {
     my ($storecfg, $vmid, $skiplock) = @_;
 
-    lock_config($vmid, sub {
+    PVE::QemuConfig->lock_config($vmid, sub {
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	if (!check_running($vmid)) {
 	    destroy_vm($storecfg, $vmid, undef, $skiplock);
@@ -5397,9 +5322,9 @@ sub rescan {
     my $updatefn =  sub {
 	my ($vmid) = @_;
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
-	check_lock($conf);
+	PVE::QemuConfig->check_lock($conf);
 
 	my $vm_volids = {};
 	foreach my $volid (keys %$volid_hash) {
@@ -5409,14 +5334,14 @@ sub rescan {
 
 	my $changes = update_disksize($vmid, $conf, $vm_volids);
 
-	write_config($vmid, $conf) if $changes;
+	PVE::QemuConfig->write_config($vmid, $conf) if $changes;
     };
 
     if (defined($vmid)) {
 	if ($nolock) {
 	    &$updatefn($vmid);
 	} else {
-	    lock_config($vmid, $updatefn, $vmid);
+	    PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
 	}
     } else {
 	my $vmlist = config_list();
@@ -5424,7 +5349,7 @@ sub rescan {
 	    if ($nolock) {
 		&$updatefn($vmid);
 	    } else {
-		lock_config($vmid, $updatefn, $vmid);
+		PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
 	    }
 	}
     }
@@ -5475,11 +5400,12 @@ sub restore_vma_archive {
 
     my $rpcenv = PVE::RPCEnvironment::get();
 
-    my $conffile = config_file($vmid);
+    my $conffile = PVE::QemuConfig->config_file($vmid);
     my $tmpfn = "$conffile.$$.tmp";
 
     # Note: $oldconf is undef if VM does not exists
-    my $oldconf = PVE::Cluster::cfs_read_file(cfs_config_path($vmid));
+    my $cfs_path = PVE::QemuConfig->cfs_config_path($vmid);
+    my $oldconf = PVE::Cluster::cfs_read_file($cfs_path);
 
     my $print_devmap = sub {
 	my $virtdev_hash = {};
@@ -5701,7 +5627,7 @@ sub restore_tar_archive {
     my $storecfg = cfs_read_file('storage.cfg');
 
     # destroy existing data - keep empty config
-    my $vmcfgfn = config_file($vmid);
+    my $vmcfgfn = PVE::QemuConfig->config_file($vmid);
     destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
 
     my $tocmd = "/usr/lib/qemu-server/qmextract";
@@ -5723,7 +5649,7 @@ sub restore_tar_archive {
     local $ENV{VZDUMP_VMID} = $vmid;
     local $ENV{VZDUMP_USER} = $user;
 
-    my $conffile = config_file($vmid);
+    my $conffile = PVE::QemuConfig->config_file($vmid);
     my $tmpfn = "$conffile.$$.tmp";
 
     # disable interrupts (always do cleanups)
@@ -5925,12 +5851,12 @@ sub snapshot_prepare {
 
     my $updatefn =  sub {
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	die "you can't take a snapshot if it's a template\n"
-	    if is_template($conf);
+	    if PVE::QemuConfig->is_template($conf);
 
-	check_lock($conf);
+	PVE::QemuConfig->check_lock($conf);
 
 	$conf->{lock} = 'snapshot';
 
@@ -5953,10 +5879,10 @@ sub snapshot_prepare {
 	$snap->{snaptime} = time();
 	$snap->{description} = $comment if $comment;
 
-	write_config($vmid, $conf);
+	PVE::QemuConfig->write_config($vmid, $conf);
     };
 
-    lock_config($vmid, $updatefn);
+    PVE::QemuConfig->lock_config($vmid, $updatefn);
 
     return $snap;
 }
@@ -5966,7 +5892,7 @@ sub snapshot_commit {
 
     my $updatefn = sub {
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	die "missing snapshot lock\n"
 	    if !($conf->{lock} && $conf->{lock} eq 'snapshot');
@@ -5983,10 +5909,10 @@ sub snapshot_commit {
 
 	$conf->{parent} = $snapname;
 
-	write_config($vmid, $conf);
+	PVE::QemuConfig->write_config($vmid, $conf);
     };
 
-    lock_config($vmid, $updatefn);
+    PVE::QemuConfig->lock_config($vmid, $updatefn);
 }
 
 sub snapshot_rollback {
@@ -5996,11 +5922,11 @@ sub snapshot_rollback {
 
     my $storecfg = PVE::Storage::config();
 
-    my $conf = load_config($vmid);
+    my $conf = PVE::QemuConfig->load_config($vmid);
 
     my $get_snapshot_config = sub {
 
-	die "you can't rollback if vm is a template\n" if is_template($conf);
+	die "you can't rollback if vm is a template\n" if PVE::QemuConfig->is_template($conf);
 
 	my $res = $conf->{snapshots}->{$snapname};
 
@@ -6023,7 +5949,7 @@ sub snapshot_rollback {
 
     my $updatefn = sub {
 
-	$conf = load_config($vmid);
+	$conf = PVE::QemuConfig->load_config($vmid);
 
 	$snap = &$get_snapshot_config();
 
@@ -6031,7 +5957,7 @@ sub snapshot_rollback {
 	    if $snap->{snapstate};
 
 	if ($prepare) {
-	    check_lock($conf);
+	    PVE::QemuConfig->check_lock($conf);
 	    vm_stop($storecfg, $vmid, undef, undef, 5, undef, undef);
 	}
 
@@ -6062,7 +5988,7 @@ sub snapshot_rollback {
 	    delete $conf->{machine} if $snap->{vmstate} && !$has_machine_config;
 	}
 
-	write_config($vmid, $conf);
+	PVE::QemuConfig->write_config($vmid, $conf);
 
 	if (!$prepare && $snap->{vmstate}) {
 	    my $statefile = PVE::Storage::path($storecfg, $snap->{vmstate});
@@ -6070,7 +5996,7 @@ sub snapshot_rollback {
 	}
     };
 
-    lock_config($vmid, $updatefn);
+    PVE::QemuConfig->lock_config($vmid, $updatefn);
 
     foreach_drive($snap, sub {
 	my ($ds, $drive) = @_;
@@ -6084,7 +6010,7 @@ sub snapshot_rollback {
     });
 
     $prepare = 0;
-    lock_config($vmid, $updatefn);
+    PVE::QemuConfig->lock_config($vmid, $updatefn);
 }
 
 my $savevm_wait = sub {
@@ -6151,7 +6077,7 @@ sub snapshot_create {
 
     $save_vmstate = 0 if !$snap->{vmstate}; # vm is not running
 
-    my $config = load_config($vmid);
+    my $config = PVE::QemuConfig->load_config($vmid);
 
     my ($running, $freezefs) = check_freeze_needed($vmid, $config, $snap->{vmstate});
 
@@ -6247,12 +6173,12 @@ sub snapshot_delete {
     my $updatefn =  sub {
 	my ($remove_drive) = @_;
 
-	my $conf = load_config($vmid);
+	my $conf = PVE::QemuConfig->load_config($vmid);
 
 	if (!$drivehash) {
-	    check_lock($conf);
+	    PVE::QemuConfig->check_lock($conf);
 	    die "you can't delete a snapshot if vm is a template\n"
-		if is_template($conf);
+		if PVE::QemuConfig->is_template($conf);
 	}
 
 	$snap = $conf->{snapshots}->{$snapname};
@@ -6289,10 +6215,10 @@ sub snapshot_delete {
 	    }
 	}
 
-	write_config($vmid, $conf);
+	PVE::QemuConfig->write_config($vmid, $conf);
     };
 
-    lock_config($vmid, $updatefn);
+    PVE::QemuConfig->lock_config($vmid, $updatefn);
 
     # now remove vmstate file
 
@@ -6305,7 +6231,7 @@ sub snapshot_delete {
 	    warn $err;
 	}
 	# save changes (remove vmstate from snapshot)
-	lock_config($vmid, $updatefn, 'vmstate') if !$force;
+	PVE::QemuConfig->lock_config($vmid, $updatefn, 'vmstate') if !$force;
     };
 
     # now remove all internal snapshots
@@ -6326,13 +6252,13 @@ sub snapshot_delete {
 	}
 
 	# save changes (remove drive fron snapshot)
-	lock_config($vmid, $updatefn, $ds) if !$force;
+	PVE::QemuConfig->lock_config($vmid, $updatefn, $ds) if !$force;
 	push @$unused, $volid;
     });
 
     # now cleanup config
     $prepare = 0;
-    lock_config($vmid, $updatefn);
+    PVE::QemuConfig->lock_config($vmid, $updatefn);
 }
 
 sub has_feature {
@@ -6368,16 +6294,10 @@ sub template_create {
 	my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
 	$drive->{file} = $voliddst;
 	$conf->{$ds} = print_drive($vmid, $drive);
-	write_config($vmid, $conf);
+	PVE::QemuConfig->write_config($vmid, $conf);
     });
 }
 
-sub is_template {
-    my ($conf) = @_;
-
-    return 1 if defined $conf->{template} && $conf->{template} == 1;
-}
-
 sub qemu_img_convert {
     my ($src_volid, $dst_volid, $size, $snapname) = @_;
 
diff --git a/PVE/VZDump/QemuServer.pm b/PVE/VZDump/QemuServer.pm
index 1636639..4309e0b 100644
--- a/PVE/VZDump/QemuServer.pm
+++ b/PVE/VZDump/QemuServer.pm
@@ -46,7 +46,7 @@ sub prepare {
 
     $task->{disks} = [];
 
-    my $conf = $self->{vmlist}->{$vmid} = PVE::QemuServer::load_config($vmid);
+    my $conf = $self->{vmlist}->{$vmid} = PVE::QemuConfig->load_config($vmid);
 
     $self->{vm_was_running} = 1;
     if (!PVE::QemuServer::check_running($vmid)) {
@@ -230,7 +230,7 @@ sub archive {
 
     my $diskcount = scalar(@{$task->{disks}});
 
-    if (PVE::QemuServer::is_template($self->{vmlist}->{$vmid}) || !$diskcount) {
+    if (PVE::QemuConfig->is_template($self->{vmlist}->{$vmid}) || !$diskcount) {
 	my @pathlist;
 	foreach my $di (@{$task->{disks}}) {
 	    if ($di->{type} eq 'block' || $di->{type} eq 'file') {
diff --git a/pve-bridge b/pve-bridge
index 4426c65..b1d40f8 100755
--- a/pve-bridge
+++ b/pve-bridge
@@ -24,7 +24,7 @@ my $netid = "net$2";
 
 my $migratedfrom = $hotplug ? undef : $ENV{PVE_MIGRATED_FROM};
 
-my $conf = PVE::QemuServer::load_config($vmid, $migratedfrom);
+my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
 
 my $netconf = $conf->{$netid};
 
diff --git a/test/snapshot-test.pm b/test/snapshot-test.pm
index 4dc2897..70355fd 100644
--- a/test/snapshot-test.pm
+++ b/test/snapshot-test.pm
@@ -8,6 +8,7 @@ use lib qw(..);
 use PVE::Storage;
 use PVE::Storage::Plugin;
 use PVE::QemuServer;
+use PVE::QemuConfig;
 use PVE::Tools;
 
 use Test::MockModule;
@@ -223,22 +224,22 @@ sub testcase_rollback {
     };
 }
 
-# BEGIN redefine PVE::QemuServer methods 
+# BEGIN mocked PVE::QemuConfig methods
 sub config_file_lock {
     return "snapshot-working/pve-test.lock";
 }
 
 sub cfs_config_path {
-    my ($vmid, $node) = @_;
+    my ($class, $vmid, $node) = @_;
 
     $node = $nodename if !$node;
     return "snapshot-working/$node/qemu-server/$vmid.conf";
 }
 
 sub load_config {
-    my ($vmid, $node) = @_;
+    my ($class, $vmid, $node) = @_;
 
-    my $filename = cfs_config_path($vmid, $node);
+    my $filename = $class->cfs_config_path($vmid, $node);
 
     my $raw = PVE::Tools::file_get_contents($filename);
 
@@ -247,9 +248,9 @@ sub load_config {
 }
 
 sub write_config {
-    my ($vmid, $conf) = @_;
+    my ($class, $vmid, $conf) = @_;
 
-    my $filename = cfs_config_path($vmid);
+    my $filename = $class->cfs_config_path($vmid);
 
     if ($conf->{snapshots}) {
 	foreach my $snapname (keys %{$conf->{snapshots}}) {
@@ -262,7 +263,9 @@ sub write_config {
 
     PVE::Tools::file_set_contents($filename, $raw);
 }
+# END mocked PVE::QemuConfig methods
 
+# BEGIN redefine PVE::QemuServer methods
 sub has_feature {
     my ($feature, $conf, $storecfg, $snapname, $running, $backup_only) = @_;
     return $snapshot_possible;
@@ -345,6 +348,12 @@ sub vm_stop {
 PVE::Tools::run_command("rm -rf snapshot-working");
 PVE::Tools::run_command("cp -a snapshot-input snapshot-working");
 
+my $qemu_config_module = new Test::MockModule('PVE::QemuConfig');
+$qemu_config_module->mock('config_file_lock', \&config_file_lock);
+$qemu_config_module->mock('cfs_config_path', \&cfs_config_path);
+$qemu_config_module->mock('load_config', \&load_config);
+$qemu_config_module->mock('write_config', \&write_config);
+
 $running = 1;
 $freeze_possible = 1;
 $save_vmstate_works = 1;
-- 
2.1.4





More information about the pve-devel mailing list