Refactor basic config-related methods

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.
This commit is contained in:
Fabian Grünbichler 2016-03-07 12:41:12 +01:00 committed by Dietmar Maurer
parent a157d0fd17
commit ffda963f46
9 changed files with 221 additions and 252 deletions

View File

@ -13,6 +13,7 @@ use PVE::Exception qw(raise raise_param_exc raise_perm_exc);
use PVE::Storage; use PVE::Storage;
use PVE::JSONSchema qw(get_standard_option); use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler; use PVE::RESTHandler;
use PVE::QemuConfig;
use PVE::QemuServer; use PVE::QemuServer;
use PVE::QemuMigrate; use PVE::QemuMigrate;
use PVE::RPCEnvironment; use PVE::RPCEnvironment;
@ -205,14 +206,6 @@ my $check_vm_modify_config_perm = sub {
return 1; 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({ __PACKAGE__->register_method({
name => 'vmlist', name => 'vmlist',
path => '', path => '',
@ -339,7 +332,7 @@ __PACKAGE__->register_method({
my $pool = extract_param($param, 'pool'); 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(); my $storecfg = PVE::Storage::config();
@ -399,9 +392,9 @@ __PACKAGE__->register_method({
if ($vmlist->{ids}->{$vmid}) { if ($vmlist->{ids}->{$vmid}) {
my $current_node = $vmlist->{ids}->{$vmid}->{node}; my $current_node = $vmlist->{ids}->{$vmid}->{node};
if ($current_node eq $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" die "unable to restore vm $vmid - config file already exists\n"
if !$force; if !$force;
@ -462,7 +455,7 @@ __PACKAGE__->register_method({
$conf->{smbios1} = "uuid=$uuid_str"; $conf->{smbios1} = "uuid=$uuid_str";
} }
PVE::QemuServer::write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
}; };
my $err = $@; my $err = $@;
@ -481,7 +474,7 @@ __PACKAGE__->register_method({
return $rpcenv->fork_worker('qmcreate', $vmid, $authuser, $realcmd); 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({ __PACKAGE__->register_method({
@ -661,7 +654,7 @@ __PACKAGE__->register_method({
code => sub { code => sub {
my ($param) = @_; my ($param) = @_;
my $conf = PVE::QemuServer::load_config($param->{vmid}); my $conf = PVE::QemuConfig->load_config($param->{vmid});
delete $conf->{snapshots}; delete $conf->{snapshots};
@ -732,7 +725,7 @@ __PACKAGE__->register_method({
code => sub { code => sub {
my ($param) = @_; 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}); 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 $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" die "checksum missmatch (file change by other user?)\n"
if $digest && $digest ne $conf->{digest}; 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) { foreach my $opt (keys %$revert) {
if (defined($conf->{$opt})) { if (defined($conf->{$opt})) {
@ -906,31 +899,31 @@ my $update_vm_api = sub {
foreach my $opt (@delete) { foreach my $opt (@delete) {
$modified->{$opt} = 1; $modified->{$opt} = 1;
$conf = PVE::QemuServer::load_config($vmid); # update/reload $conf = PVE::QemuConfig->load_config($vmid); # update/reload
if ($opt =~ m/^unused/) { if ($opt =~ m/^unused/) {
my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt}); 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']); $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.Disk']);
if (PVE::QemuServer::try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser)) { if (PVE::QemuServer::try_deallocate_drive($storecfg, $vmid, $conf, $opt, $drive, $rpcenv, $authuser)) {
delete $conf->{$opt}; delete $conf->{$opt};
PVE::QemuServer::write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
} }
} elsif (PVE::QemuServer::is_valid_drivename($opt)) { } 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']); $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})) PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt}))
if defined($conf->{pending}->{$opt}); if defined($conf->{pending}->{$opt});
PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force); PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
PVE::QemuServer::write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
} else { } else {
PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force); 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 foreach my $opt (keys %$param) { # add/change
$modified->{$opt} = 1; $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 next if defined($conf->{pending}->{$opt}) && ($param->{$opt} eq $conf->{pending}->{$opt}); # skip if nothing changed
if (PVE::QemuServer::is_valid_drivename($opt)) { if (PVE::QemuServer::is_valid_drivename($opt)) {
@ -948,13 +941,13 @@ my $update_vm_api = sub {
$conf->{pending}->{$opt} = $param->{$opt}; $conf->{pending}->{$opt} = $param->{$opt};
} }
PVE::QemuServer::vmconfig_undelete_pending_option($conf, $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 # 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); 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}}); return if !scalar(keys %{$conf->{pending}});
@ -962,7 +955,7 @@ my $update_vm_api = sub {
# apply pending changes # apply pending changes
$conf = PVE::QemuServer::load_config($vmid); # update/reload $conf = PVE::QemuConfig->load_config($vmid); # update/reload
if ($running) { if ($running) {
my $errors = {}; 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 = [ my $vm_config_perm_list = [
@ -1161,11 +1154,11 @@ __PACKAGE__->register_method({
if $skiplock && $authuser ne 'root@pam'; if $skiplock && $authuser ne 'root@pam';
# test if VM exists # test if VM exists
my $conf = PVE::QemuServer::load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
my $storecfg = PVE::Storage::config(); 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" die "unable to remove VM $vmid - used in HA resources\n"
if PVE::HA::Config::vm_is_ha_managed($vmid); if PVE::HA::Config::vm_is_ha_managed($vmid);
@ -1270,7 +1263,7 @@ __PACKAGE__->register_method({
my $node = $param->{node}; my $node = $param->{node};
my $websocket = $param->{websocket}; 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"; my $authpath = "/vms/$vmid";
@ -1387,7 +1380,7 @@ __PACKAGE__->register_method({
PVE::AccessControl::verify_vnc_ticket($param->{vncticket}, $authuser, $authpath); 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 # 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 # security if we verify that $param->{port} belongs to VM $vmid. This
@ -1428,7 +1421,7 @@ __PACKAGE__->register_method({
my $node = $param->{node}; my $node = $param->{node};
my $proxy = $param->{proxy}; my $proxy = $param->{proxy};
my $conf = PVE::QemuServer::load_config($vmid, $node); my $conf = PVE::QemuConfig->load_config($vmid, $node);
my $title = "VM $vmid"; my $title = "VM $vmid";
$title .= " - ". $conf->{name} if $conf->{name}; $title .= " - ". $conf->{name} if $conf->{name};
@ -1473,7 +1466,7 @@ __PACKAGE__->register_method({
my ($param) = @_; my ($param) = @_;
# test if VM exists # test if VM exists
my $conf = PVE::QemuServer::load_config($param->{vmid}); my $conf = PVE::QemuConfig->load_config($param->{vmid});
my $res = [ my $res = [
{ subdir => 'current' }, { subdir => 'current' },
@ -1506,7 +1499,7 @@ __PACKAGE__->register_method({
my ($param) = @_; my ($param) = @_;
# test if VM exists # 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 $vmstatus = PVE::QemuServer::vmstatus($param->{vmid}, 1);
my $status = $vmstatus->{$param->{vmid}}; my $status = $vmstatus->{$param->{vmid}};
@ -2039,7 +2032,7 @@ __PACKAGE__->register_method({
my $running = PVE::QemuServer::check_running($vmid); my $running = PVE::QemuServer::check_running($vmid);
my $conf = PVE::QemuServer::load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
if($snapname){ if($snapname){
my $snap = $conf->{snapshots}->{$snapname}; my $snap = $conf->{snapshots}->{$snapname};
@ -2188,9 +2181,9 @@ __PACKAGE__->register_method({
# do all tests after lock # do all tests after lock
# we also try to do all tests before we fork the worker # 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; 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; 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" die "unable to create VM $newid: config file already exists\n"
if -f $conffile; if -f $conffile;
@ -2299,17 +2292,17 @@ __PACKAGE__->register_method({
$newconf->{$opt} = PVE::QemuServer::print_drive($vmid, $newdrive); $newconf->{$opt} = PVE::QemuServer::print_drive($vmid, $newdrive);
PVE::QemuServer::write_config($newid, $newconf); PVE::QemuConfig->write_config($newid, $newconf);
} }
delete $newconf->{lock}; delete $newconf->{lock};
PVE::QemuServer::write_config($newid, $newconf); PVE::QemuConfig->write_config($newid, $newconf);
if ($target) { if ($target) {
# always deactivate volumes - avoid lvm LVs to be active on several nodes # always deactivate volumes - avoid lvm LVs to be active on several nodes
PVE::Storage::deactivate_volumes($storecfg, $vollist, $snapname) if !$running; 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" die "Failed to move config to node '$target' - rename failed: $!\n"
if !rename($conffile, $newconffile); if !rename($conffile, $newconffile);
} }
@ -2336,9 +2329,9 @@ __PACKAGE__->register_method({
return $rpcenv->fork_worker('qmclone', $vmid, $authuser, $realcmd); 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 # 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 $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" die "checksum missmatch (file change by other user?)\n"
if $digest && $digest ne $conf->{digest}; 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::add_unused_volume($conf, $old_volid) if !$param->{delete};
PVE::QemuServer::write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
eval { eval {
# try to deactivate volumes - avoid lvm LVs to be active on several nodes # 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)) { if (PVE::QemuServer::is_volume_in_use($storecfg, $conf, undef, $old_volid)) {
warn "volume $old_volid still has snapshots, can't delete it\n"; warn "volume $old_volid still has snapshots, can't delete it\n";
PVE::QemuServer::add_unused_volume($conf, $old_volid); PVE::QemuServer::add_unused_volume($conf, $old_volid);
PVE::QemuServer::write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
} else { } else {
eval { PVE::Storage::vdisk_free($storecfg, $old_volid); }; eval { PVE::Storage::vdisk_free($storecfg, $old_volid); };
warn $@ if $@; warn $@ if $@;
@ -2495,7 +2488,7 @@ __PACKAGE__->register_method({
return $rpcenv->fork_worker('qmmove', $vmid, $authuser, $realcmd); 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({ __PACKAGE__->register_method({
@ -2557,11 +2550,11 @@ __PACKAGE__->register_method({
if $param->{force} && $authuser ne 'root@pam'; if $param->{force} && $authuser ne 'root@pam';
# test if VM exists # test if VM exists
my $conf = PVE::QemuServer::load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
# try to detect errors early # try to detect errors early
PVE::QemuServer::check_lock($conf); PVE::QemuConfig->check_lock($conf);
if (PVE::QemuServer::check_running($vmid)) { if (PVE::QemuServer::check_running($vmid)) {
die "cant migrate running VM without --online\n" die "cant migrate running VM without --online\n"
@ -2629,7 +2622,7 @@ __PACKAGE__->register_method({
my $vmid = $param->{vmid}; 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 = ''; my $res = '';
eval { eval {
@ -2700,11 +2693,11 @@ __PACKAGE__->register_method({
my $updatefn = 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" die "checksum missmatch (file change by other user?)\n"
if $digest && $digest ne $conf->{digest}; 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}; die "disk '$disk' does not exist\n" if !$conf->{$disk};
@ -2755,10 +2748,10 @@ __PACKAGE__->register_method({
$drive->{size} = $newsize; $drive->{size} = $newsize;
$conf->{$disk} = PVE::QemuServer::print_drive($vmid, $drive); $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; return undef;
}}); }});
@ -2792,7 +2785,7 @@ __PACKAGE__->register_method({
my $vmid = $param->{vmid}; my $vmid = $param->{vmid};
my $conf = PVE::QemuServer::load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
my $snaphash = $conf->{snapshots} || {}; my $snaphash = $conf->{snapshots} || {};
my $res = []; my $res = [];
@ -2950,9 +2943,9 @@ __PACKAGE__->register_method({
my $updatefn = sub { 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}; my $snap = $conf->{snapshots}->{$snapname};
@ -2960,10 +2953,10 @@ __PACKAGE__->register_method({
$snap->{description} = $param->{description} if defined($param->{description}); $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; return undef;
}}); }});
@ -2997,7 +2990,7 @@ __PACKAGE__->register_method({
my $snapname = extract_param($param, 'snapname'); 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}; my $snap = $conf->{snapshots}->{$snapname};
@ -3138,15 +3131,15 @@ __PACKAGE__->register_method({
my $updatefn = sub { 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" die "unable to create template, because VM contains snapshots\n"
if $conf->{snapshots} && scalar(keys %{$conf->{snapshots}}); if $conf->{snapshots} && scalar(keys %{$conf->{snapshots}});
die "you can't convert a template to a template\n" 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" die "you can't convert a VM to template if VM is running\n"
if PVE::QemuServer::check_running($vmid); if PVE::QemuServer::check_running($vmid);
@ -3156,12 +3149,12 @@ __PACKAGE__->register_method({
}; };
$conf->{template} = 1; $conf->{template} = 1;
PVE::QemuServer::write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
return $rpcenv->fork_worker('qmtemplate', $vmid, $authuser, $realcmd); return $rpcenv->fork_worker('qmtemplate', $vmid, $authuser, $realcmd);
}; };
PVE::QemuServer::lock_config($vmid, $updatefn); PVE::QemuConfig->lock_config($vmid, $updatefn);
return undef; return undef;
}}); }});

View File

@ -117,7 +117,7 @@ __PACKAGE__->register_method ({
my ($param) = @_; my ($param) = @_;
# test if VM exists # 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 $vmstatus = PVE::QemuServer::vmstatus($param->{vmid}, 1);
my $stat = $vmstatus->{$param->{vmid}}; my $stat = $vmstatus->{$param->{vmid}};
@ -185,10 +185,10 @@ __PACKAGE__->register_method ({
my $vmid = $param->{vmid}; my $vmid = $param->{vmid};
PVE::QemuServer::lock_config ($vmid, sub { 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->{lock};
delete $conf->{pending}->{lock} if $conf->{pending}; # just to be sure 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; return undef;
@ -280,7 +280,7 @@ __PACKAGE__->register_method ({
my $vmid = $param->{vmid}; 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"; print "Entering Qemu Monitor for VM $vmid - type 'help' for help\n";
@ -350,7 +350,7 @@ __PACKAGE__->register_method ({
my $vmid = $param->{vmid}; 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}; my $iface = $param->{iface};

View File

@ -1,7 +1,8 @@
PERLSOURCE = \ PERLSOURCE = \
QemuServer.pm \ QemuServer.pm \
QemuMigrate.pm \ QemuMigrate.pm \
QMPClient.pm QMPClient.pm \
QemuConfig.pm
.PHONY: install .PHONY: install
install: install:

46
PVE/QemuConfig.pm Normal file
View File

@ -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;

View File

@ -122,7 +122,7 @@ sub finish_tunnel {
sub lock_vm { sub lock_vm {
my ($self, $vmid, $code, @param) = @_; my ($self, $vmid, $code, @param) = @_;
return PVE::QemuServer::lock_config($vmid, $code, @param); return PVE::QemuConfig->lock_config($vmid, $code, @param);
} }
sub prepare { sub prepare {
@ -133,9 +133,9 @@ sub prepare {
$self->{storecfg} = PVE::Storage::config(); $self->{storecfg} = PVE::Storage::config();
# test is VM exist # 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; my $running = 0;
if (my $pid = PVE::QemuServer::check_running($vmid)) { if (my $pid = PVE::QemuServer::check_running($vmid)) {
@ -277,7 +277,7 @@ sub phase1 {
# set migrate lock in config file # set migrate lock in config file
$conf->{lock} = 'migrate'; $conf->{lock} = 'migrate';
PVE::QemuServer::write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
sync_disks($self, $vmid); sync_disks($self, $vmid);
@ -290,7 +290,7 @@ sub phase1_cleanup {
my $conf = $self->{vmconf}; my $conf = $self->{vmconf};
delete $conf->{lock}; delete $conf->{lock};
eval { PVE::QemuServer::write_config($vmid, $conf) }; eval { PVE::QemuConfig->write_config($vmid, $conf) };
if (my $err = $@) { if (my $err = $@) {
$self->log('err', $err); $self->log('err', $err);
} }
@ -546,7 +546,7 @@ sub phase2_cleanup {
my $conf = $self->{vmconf}; my $conf = $self->{vmconf};
delete $conf->{lock}; delete $conf->{lock};
eval { PVE::QemuServer::write_config($vmid, $conf) }; eval { PVE::QemuConfig->write_config($vmid, $conf) };
if (my $err = $@) { if (my $err = $@) {
$self->log('err', $err); $self->log('err', $err);
} }
@ -594,8 +594,8 @@ sub phase3_cleanup {
return if $self->{phase2errors}; return if $self->{phase2errors};
# move config to remote node # move config to remote node
my $conffile = PVE::QemuServer::config_file($vmid); my $conffile = PVE::QemuConfig->config_file($vmid);
my $newconffile = PVE::QemuServer::config_file($vmid, $self->{node}); my $newconffile = PVE::QemuConfig->config_file($vmid, $self->{node});
die "Failed to move config to node '$self->{node}' - rename failed: $!\n" die "Failed to move config to node '$self->{node}' - rename failed: $!\n"
if !rename($conffile, $newconffile); if !rename($conffile, $newconffile);

View File

@ -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::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
use PVE::INotify; use PVE::INotify;
use PVE::ProcFSTools; use PVE::ProcFSTools;
use PVE::QemuConfig;
use PVE::QMPClient; use PVE::QMPClient;
use PVE::RPCEnvironment; use PVE::RPCEnvironment;
use Time::HiRes qw(gettimeofday); 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{ sub check_iommu_support{
#fixme : need to check IOMMU support #fixme : need to check IOMMU support
#http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM #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 { sub touch_config {
my ($vmid) = @_; my ($vmid) = @_;
my $conf = config_file($vmid); my $conf = PVE::QemuConfig->config_file($vmid);
utime undef, undef, $conf; utime undef, undef, $conf;
} }
sub destroy_vm { sub destroy_vm {
my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_; 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 # only remove disks owned by this VM
foreach_drive($conf, sub { foreach_drive($conf, sub {
@ -2004,18 +1955,6 @@ sub destroy_vm {
warn $@ if $@; 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 { sub parse_vm_config {
my ($filename, $raw) = @_; my ($filename, $raw) = @_;
@ -2222,14 +2161,6 @@ sub write_vm_config {
return $raw; return $raw;
} }
sub write_config {
my ($vmid, $conf) = @_;
my $cfspath = cfs_config_path($vmid);
PVE::Cluster::cfs_write_file($cfspath, $conf);
}
sub load_defaults { sub load_defaults {
my $res = {}; my $res = {};
@ -2336,12 +2267,6 @@ sub shared_nodes {
return $nodehash return $nodehash
} }
sub check_lock {
my ($conf) = @_;
die "VM is locked ($conf->{lock})\n" if $conf->{lock};
}
sub check_cmdline { sub check_cmdline {
my ($pidfile, $pid) = @_; my ($pidfile, $pid) = @_;
@ -2371,7 +2296,7 @@ sub check_cmdline {
sub check_running { sub check_running {
my ($vmid, $nocheck, $node) = @_; 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" die "unable to find configuration file for VM $vmid - no such machine\n"
if !$nocheck && ! -f $filename; if !$nocheck && ! -f $filename;
@ -2459,7 +2384,7 @@ sub vmstatus {
foreach my $vmid (keys %$list) { foreach my $vmid (keys %$list) {
next if $opt_vmid && ($vmid ne $opt_vmid); 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 $conf = PVE::Cluster::cfs_read_file($cfspath) || {};
my $d = {}; my $d = {};
@ -2499,7 +2424,7 @@ sub vmstatus {
$d->{diskread} = 0; $d->{diskread} = 0;
$d->{diskwrite} = 0; $d->{diskwrite} = 0;
$d->{template} = is_template($conf); $d->{template} = PVE::QemuConfig->is_template($conf);
$res->{$vmid} = $d; $res->{$vmid} = $d;
} }
@ -3196,7 +3121,7 @@ sub config_to_command {
#if dimm_memory is not aligned to dimm map #if dimm_memory is not aligned to dimm map
if($current_size > $memory) { if($current_size > $memory) {
$conf->{memory} = $current_size; $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 #update conf after each succesful module hotplug
$conf->{memory} = $current_size; $conf->{memory} = $current_size;
write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
}); });
} else { } else {
@ -3878,7 +3803,7 @@ sub qemu_memory_hotplug {
$conf->{memory} = $current_size; $conf->{memory} = $current_size;
eval { qemu_objectdel($vmid, "mem-$name"); }; 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) { if ($changes) {
write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
$conf = load_config($vmid); # update/reload $conf = PVE::QemuConfig->load_config($vmid); # update/reload
} }
my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1'); 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 # save new config if hotplug was successful
delete $conf->{$opt}; delete $conf->{$opt};
vmconfig_undelete_pending_option($conf, $opt); vmconfig_undelete_pending_option($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
} }
} }
@ -4240,8 +4165,8 @@ sub vmconfig_hotplug_pending {
# save new config if hotplug was successful # save new config if hotplug was successful
$conf->{$opt} = $value; $conf->{$opt} = $value;
delete $conf->{pending}->{$opt}; delete $conf->{pending}->{$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
} }
} }
} }
@ -4293,26 +4218,26 @@ sub vmconfig_apply_pending {
my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete}); my $pending_delete_hash = split_flagged_list($conf->{pending}->{delete});
while (my ($opt, $force) = each %$pending_delete_hash) { while (my ($opt, $force) = each %$pending_delete_hash) {
die "internal error" if $opt =~ m/^unused/; 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})) { if (!defined($conf->{$opt})) {
vmconfig_undelete_pending_option($conf, $opt); vmconfig_undelete_pending_option($conf, $opt);
write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
} elsif (is_valid_drivename($opt)) { } elsif (is_valid_drivename($opt)) {
vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force); vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
vmconfig_undelete_pending_option($conf, $opt); vmconfig_undelete_pending_option($conf, $opt);
delete $conf->{$opt}; delete $conf->{$opt};
write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
} else { } else {
vmconfig_undelete_pending_option($conf, $opt); vmconfig_undelete_pending_option($conf, $opt);
delete $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 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})) { if (defined($conf->{$opt}) && ($conf->{$opt} eq $conf->{pending}->{$opt})) {
# skip if nothing changed # skip if nothing changed
@ -4325,7 +4250,7 @@ sub vmconfig_apply_pending {
} }
delete $conf->{pending}->{$opt}; 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, my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
$forcemachine, $spice_ticket) = @_; $forcemachine, $spice_ticket) = @_;
lock_config($vmid, sub { PVE::QemuConfig->lock_config($vmid, sub {
my $conf = load_config($vmid, $migratedfrom); 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); die "VM $vmid already running\n" if check_running($vmid, undef, $migratedfrom);
if (!$statefile && scalar(keys %{$conf->{pending}})) { if (!$statefile && scalar(keys %{$conf->{pending}})) {
vmconfig_apply_pending($vmid, $conf, $storecfg); vmconfig_apply_pending($vmid, $conf, $storecfg);
$conf = load_config($vmid); # update/reload $conf = PVE::QemuConfig->load_config($vmid); # update/reload
} }
my $defaults = load_defaults(); my $defaults = load_defaults();
@ -4670,7 +4595,7 @@ sub vm_human_monitor_command {
sub vm_commandline { sub vm_commandline {
my ($storecfg, $vmid) = @_; my ($storecfg, $vmid) = @_;
my $conf = load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
my $defaults = load_defaults(); my $defaults = load_defaults();
@ -4682,11 +4607,11 @@ sub vm_commandline {
sub vm_reset { sub vm_reset {
my ($vmid, $skiplock) = @_; 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"); vm_mon_cmd($vmid, "system_reset");
}); });
@ -4740,20 +4665,20 @@ sub vm_stop {
if ($migratedfrom){ if ($migratedfrom){
my $pid = check_running($vmid, $nocheck, $migratedfrom); my $pid = check_running($vmid, $nocheck, $migratedfrom);
kill 15, $pid if $pid; 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); vm_stop_cleanup($storecfg, $vmid, $conf, $keepActive, 0);
return; return;
} }
lock_config($vmid, sub { PVE::QemuConfig->lock_config($vmid, sub {
my $pid = check_running($vmid, $nocheck); my $pid = check_running($vmid, $nocheck);
return if !$pid; return if !$pid;
my $conf; my $conf;
if (!$nocheck) { if (!$nocheck) {
$conf = load_config($vmid); $conf = PVE::QemuConfig->load_config($vmid);
check_lock($conf) if !$skiplock; PVE::QemuConfig->check_lock($conf) if !$skiplock;
if (!defined($timeout) && $shutdown && $conf->{startup}) { if (!defined($timeout) && $shutdown && $conf->{startup}) {
my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup}); my $opts = PVE::JSONSchema::pve_parse_startup_order($conf->{startup});
$timeout = $opts->{down} if $opts->{down}; $timeout = $opts->{down} if $opts->{down};
@ -4824,11 +4749,11 @@ sub vm_stop {
sub vm_suspend { sub vm_suspend {
my ($vmid, $skiplock) = @_; 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"); vm_mon_cmd($vmid, "stop");
}); });
@ -4837,13 +4762,13 @@ sub vm_suspend {
sub vm_resume { sub vm_resume {
my ($vmid, $skiplock, $nocheck) = @_; my ($vmid, $skiplock, $nocheck) = @_;
lock_config($vmid, sub { PVE::QemuConfig->lock_config($vmid, sub {
if (!$nocheck) { 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"); vm_mon_cmd($vmid, "cont");
@ -4856,9 +4781,9 @@ sub vm_resume {
sub vm_sendkey { sub vm_sendkey {
my ($vmid, $skiplock, $key) = @_; 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 # there is no qmp command, so we use the human monitor command
vm_human_monitor_command($vmid, "sendkey $key"); vm_human_monitor_command($vmid, "sendkey $key");
@ -4868,9 +4793,9 @@ sub vm_sendkey {
sub vm_destroy { sub vm_destroy {
my ($storecfg, $vmid, $skiplock) = @_; 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)) { if (!check_running($vmid)) {
destroy_vm($storecfg, $vmid, undef, $skiplock); destroy_vm($storecfg, $vmid, undef, $skiplock);
@ -5397,9 +5322,9 @@ sub rescan {
my $updatefn = sub { my $updatefn = sub {
my ($vmid) = @_; 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 = {}; my $vm_volids = {};
foreach my $volid (keys %$volid_hash) { foreach my $volid (keys %$volid_hash) {
@ -5409,14 +5334,14 @@ sub rescan {
my $changes = update_disksize($vmid, $conf, $vm_volids); 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 (defined($vmid)) {
if ($nolock) { if ($nolock) {
&$updatefn($vmid); &$updatefn($vmid);
} else { } else {
lock_config($vmid, $updatefn, $vmid); PVE::QemuConfig->lock_config($vmid, $updatefn, $vmid);
} }
} else { } else {
my $vmlist = config_list(); my $vmlist = config_list();
@ -5424,7 +5349,7 @@ sub rescan {
if ($nolock) { if ($nolock) {
&$updatefn($vmid); &$updatefn($vmid);
} else { } 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 $rpcenv = PVE::RPCEnvironment::get();
my $conffile = config_file($vmid); my $conffile = PVE::QemuConfig->config_file($vmid);
my $tmpfn = "$conffile.$$.tmp"; my $tmpfn = "$conffile.$$.tmp";
# Note: $oldconf is undef if VM does not exists # 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 $print_devmap = sub {
my $virtdev_hash = {}; my $virtdev_hash = {};
@ -5701,7 +5627,7 @@ sub restore_tar_archive {
my $storecfg = cfs_read_file('storage.cfg'); my $storecfg = cfs_read_file('storage.cfg');
# destroy existing data - keep empty config # 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; destroy_vm($storecfg, $vmid, 1) if -f $vmcfgfn;
my $tocmd = "/usr/lib/qemu-server/qmextract"; my $tocmd = "/usr/lib/qemu-server/qmextract";
@ -5723,7 +5649,7 @@ sub restore_tar_archive {
local $ENV{VZDUMP_VMID} = $vmid; local $ENV{VZDUMP_VMID} = $vmid;
local $ENV{VZDUMP_USER} = $user; local $ENV{VZDUMP_USER} = $user;
my $conffile = config_file($vmid); my $conffile = PVE::QemuConfig->config_file($vmid);
my $tmpfn = "$conffile.$$.tmp"; my $tmpfn = "$conffile.$$.tmp";
# disable interrupts (always do cleanups) # disable interrupts (always do cleanups)
@ -5925,12 +5851,12 @@ sub snapshot_prepare {
my $updatefn = sub { 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" 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'; $conf->{lock} = 'snapshot';
@ -5953,10 +5879,10 @@ sub snapshot_prepare {
$snap->{snaptime} = time(); $snap->{snaptime} = time();
$snap->{description} = $comment if $comment; $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; return $snap;
} }
@ -5966,7 +5892,7 @@ sub snapshot_commit {
my $updatefn = sub { my $updatefn = sub {
my $conf = load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
die "missing snapshot lock\n" die "missing snapshot lock\n"
if !($conf->{lock} && $conf->{lock} eq 'snapshot'); if !($conf->{lock} && $conf->{lock} eq 'snapshot');
@ -5983,10 +5909,10 @@ sub snapshot_commit {
$conf->{parent} = $snapname; $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 { sub snapshot_rollback {
@ -5996,11 +5922,11 @@ sub snapshot_rollback {
my $storecfg = PVE::Storage::config(); my $storecfg = PVE::Storage::config();
my $conf = load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
my $get_snapshot_config = sub { 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}; my $res = $conf->{snapshots}->{$snapname};
@ -6023,7 +5949,7 @@ sub snapshot_rollback {
my $updatefn = sub { my $updatefn = sub {
$conf = load_config($vmid); $conf = PVE::QemuConfig->load_config($vmid);
$snap = &$get_snapshot_config(); $snap = &$get_snapshot_config();
@ -6031,7 +5957,7 @@ sub snapshot_rollback {
if $snap->{snapstate}; if $snap->{snapstate};
if ($prepare) { if ($prepare) {
check_lock($conf); PVE::QemuConfig->check_lock($conf);
vm_stop($storecfg, $vmid, undef, undef, 5, undef, undef); 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; delete $conf->{machine} if $snap->{vmstate} && !$has_machine_config;
} }
write_config($vmid, $conf); PVE::QemuConfig->write_config($vmid, $conf);
if (!$prepare && $snap->{vmstate}) { if (!$prepare && $snap->{vmstate}) {
my $statefile = PVE::Storage::path($storecfg, $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 { foreach_drive($snap, sub {
my ($ds, $drive) = @_; my ($ds, $drive) = @_;
@ -6084,7 +6010,7 @@ sub snapshot_rollback {
}); });
$prepare = 0; $prepare = 0;
lock_config($vmid, $updatefn); PVE::QemuConfig->lock_config($vmid, $updatefn);
} }
my $savevm_wait = sub { my $savevm_wait = sub {
@ -6151,7 +6077,7 @@ sub snapshot_create {
$save_vmstate = 0 if !$snap->{vmstate}; # vm is not running $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}); my ($running, $freezefs) = check_freeze_needed($vmid, $config, $snap->{vmstate});
@ -6247,12 +6173,12 @@ sub snapshot_delete {
my $updatefn = sub { my $updatefn = sub {
my ($remove_drive) = @_; my ($remove_drive) = @_;
my $conf = load_config($vmid); my $conf = PVE::QemuConfig->load_config($vmid);
if (!$drivehash) { if (!$drivehash) {
check_lock($conf); PVE::QemuConfig->check_lock($conf);
die "you can't delete a snapshot if vm is a template\n" 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}; $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 # now remove vmstate file
@ -6305,7 +6231,7 @@ sub snapshot_delete {
warn $err; warn $err;
} }
# save changes (remove vmstate from snapshot) # 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 # now remove all internal snapshots
@ -6326,13 +6252,13 @@ sub snapshot_delete {
} }
# save changes (remove drive fron snapshot) # 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; push @$unused, $volid;
}); });
# now cleanup config # now cleanup config
$prepare = 0; $prepare = 0;
lock_config($vmid, $updatefn); PVE::QemuConfig->lock_config($vmid, $updatefn);
} }
sub has_feature { sub has_feature {
@ -6368,16 +6294,10 @@ sub template_create {
my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid); my $voliddst = PVE::Storage::vdisk_create_base($storecfg, $volid);
$drive->{file} = $voliddst; $drive->{file} = $voliddst;
$conf->{$ds} = print_drive($vmid, $drive); $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 { sub qemu_img_convert {
my ($src_volid, $dst_volid, $size, $snapname) = @_; my ($src_volid, $dst_volid, $size, $snapname) = @_;

View File

@ -46,7 +46,7 @@ sub prepare {
$task->{disks} = []; $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; $self->{vm_was_running} = 1;
if (!PVE::QemuServer::check_running($vmid)) { if (!PVE::QemuServer::check_running($vmid)) {
@ -230,7 +230,7 @@ sub archive {
my $diskcount = scalar(@{$task->{disks}}); 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; my @pathlist;
foreach my $di (@{$task->{disks}}) { foreach my $di (@{$task->{disks}}) {
if ($di->{type} eq 'block' || $di->{type} eq 'file') { if ($di->{type} eq 'block' || $di->{type} eq 'file') {

View File

@ -24,7 +24,7 @@ my $netid = "net$2";
my $migratedfrom = $hotplug ? undef : $ENV{PVE_MIGRATED_FROM}; 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}; my $netconf = $conf->{$netid};

View File

@ -8,6 +8,7 @@ use lib qw(..);
use PVE::Storage; use PVE::Storage;
use PVE::Storage::Plugin; use PVE::Storage::Plugin;
use PVE::QemuServer; use PVE::QemuServer;
use PVE::QemuConfig;
use PVE::Tools; use PVE::Tools;
use Test::MockModule; use Test::MockModule;
@ -223,22 +224,22 @@ sub testcase_rollback {
}; };
} }
# BEGIN redefine PVE::QemuServer methods # BEGIN mocked PVE::QemuConfig methods
sub config_file_lock { sub config_file_lock {
return "snapshot-working/pve-test.lock"; return "snapshot-working/pve-test.lock";
} }
sub cfs_config_path { sub cfs_config_path {
my ($vmid, $node) = @_; my ($class, $vmid, $node) = @_;
$node = $nodename if !$node; $node = $nodename if !$node;
return "snapshot-working/$node/qemu-server/$vmid.conf"; return "snapshot-working/$node/qemu-server/$vmid.conf";
} }
sub load_config { 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); my $raw = PVE::Tools::file_get_contents($filename);
@ -247,9 +248,9 @@ sub load_config {
} }
sub write_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}) { if ($conf->{snapshots}) {
foreach my $snapname (keys %{$conf->{snapshots}}) { foreach my $snapname (keys %{$conf->{snapshots}}) {
@ -262,7 +263,9 @@ sub write_config {
PVE::Tools::file_set_contents($filename, $raw); PVE::Tools::file_set_contents($filename, $raw);
} }
# END mocked PVE::QemuConfig methods
# BEGIN redefine PVE::QemuServer methods
sub has_feature { sub has_feature {
my ($feature, $conf, $storecfg, $snapname, $running, $backup_only) = @_; my ($feature, $conf, $storecfg, $snapname, $running, $backup_only) = @_;
return $snapshot_possible; return $snapshot_possible;
@ -345,6 +348,12 @@ sub vm_stop {
PVE::Tools::run_command("rm -rf snapshot-working"); PVE::Tools::run_command("rm -rf snapshot-working");
PVE::Tools::run_command("cp -a snapshot-input 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; $running = 1;
$freeze_possible = 1; $freeze_possible = 1;
$save_vmstate_works = 1; $save_vmstate_works = 1;