From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH common 3/3] add PVE/HardwareMap and Plugins
Date: Mon, 21 Jun 2021 15:55:17 +0200 [thread overview]
Message-ID: <20210621135534.14807-5-d.csapak@proxmox.com> (raw)
In-Reply-To: <20210621135534.14807-1-d.csapak@proxmox.com>
adds the Top level package PVE::HardwareMap that
registers the Plugins for the config, as well
as provides some convenience methods
(find_device_on_current_node, lock/write/get config)
The Plugins themselves are usual SectionConfigs plugins
with (for now) two types: usb, pci
each type gets an 'assert_device_valid' method that
checks the local node for validity of the device
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
---
src/Makefile | 4 ++
src/PVE/HardwareMap.pm | 54 ++++++++++++++++++++
src/PVE/HardwareMap/PCIPlugin.pm | 87 ++++++++++++++++++++++++++++++++
src/PVE/HardwareMap/Plugin.pm | 82 ++++++++++++++++++++++++++++++
src/PVE/HardwareMap/USBPlugin.pm | 69 +++++++++++++++++++++++++
5 files changed, 296 insertions(+)
create mode 100644 src/PVE/HardwareMap.pm
create mode 100644 src/PVE/HardwareMap/PCIPlugin.pm
create mode 100644 src/PVE/HardwareMap/Plugin.pm
create mode 100644 src/PVE/HardwareMap/USBPlugin.pm
diff --git a/src/Makefile b/src/Makefile
index 13de6c6..7cd20d5 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -17,6 +17,10 @@ LIB_SOURCES = \
Daemon.pm \
Exception.pm \
Format.pm \
+ HardwareMap.pm \
+ HardwareMap/Plugin.pm \
+ HardwareMap/PCIPlugin.pm \
+ HardwareMap/USBPlugin.pm \
INotify.pm \
JSONSchema.pm \
LDAP.pm \
diff --git a/src/PVE/HardwareMap.pm b/src/PVE/HardwareMap.pm
new file mode 100644
index 0000000..a0f4a9f
--- /dev/null
+++ b/src/PVE/HardwareMap.pm
@@ -0,0 +1,54 @@
+package PVE::HardwareMap;
+
+use strict;
+use warnings;
+
+use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
+use PVE::HardwareMap::Plugin;
+use PVE::HardwareMap::PCIPlugin;
+use PVE::HardwareMap::USBPlugin;
+use PVE::INotify;
+
+use base qw(Exporter);
+
+our @EXPORT_OK = qw(find_device_on_current_node);
+
+PVE::HardwareMap::PCIPlugin->register();
+PVE::HardwareMap::USBPlugin->register();
+
+PVE::HardwareMap::Plugin->init();
+
+sub find_device_on_current_node {
+ my ($type, $id) = @_;
+
+ my $data = cfs_read_file($PVE::HardwareMap::Plugin::FILENAME);
+
+ my $res = {};
+
+ my $node = PVE::INotify::nodename();
+ my $sectionid = "$node:$id";
+
+ return $data->{ids}->{$sectionid};
+}
+
+sub config {
+ return cfs_read_file($PVE::HardwareMap::Plugin::FILENAME);
+}
+
+sub lock_config {
+ my ($code, $errmsg) = @_;
+
+ cfs_lock_file($PVE::HardwareMap::Plugin::FILENAME, undef, $code);
+ if (my $err = $@) {
+ $errmsg ? die "$errmsg: $err" : die $err;
+ }
+}
+
+sub write_config {
+ my ($cfg) = @_;
+
+ cfs_write_file($PVE::HardwareMap::Plugin::FILENAME, $cfg);
+}
+
+
+1;
diff --git a/src/PVE/HardwareMap/PCIPlugin.pm b/src/PVE/HardwareMap/PCIPlugin.pm
new file mode 100644
index 0000000..eb6d090
--- /dev/null
+++ b/src/PVE/HardwareMap/PCIPlugin.pm
@@ -0,0 +1,87 @@
+package PVE::HardwareMap::PCIPlugin;
+
+use strict;
+use warnings;
+
+use PVE::HardwareMap::Plugin;
+use PVE::SysFSTools;
+
+use base qw(PVE::HardwareMap::Plugin);
+
+sub type {
+ return 'pci';
+}
+
+sub properties {
+ return {
+ pcipath => {
+ description => "The path to the device. If the function is omitted, the whole device is mapped. In that case use the attrubes of the first device.",
+ type => 'string',
+ pattern => qr/^[0-9A-Fa-f]{4}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}(:?.[0-9A-Fa-f])?$/,
+ },
+ mdev => {
+ description => "The Device supports mediated devices.",
+ type => 'boolean',
+ },
+ iommugroup => {
+ type => 'integer',
+ description => "The IOMMU group in which the device is in.",
+ }
+ };
+}
+
+sub options {
+ return {
+ node => { fixed => 1 },
+ name => { fixed => 1 },
+ pcipath => { },
+ vendor => { },
+ device => { },
+ iommugroup => { },
+ subsystem_vendor => { optional => 1 },
+ subsystem_device => { optional => 1 },
+ mdev => { optional => 1 },
+ };
+}
+
+sub assert_device_valid {
+ my ($class, $cfg) = @_;
+
+ my $path = $cfg->{pcipath};
+
+ if ($path !~ m/\.[a-f0-9]/i) {
+ # whole device, add .0 (must exist)
+ $path = "$path.0";
+ }
+
+ my $info = PVE::SysFSTools::pci_device_info($path, 1);
+ die "pci device '$path' not found\n" if !defined($info);
+
+ my $props = {
+ vendor => $cfg->{vendor},
+ device => $cfg->{device},
+ subsystem_vendor => $cfg->{subsystem_vendor},
+ subsystem_device => $cfg->{subsystem_device},
+ iommugroup => $cfg->{iommugroup},
+ mdev => $cfg->{mdev},
+ };
+
+ for my $prop (keys %$props) {
+ next if !defined($info->{$prop});
+ die "no '$prop' for device '$path'\n"
+ if defined($info->{$prop}) && !$props->{$prop};
+
+
+ my $correct_prop = $info->{$prop};
+ $correct_prop =~ s/^0x//;
+ my $configured_prop = $props->{$prop};
+ $configured_prop =~ s/^0x//;
+
+ die "'$prop' does not match for '$cfg->{name}' ($correct_prop != $configured_prop)\n"
+ if $correct_prop ne $configured_prop;
+ }
+
+ return 1;
+}
+
+1;
diff --git a/src/PVE/HardwareMap/Plugin.pm b/src/PVE/HardwareMap/Plugin.pm
new file mode 100644
index 0000000..2d33785
--- /dev/null
+++ b/src/PVE/HardwareMap/Plugin.pm
@@ -0,0 +1,82 @@
+package PVE::HardwareMap::Plugin;
+
+use strict;
+use warnings;
+
+use PVE::Cluster qw(cfs_register_file cfs_read_file);
+use PVE::JSONSchema qw(get_standard_option);
+
+use base qw(PVE::SectionConfig);
+
+our $FILENAME = "nodes/hardware-map.conf";
+cfs_register_file($FILENAME,
+ sub { PVE::HardwareMap::Plugin->parse_config(@_); },
+ sub { PVE::HardwareMap::Plugin->write_config(@_); });
+
+my $defaultData = {
+ propertyList => {
+ type => { description => "Hardware Type", },
+ name => {
+ description => "The custom name for the device",
+ type => 'string',
+ format => 'pve-configid',
+ },
+ node => get_standard_option('pve-node'),
+ vendor => {
+ description => "The vendor ID",
+ type => 'string',
+ pattern => qr/^(:?0x)?[0-9A-Fa-f]{4}$/,
+ },
+ device => {
+ description => "The device ID",
+ type => 'string',
+ pattern => qr/^(:?0x)?[0-9A-Fa-f]{4}$/,
+ },
+ subsystem_vendor => {
+ description => "The subsystem vendor ID",
+ type => 'string',
+ pattern => qr/^(:?0x)?[0-9A-Fa-f]{4}$/,
+ optional => 1,
+ },
+ subsystem_device => {
+ description => "The subsystem device ID",
+ type => 'string',
+ pattern => qr/^(:?0x)?[0-9A-Fa-f]{4}$/,
+ optional => 1,
+ },
+ },
+};
+
+sub private {
+ return $defaultData;
+}
+
+sub parse_section_header {
+ my ($class, $line) = @_;
+
+ if ($line =~ m/^(\S+):\s*(\S+):(\S+)\s*$/) {
+ my ($type, $node, $name) = ($1, $2, $3);
+ # TODO verify properties
+ my $errmsg = undef;
+ my $config = {
+ node => $node,
+ name => $name,
+ };
+ return ($type, "$node:$name", $errmsg, $config);
+ }
+ return undef;
+}
+
+sub format_section_header {
+ my ($class, $type, $sectionId, $scfg, $done_hash) = @_;
+ $done_hash->{name} = 1;
+ $done_hash->{node} = 1;
+ return $class->SUPER::format_section_header($type, $sectionId, $scfg, $done_hash);
+}
+
+sub assert_device_valid {
+ my ($cfg) = @_;
+ die "implement me";
+}
+
+1;
diff --git a/src/PVE/HardwareMap/USBPlugin.pm b/src/PVE/HardwareMap/USBPlugin.pm
new file mode 100644
index 0000000..a1fff77
--- /dev/null
+++ b/src/PVE/HardwareMap/USBPlugin.pm
@@ -0,0 +1,69 @@
+package PVE::HardwareMap::USBPlugin;
+
+use strict;
+use warnings;
+
+use PVE::HardwareMap::Plugin;
+
+use base qw(PVE::HardwareMap::Plugin);
+
+sub type {
+ return 'usb';
+}
+
+sub properties {
+ return {
+ usbpath => {
+ description => "The path to the usb device.",
+ type => 'string',
+ pattern => qr/^(\d+)\-(\d+(\.\d+)*)$/,
+ },
+ };
+}
+
+sub options {
+ return {
+ node => { fixed => 1 },
+ name => { fixed => 1 },
+ vendor => { },
+ device => { },
+ usbpath => { optional => 1 },
+ };
+}
+
+sub assert_device_valid {
+ my ($class, $cfg) = @_;
+
+ my $name = $cfg->{name};
+ my $vendor = $cfg->{vendor};
+ my $device = $cfg->{device};
+
+ my $usb_list = PVE::SysFSTools::scan_usb();
+
+ my $info;
+ if (my $path = $cfg->{usbpath}) {
+ for my $dev (@$usb_list) {
+ next if !$dev->{usbpath} || !$dev->{busnum};
+ my $usbpath = "$dev->{busnum}-$dev->{usbpath}";
+ next if $usbpath ne $path;
+ $info = $dev;
+ }
+ die "usb device '$path' not found\n" if !defined($info);
+
+ die "'vendor' does not match for '$name'\n"
+ if $info->{vendid} ne $cfg->{vendor};
+ die "'device' does not match for '$name'\n"
+ if $info->{prodid} ne $cfg->{device};
+ } else {
+ for my $dev (@$usb_list) {
+ next if $dev->{vendid} ne $vendor;
+ next if $dev->{prodid} ne $device;
+ $info = $dev;
+ }
+ die "usb device '$vendor:$device' not found\n" if !defined($info);
+ }
+
+ return 1;
+}
+
+1;
--
2.20.1
next prev parent reply other threads:[~2021-06-21 13:56 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-21 13:55 [pve-devel] [PATCH/RFC cluster/common/... many] add cluster-wide hardware device mapping Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH cluster 1/1] add nodes/hardware-map.conf Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH common 1/3] SysFSTools: add verbose flag to pci_device_info Dominik Csapak
2021-06-21 15:31 ` [pve-devel] applied: " Thomas Lamprecht
2021-06-21 13:55 ` [pve-devel] [PATCH common 2/3] SysFSTools: change 'product' to 'device' Dominik Csapak
2021-06-21 15:31 ` [pve-devel] applied: " Thomas Lamprecht
2021-06-21 13:55 ` Dominik Csapak [this message]
2021-06-21 13:55 ` [pve-devel] [PATCH access-control 1/2] PVE/AccessControl: add Hardware.* privileges and /hardware/ paths Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH access-control 2/2] PVE/RPCEnvironment: add helper for checking hw permissions Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH qemu-server 1/7] PVE/QemuServer: allow mapped usb devices in config Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH qemu-server 2/7] PVE/QemuServer: allow mapped pci deviced " Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH qemu-server 3/7] PVE/API2/Qemu: add permission checks for mapped usb devices Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH qemu-server 4/7] PVE/API2/Qemu: add permission checks for mapped pci devices Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH qemu-server 5/7] PVE/QemuServer: extend 'check_local_resources' for mapped resources Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH qemu-server 6/7] PVE/API2/Qemu: migrate preconditions: use new check_local_resources info Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH qemu-server 7/7] PVE/QemuMigrate: check for mapped resources on migration Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 1/8] PVE/API2/Hardware: add Mapping.pm Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 2/8] ui: form/USBSelector: make it more flexible with nodename Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 3/8] ui: form: add PCIMapSelector Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 4/8] ui: form: add USBMapSelector Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 5/8] ui: node: add HardwareView and relevant edit windows Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 6/8] ui: qemu/PCIEdit: rework panel to add a mapped configuration Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 7/8] ui: qemu/USBEdit: add 'mapped' device case Dominik Csapak
2021-06-21 13:55 ` [pve-devel] [PATCH manager 8/8] ui: window/Migrate: allow mapped devices Dominik Csapak
2021-06-22 7:07 ` [pve-devel] [PATCH/RFC cluster/common/... many] add cluster-wide hardware device mapping Dominik Csapak
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210621135534.14807-5-d.csapak@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal