X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FAPI2%2FQemu.pm;h=e2bd09360ecb35abe0e52c109c7ee1e69e4988ad;hb=f8c4b2c5ba1820b86ae69751ab643e26ca8c9852;hp=3965c269fdf1a850f7044bb85c453250e5c965cd;hpb=a4e128a9a9814618c4b63370e6215ba639b78011;p=qemu-server.git diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index 3965c26..e2bd093 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -358,8 +358,10 @@ my $check_vm_modify_config_perm = sub { $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.PowerMgmt']); } elsif ($diskoptions->{$opt}) { $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Disk']); - } elsif ($cloudinitoptions->{$opt} || ($opt =~ m/^(?:net|ipconfig)\d+$/)) { + } elsif ($opt =~ m/^(?:net|ipconfig)\d+$/) { $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Network']); + } elsif ($cloudinitoptions->{$opt}) { + $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Cloudinit', 'VM.Config.Network'], 1); } elsif ($opt eq 'vmstate') { # the user needs Disk and PowerMgmt privileges to change the vmstate # also needs privileges on the storage, that will be checked later @@ -654,9 +656,9 @@ __PACKAGE__->register_method({ eval { $vollist = &$create_disks($rpcenv, $authuser, $conf, $arch, $storecfg, $vmid, $pool, $param, $storage); - if (!$conf->{bootdisk}) { - my $firstdisk = PVE::QemuServer::Drive::resolve_first_disk($conf); - $conf->{bootdisk} = $firstdisk if $firstdisk; + if (!$conf->{boot}) { + my $devs = PVE::QemuServer::get_default_bootdevices($conf); + $conf->{boot} = PVE::QemuServer::print_bootorder($devs); } # auto generate uuid if user did not specify smbios1 option @@ -1189,6 +1191,12 @@ my $update_vm_api = sub { my $modified = {}; # record what $option we modify + my $bootcfg = PVE::JSONSchema::parse_property_string('pve-qm-boot', $conf->{boot}) + if $conf->{boot}; + my @bootorder = PVE::Tools::split_list($bootcfg->{order}) + if $bootcfg && $bootcfg->{order}; + my $bootorder_deleted = grep {$_ eq 'bootorder'} @delete; + foreach my $opt (@delete) { $modified->{$opt} = 1; $conf = PVE::QemuConfig->load_config($vmid); # update/reload @@ -1203,6 +1211,13 @@ my $update_vm_api = sub { my $is_pending_val = defined($conf->{pending}->{$opt}); delete $conf->{pending}->{$opt}; + # remove from bootorder if necessary + if (!$bootorder_deleted && @bootorder && grep {$_ eq $opt} @bootorder) { + @bootorder = grep {$_ ne $opt} @bootorder; + $conf->{pending}->{boot} = PVE::QemuServer::print_bootorder(\@bootorder); + $modified->{boot} = 1; + } + if ($opt =~ m/^unused/) { my $drive = PVE::QemuServer::parse_drive($opt, $val); PVE::QemuConfig->check_protection($conf, "can't remove unused disk '$drive->{file}'"); @@ -1281,6 +1296,24 @@ my $update_vm_api = sub { $conf->{pending}->{$opt} = $param->{$opt}; } else { $conf->{pending}->{$opt} = $param->{$opt}; + + if ($opt eq 'boot') { + my $new_bootcfg = PVE::JSONSchema::parse_property_string('pve-qm-boot', $param->{$opt}); + if ($new_bootcfg->{order}) { + my @devs = PVE::Tools::split_list($new_bootcfg->{order}); + for my $dev (@devs) { + my $exists = $conf->{$dev} || $conf->{pending}->{$dev}; + my $deleted = grep {$_ eq $dev} @delete; + die "invalid bootorder: device '$dev' does not exist'\n" + if !$exists || $deleted; + } + + # remove legacy boot order settings if new one set + $conf->{pending}->{$opt} = PVE::QemuServer::print_bootorder(\@devs); + PVE::QemuConfig->add_to_pending_delete($conf, "bootdisk") + if $conf->{bootdisk}; + } + } } PVE::QemuConfig->remove_from_pending_delete($conf, $opt); PVE::QemuConfig->write_config($vmid, $conf); @@ -1354,6 +1387,7 @@ my $vm_config_perm_list = [ 'VM.Config.Network', 'VM.Config.HWType', 'VM.Config.Options', + 'VM.Config.Cloudinit', ]; __PACKAGE__->register_method({ @@ -2997,6 +3031,7 @@ __PACKAGE__->register_method({ if !PVE::Storage::volume_has_feature($storecfg, 'clone', $drive->{file}, $snapname, $running); } $drives->{$opt} = $drive; + next if PVE::QemuServer::drive_is_cloudinit($drive); push @$vollist, $drive->{file}; } } else { @@ -3532,6 +3567,19 @@ __PACKAGE__->register_method({ if (PVE::QemuServer::check_running($vmid)) { die "can't migrate running VM without --online\n" if !$param->{online}; + + my $repl_conf = PVE::ReplicationConfig->new(); + my $is_replicated = $repl_conf->check_for_existing_jobs($vmid, 1); + my $is_replicated_to_target = defined($repl_conf->find_local_replication_job($vmid, $target)); + if ($is_replicated && !$is_replicated_to_target) { + if ($param->{force}) { + warn "WARNING: Node '$target' is not a replication target. Existing replication " . + "jobs will fail after migration!\n"; + } else { + die "Cannot live-migrate replicated VM to node '$target' - not a replication target." . + " Use 'force' to override.\n"; + } + } } else { warn "VM isn't running. Doing offline migration instead.\n" if $param->{online}; $param->{online} = 0;