api/ui: improve mdev listing for pci mappings

Currently, when we have a PCI resource mapping, we manually check only
the available models for the first PCI entry. This often works, but not
always, since one could have completely different devices in one
mapping, or with the new NVIDIA sysfs api we don't get the generally
available models.

To improve this, extend the parameter for the PCI ID to accept both,
PCI IDs or named mappings, and for the latter mappings, iterate over
all local PCI devices in it and extract the mdev types.

Rename also the parameter to better reflect what it accepts. While the
this is changing a API parameter, it's not a breaking change in this
specific case because the parameter is derived from the URL path, and
any attempt to include the parameter with a name manually is not
possible and  will result in an error:

  duplicate parameter (already defined in URI) with conflicting values!

Since we cannot reach the API handler without giving the parameter
already via the URL, there is no way to give it via name.

Accepting named mappings directly in this API endpoint also vastly
simplifies the UI code, since we now only have to give the mapping to
the selector instead of an (arbitrarily selected) PCI id from that
mapping.

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
 [ TL: also split pciid into pci-id for readability and reword message
   slightly ]
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
This commit is contained in:
Dominik Csapak 2024-10-30 09:59:44 +01:00 committed by Thomas Lamprecht
parent 07f600f7b8
commit 8b33297c6e
2 changed files with 38 additions and 19 deletions

View File

@ -135,7 +135,7 @@ __PACKAGE__->register_method ({
__PACKAGE__->register_method ({
name => 'pciindex',
path => '{pciid}',
path => '{pci-id-or-mapping}',
method => 'GET',
description => "Index of available pci methods",
permissions => {
@ -145,9 +145,9 @@ __PACKAGE__->register_method ({
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
pciid => {
'pci-id-or-mapping' => {
type => 'string',
pattern => '(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]',
pattern => '(?:(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F])|([a-zA-Z][a-zA-Z0-9_-]+)',
},
},
},
@ -171,7 +171,7 @@ __PACKAGE__->register_method ({
__PACKAGE__->register_method ({
name => 'mdevscan',
path => '{pciid}/mdev',
path => '{pci-id-or-mapping}/mdev',
method => 'GET',
description => "List mediated device types for given PCI device.",
protected => 1,
@ -183,10 +183,10 @@ __PACKAGE__->register_method ({
additionalProperties => 0,
properties => {
node => get_standard_option('pve-node'),
pciid => {
'pci-id-or-mapping' => {
type => 'string',
pattern => '(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]',
description => "The PCI ID to list the mdev types for."
pattern => '(?:(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F])|([a-zA-Z][a-zA-Z0-9_-]+)',
description => "The PCI ID or mapping to list the mdev types for."
},
},
},
@ -206,6 +206,12 @@ __PACKAGE__->register_method ({
},
description => {
type => 'string',
description => "Additional description of the type."
},
name => {
type => 'string',
optional => 1,
description => 'A human readable name for the type.',
},
},
},
@ -213,5 +219,28 @@ __PACKAGE__->register_method ({
code => sub {
my ($param) = @_;
return PVE::SysFSTools::get_mdev_types($param->{pciid});
if ($param->{'pci-id-or-mapping'} =~ m/^(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]$/) {
return PVE::SysFSTools::get_mdev_types($param->{'pci-id-or-mapping'}); # PCI ID
} else {
my $mapping = $param->{'pci-id-or-mapping'};
my $types = {};
my $devices = PVE::Mapping::PCI::find_on_current_node($mapping);
for my $device ($devices->@*) {
my $id = $device->{path};
next if $id =~ m/;/; # mdev not supported for multifunction devices
my $device_types = PVE::SysFSTools::get_mdev_types($id);
for my $type_definition ($device_types->@*) {
my $type = $type_definition->{type};
if (!defined($types->{$type})) {
$types->{$type} = $type_definition;
}
}
}
return [sort { $a->{type} cmp $b->{type} } values($types->%*)];
}
}});

View File

@ -67,17 +67,7 @@ Ext.define('PVE.qemu.PCIInputPanel', {
let path = value;
if (pciDev.data.map) {
// find local mapping
for (const entry of pciDev.data.map) {
let mapping = PVE.Parser.parsePropertyString(entry);
if (mapping.node === pcisel.up('inputpanel').nodename) {
path = mapping.path.split(';')[0];
break;
}
}
if (path.indexOf('.') === -1) {
path += '.0';
}
path = pciDev.data.id;
}
if (pciDev.data.mdev) {