api: migrate preconditions: include not mapped resources for running VMs

So that we can show a proper warning in the migrate dialog and check it
in the bulk migrate precondition check.

The returned 'unavailable_storages' and 'unavailable-resources' should
be the same as before, but we now always return (not_)allowed_nodes
too.

To make the code a bit easier to read, reorganize how we construct the
(not_)allowed_nodes properties.

Also add a note that we want to redesign the return values here for a
easier to consume interface.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Reviewed-by: Christoph Heiss <c.heiss@proxmox.com>
Reviewed-by: Fiona Ebner <f.ebner@proxmox.com>
Tested-by: Christoph Heiss <c.heiss@proxmox.com>
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Dominik Csapak 2025-03-11 14:20:47 +01:00 committed by Thomas Lamprecht
parent b86d32dcb2
commit 8aeaad24ab

View File

@ -4603,6 +4603,8 @@ __PACKAGE__->register_method({
}, },
}, },
returns => { returns => {
# TODO 9.x: rework the api call to return more sensible structures
# e.g. a simple list of nodes with their blockers and/or notices to show
type => "object", type => "object",
properties => { properties => {
running => { running => {
@ -4616,7 +4618,7 @@ __PACKAGE__->register_method({
description => "An allowed node", description => "An allowed node",
}, },
optional => 1, optional => 1,
description => "List nodes allowed for offline migration, only passed if VM is offline" description => "List of nodes allowed for migration.",
}, },
not_allowed_nodes => { not_allowed_nodes => {
type => 'object', type => 'object',
@ -4632,7 +4634,7 @@ __PACKAGE__->register_method({
}, },
}, },
}, },
description => "List not allowed nodes with additional information, only passed if VM is offline" description => "List of not allowed nodes with additional information.",
}, },
local_disks => { local_disks => {
type => 'array', type => 'array',
@ -4710,37 +4712,40 @@ __PACKAGE__->register_method({
my ($local_resources, $mapped_resources, $missing_mappings_by_node) = my ($local_resources, $mapped_resources, $missing_mappings_by_node) =
PVE::QemuServer::check_local_resources($vmconf, $res->{running}, 1); PVE::QemuServer::check_local_resources($vmconf, $res->{running}, 1);
delete $missing_mappings_by_node->{$localnode};
my $vga = PVE::QemuServer::parse_vga($vmconf->{vga}); my $vga = PVE::QemuServer::parse_vga($vmconf->{vga});
if ($res->{running} && $vga->{'clipboard'} && $vga->{'clipboard'} eq 'vnc') { if ($res->{running} && $vga->{'clipboard'} && $vga->{'clipboard'} eq 'vnc') {
push $local_resources->@*, "clipboard=vnc"; push $local_resources->@*, "clipboard=vnc";
} }
# if vm is not running, return target nodes where local storage/mapped devices are available $res->{allowed_nodes} = [];
# for offline migration $res->{not_allowed_nodes} = {};
if (!$res->{running}) {
$res->{allowed_nodes} = [];
my $checked_nodes = PVE::QemuServer::check_local_storage_availability($vmconf, $storecfg);
delete $checked_nodes->{$localnode};
foreach my $node (keys %$checked_nodes) { my $storage_nodehash = PVE::QemuServer::check_local_storage_availability($vmconf, $storecfg);
my $missing_mappings = $missing_mappings_by_node->{$node};
if (scalar($missing_mappings->@*)) {
$checked_nodes->{$node}->{'unavailable-resources'} = $missing_mappings;
next;
}
if (!defined($checked_nodes->{$node}->{unavailable_storages})) { my $nodelist = PVE::Cluster::get_nodelist();
push @{$res->{allowed_nodes}}, $node; for my $node ($nodelist->@*) {
} next if $node eq $localnode;
# extract missing storage info
if (my $storage_info = $storage_nodehash->{$node}) {
$res->{not_allowed_nodes}->{$node} = $storage_info;
}
# extract missing mappings info
my $missing_mappings = $missing_mappings_by_node->{$node};
if (scalar($missing_mappings->@*)) {
$res->{not_allowed_nodes}->{$node}->{'unavailable-resources'} = $missing_mappings;
}
# if nothing came up, add it to the allowed nodes
if (scalar($res->{not_allowed_nodes}->{$node}->%*) == 0) {
push $res->{allowed_nodes}->@*, $node;
} }
$res->{not_allowed_nodes} = $checked_nodes;
} }
my $local_disks = &$check_vm_disks_local($storecfg, $vmconf, $vmid); my $local_disks = &$check_vm_disks_local($storecfg, $vmconf, $vmid);
$res->{local_disks} = [ values %$local_disks ];; $res->{local_disks} = [ values %$local_disks ];
$res->{local_resources} = $local_resources; $res->{local_resources} = $local_resources;
$res->{'mapped-resources'} = [ sort keys $mapped_resources->%* ]; $res->{'mapped-resources'} = [ sort keys $mapped_resources->%* ];