use PVE::Storage;
use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler;
+use PVE::ReplicationConfig;
+use PVE::GuestHelpers;
use PVE::QemuConfig;
use PVE::QemuServer;
use PVE::QemuMigrate;
use PVE::Network;
use PVE::Firewall;
use PVE::API2::Firewall::VM;
-use PVE::ReplicationTools;
BEGIN {
if (!$ENV{PVE_GENERATING_DOCS}) {
my $vollist = [];
my $res = {};
- PVE::QemuServer::foreach_drive($settings, sub {
+
+ my $code = sub {
my ($ds, $disk) = @_;
my $volid = $disk->{file};
if (!$volid || $volid eq 'none' || $volid eq 'cdrom') {
delete $disk->{size};
$res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
- } elsif ($volid =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
+ } elsif ($volid =~ m!^(([^/:\s]+):)?(\d+(\.\d+)?)$!) {
my ($storeid, $size) = ($2 || $default_storage, $3);
die "no storage ID specified (and no default storage)\n" if !$storeid;
my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
$res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
}
- });
+ };
+
+ eval { PVE::QemuServer::foreach_drive($settings, $code); };
# free allocated images on error
if (my $err = $@) {
foreach my $opt (@delete) {
$modified->{$opt} = 1;
$conf = PVE::QemuConfig->load_config($vmid); # update/reload
- if (!defined($conf->{$opt})) {
+ if (!defined($conf->{$opt}) && !defined($conf->{pending}->{$opt})) {
warn "cannot delete '$opt' - not set in current configuration!\n";
$modified->{$opt} = 0;
next;
if defined($conf->{pending}->{$opt});
PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
PVE::QemuConfig->write_config($vmid, $conf);
- } elsif ($opt eq "replica" || $opt eq "replica_target") {
- delete $conf->{$opt};
- delete $conf->{replica} if $opt eq "replica_target";
-
- PVE::QemuConfig->write_config($vmid, $conf);
- PVE::ReplicationTools::job_remove($vmid);
- } elsif ($opt eq "replica_interval" || $opt eq "replica_rate_limit") {
- delete $conf->{$opt};
- PVE::QemuConfig->write_config($vmid, $conf);
- PVE::ReplicationTools::update_conf($vmid, $opt, $param->{$opt});
} else {
PVE::QemuServer::vmconfig_delete_pending_option($conf, $opt, $force);
PVE::QemuConfig->write_config($vmid, $conf);
if defined($conf->{pending}->{$opt});
&$create_disks($rpcenv, $authuser, $conf->{pending}, $storecfg, $vmid, undef, {$opt => $param->{$opt}});
- } elsif ($opt eq "replica") {
- die "Not all volumes are syncable, please check your config\n"
- if !PVE::ReplicationTools::check_guest_volumes_syncable($conf, 'qemu');
- die "replica_target is required\n"
- if !$conf->{replica_target} && !$param->{replica_target};
- $conf->{$opt} = $param->{$opt};
- } elsif ($opt eq "replica_interval" || $opt eq "replica_rate_limit") {
- $conf->{$opt} = $param->{$opt};
- PVE::ReplicationTools::update_conf($vmid, $opt, $param->{$opt});
- } elsif ($opt eq "replica_target" ) {
- die "Node: $param->{$opt} does not exists in Cluster.\n"
- if !PVE::Cluster::check_node_exists($param->{$opt});
- PVE::ReplicationTools::update_conf($vmid, $opt, $param->{$opt})
- if defined($conf->{$opt});
- $conf->{$opt} = $param->{$opt};
} else {
$conf->{pending}->{$opt} = $param->{$opt};
}
PVE::QemuConfig->write_config($vmid, $conf);
}
- if (defined($param->{replica})) {
- if ($param->{replica}) {
- PVE::ReplicationTools::job_enable($vmid);
- } else {
- PVE::ReplicationTools::job_disable($vmid);
- }
- }
-
# remove pending changes when nothing changed
$conf = PVE::QemuConfig->load_config($vmid); # update/reload
my $changes = PVE::QemuServer::vmconfig_cleanup_pending($conf);
die "unable to remove VM $vmid - used in HA resources\n"
if PVE::HA::Config::vm_is_ha_managed($vmid);
+ # do not allow destroy if there are replication jobs
+ my $repl_conf = PVE::ReplicationConfig->new();
+ $repl_conf->check_for_existing_jobs($vmid);
+
# early tests (repeat after locking)
die "VM $vmid is running - destroy failed\n"
if PVE::QemuServer::check_running($vmid);
syslog('info', "destroy VM $vmid: $upid\n");
- # return without error if vm has no replica job
- PVE::ReplicationTools::destroy_replica($vmid);
-
PVE::QemuServer::vm_destroy($storecfg, $vmid, $skiplock);
PVE::AccessControl::remove_vm_access($vmid);
$cmd = [@$remcmd, "/usr/sbin/qm", 'vncproxy', $vmid];
my $sock = IO::Socket::IP->new(
+ ReuseAddr => 1,
Listen => 1,
LocalPort => $port,
Proto => 'tcp',
return;
};
- my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd);
+ my $upid = $rpcenv->fork_worker('vncproxy', $vmid, $authuser, $realcmd, 1);
PVE::Tools::wait_for_vnc_port($port);
$newconf->{$opt} = $value; # simply copy configuration
} else {
if ($param->{full}) {
- die "Full clone feature is not available"
+ die "Full clone feature is not supported for drive '$opt'\n"
if !PVE::Storage::volume_has_feature($storecfg, 'copy', $drive->{file}, $snapname, $running);
$fullclone->{$opt} = 1;
} else {
# not full means clone instead of copy
- die "Linked clone feature is not available"
+ die "Linked clone feature is not supported for drive '$opt'\n"
if !PVE::Storage::volume_has_feature($storecfg, 'clone', $drive->{file}, $snapname, $running);
}
$drives->{$opt} = $drive;
} else {
- my $realcmd = sub {
- my $upid = shift;
+ my $code = sub {
+ my $realcmd = sub {
+ my $upid = shift;
+
+ PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
+ };
- PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
+ return $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
};
- return $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
+ return PVE::GuestHelpers::guest_migration_lock($vmid, 10, $code);
}
}});