all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Leo Nunner <l.nunner@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH qemu-server 1/2] fix #4068: implement support for fw_cfg
Date: Wed,  1 Mar 2023 10:12:26 +0100	[thread overview]
Message-ID: <20230301091229.53505-2-l.nunner@proxmox.com> (raw)
In-Reply-To: <20230301091229.53505-1-l.nunner@proxmox.com>

Implements support for passing values to the fw_cfg argument for QEMU.
If the value looks like a file, the backend checks for the correct
permissions/path and if everything is right, includes it as a file
instead of as a string.

Setting the argument requires the VM.Config.Options permission on the
guest. Including files requires Datastore.Audit and Datastore.Allocate
on the specific storage.

Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
RFC: I feel like a more implicit option for passing files would be
nicer, but I can't really think of a nice way…

 PVE/API2/Qemu.pm  | 14 ++++++++++++++
 PVE/QemuServer.pm | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 587bb22..c03394f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -639,6 +639,8 @@ my $check_vm_modify_config_perm = sub {
 	    # the user needs Disk and PowerMgmt privileges to change the vmstate
 	    # also needs privileges on the storage, that will be checked later
 	    $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Disk', 'VM.PowerMgmt' ]);
+	} elsif ($opt eq 'fw_cfg') {
+	    $rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Options']);
 	} else {
 	    # catches hostpci\d+, args, lock, etc.
 	    # new options will be checked here
@@ -1770,6 +1772,18 @@ my $update_vm_api  = sub {
 		} elsif ($opt eq 'tags') {
 		    assert_tag_permissions($vmid, $conf->{$opt}, $param->{$opt}, $rpcenv, $authuser);
 		    $conf->{pending}->{$opt} = PVE::GuestHelpers::get_unique_tags($param->{$opt});
+		} elsif ($opt eq 'fw_cfg') {
+		    foreach my $fw_cfg (PVE::Tools::split_list($param->{$opt})) {
+			my ($opt, $val) = split("=", $fw_cfg);
+
+			if (my $storage = PVE::Storage::parse_volume_id($val, 1)) {
+			    $rpcenv->check($authuser, "/storage/$storage", ['Datastore.Audit', 'Datastore.Allocate']);
+
+			    my ($path, undef, $type) = PVE::Storage::path($storecfg, $val);
+			    die "File $val is not in snippets directory\n" if $type ne "snippets";
+			}
+		    }
+		    $conf->{pending}->{$opt} = $param->{$opt};
 		} else {
 		    $conf->{pending}->{$opt} = $param->{$opt};
 
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 40be44d..c5dea1f 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -723,6 +723,12 @@ EODESCR
 	description => "List of host cores used to execute guest processes, for example: 0,5,8-11",
 	optional => 1,
     },
+    fw_cfg => {
+	type => 'string',
+	optional => 1,
+	description => 'Pass values to the guest via the fw_cfg parameter.',
+	format => 'pve-fw-cfg-list',
+    },
 };
 
 my $cicustom_fmt = {
@@ -1076,6 +1082,21 @@ sub verify_volume_id_or_absolute_path {
     return $volid;
 }
 
+PVE::JSONSchema::register_format('pve-fw-cfg', \&verify_fw_cfg);
+sub verify_fw_cfg {
+    my ($value, $noerr) = @_;
+
+    my $FW_CFG_REGEX = qr/[a-z0-9\.\/:\-]+/;
+
+    if ($value =~ m/^(opt\/$FW_CFG_REGEX)=($FW_CFG_REGEX)$/) {
+	return $value;
+    }
+
+    return if $noerr;
+
+    die "unable to parse fw_cfg option\n";
+}
+
 my $usb_fmt = {
     host => {
 	default_key => 1,
@@ -4181,6 +4202,20 @@ sub config_to_command {
 	push @$cmd, '-snapshot';
     }
 
+    if ($conf->{fw_cfg}) {
+	foreach my $conf (PVE::Tools::split_list($conf->{fw_cfg})) {
+	    my ($opt, $val) = split("=", $conf);
+
+	    push @$cmd, "-fw_cfg";
+	    if (PVE::Storage::parse_volume_id($val, 1)) {
+		my $path = PVE::Storage::path($storecfg, $val);
+		push @$cmd, "$opt,file=$path";
+	    } else {
+		push @$cmd, "$opt,string=$val";
+	    }
+	}
+    }
+
     # add custom args
     if ($conf->{args}) {
 	my $aa = PVE::Tools::split_args($conf->{args});
-- 
2.30.2





  reply	other threads:[~2023-03-01  9:13 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-01  9:12 [pve-devel] [PATCH qemu-server docs manager] Implement " Leo Nunner
2023-03-01  9:12 ` Leo Nunner [this message]
2023-03-15 14:05   ` [pve-devel] [PATCH qemu-server 1/2] fix #4068: implement " Wolfgang Bumiller
2023-03-24  9:43     ` Leo Nunner
2023-03-01  9:12 ` [pve-devel] [PATCH qemu-server 2/2] test: add cfg2cmd tests " Leo Nunner
2023-03-01  9:12 ` [pve-devel] [PATCH docs] fix #4068: document fw_cfg parameter Leo Nunner
2023-03-01  9:12 ` [pve-devel] [PATCH manager] fix #4068: expose fw_cfg through the GUI Leo Nunner

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=20230301091229.53505-2-l.nunner@proxmox.com \
    --to=l.nunner@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