all lists on lists.proxmox.com
 help / color / mirror / Atom feed
* [PATCH common/manager 0/3] fix #7803: 'localhost' alias handling in node-specific endpoints
@ 2026-07-14 14:50 Elias Huhsovitz
  2026-07-14 14:50 ` [PATCH common 1/3] inotify: add helper to resolve 'localhost' node alias Elias Huhsovitz
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Elias Huhsovitz @ 2026-07-14 14:50 UTC (permalink / raw)
  To: pve-devel; +Cc: Elias Huhsovitz

This series fixes bug #7803, where API endpoints like
/nodes/localhost/config and /nodes/localhost/certificates/info return
empty data or fail, while the same endpoints work correctly when using
the actual node name (e.g., /nodes/node1/config).

The API routing layer correctly proxies
'localhost' to the local node, but the endpoint handlers use the literal
string 'localhost' to construct file paths in the cluster filesystem.
Since no node directory named 'localhost' exists, the file
lookups fail.

To resolve this, the first patch introduces a
PVE::INotify::resolve_nodename() helper in pve-common to centralize the
alias resolution. The subsequent patches apply this helper to the
affected endpoints in pve-manager (NodeConfig, Certificates, RRD,
migrateall) and refactor existing inline resolutions in the bulk
operation endpoints (startall, stopall, suspendall) for consistency.

Note: The pve-common patch (1/3) must be applied and built before the
pve-manager patches, as the API changes depend on the new helper
function.


pve-common:

Elias Huhsovitz (1):
  inotify: add helper to resolve 'localhost' node alias

 src/PVE/INotify.pm | 5 +++++
 1 file changed, 5 insertions(+)


pve-manager:

Elias Huhsovitz (2):
  fix #7803: api: nodes: resolve 'localhost' alias in node-specific
    endpoints
  api: nodes: use resolve_nodename helper for bulk operation

 PVE/API2/Ceph/MDS.pm     |  3 +--
 PVE/API2/Certificates.pm |  8 +++++---
 PVE/API2/NodeConfig.pm   |  6 ++++--
 PVE/API2/Nodes.pm        | 22 +++++++++-------------
 4 files changed, 19 insertions(+), 20 deletions(-)


Summary over all repositories:
  5 files changed, 24 insertions(+), 20 deletions(-)

-- 
Generated by murpp 0.12.0




^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH common 1/3] inotify: add helper to resolve 'localhost' node alias
  2026-07-14 14:50 [PATCH common/manager 0/3] fix #7803: 'localhost' alias handling in node-specific endpoints Elias Huhsovitz
@ 2026-07-14 14:50 ` Elias Huhsovitz
  2026-07-14 14:50 ` [PATCH manager 2/3] fix #7803: api: nodes: resolve 'localhost' alias in node-specific endpoints Elias Huhsovitz
  2026-07-14 14:50 ` [PATCH manager 3/3] api: nodes: use resolve_nodename helper for bulk operation Elias Huhsovitz
  2 siblings, 0 replies; 5+ messages in thread
From: Elias Huhsovitz @ 2026-07-14 14:50 UTC (permalink / raw)
  To: pve-devel; +Cc: Elias Huhsovitz

Several API endpoints accept 'localhost' as a valid node alias via the
API routing layer. However, the endpoint handlers often use the literal
string 'localhost' to construct file paths in the cluster filesystem
(e.g., /etc/pve/nodes/localhost/config), which fails because no actual
node directory with that name exists.

Add a PVE::INotify::resolve_nodename() helper to centralize the
translation of 'localhost' to the actual node name. This ensures
consistent behavior. across multiple API handlers.

Signed-off-by: Elias Huhsovitz <e.huhsovitz@proxmox.com>
---
 src/PVE/INotify.pm | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/PVE/INotify.pm b/src/PVE/INotify.pm
index 53b4e21..25ea0b8 100644
--- a/src/PVE/INotify.pm
+++ b/src/PVE/INotify.pm
@@ -533,6 +533,11 @@ sub nodename {
     return $cached_nodename;
 }
 
+sub resolve_nodename {
+    my ($node) = @_;
+    return $node eq 'localhost' ? nodename() : $node;
+}
+
 sub read_etc_hostname {
     my ($filename, $fd) = @_;
 
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH manager 2/3] fix #7803: api: nodes: resolve 'localhost' alias in node-specific endpoints
  2026-07-14 14:50 [PATCH common/manager 0/3] fix #7803: 'localhost' alias handling in node-specific endpoints Elias Huhsovitz
  2026-07-14 14:50 ` [PATCH common 1/3] inotify: add helper to resolve 'localhost' node alias Elias Huhsovitz
@ 2026-07-14 14:50 ` Elias Huhsovitz
  2026-07-14 14:57   ` Shannon Sterz
  2026-07-14 14:50 ` [PATCH manager 3/3] api: nodes: use resolve_nodename helper for bulk operation Elias Huhsovitz
  2 siblings, 1 reply; 5+ messages in thread
From: Elias Huhsovitz @ 2026-07-14 14:50 UTC (permalink / raw)
  To: pve-devel; +Cc: Elias Huhsovitz

When 'localhost' is used as the node parameter, the API proxy correctly
routes the request to the local node. However, several endpoint handlers
used the literal string 'localhost' to construct file paths or validate
cluster nodes, resulting in empty data or validation errors.

Use the new PVE::INotify::resolve_nodename() helper to correctly resolve
the alias before accessing the cluster filesystem or checking node
existence. This fixes the following endpoints:
- NodeConfig (get_config, set_options)
- Certificates (info, upload_custom_cert, remove_custom_cert)
- Nodes (rrd, rrddata, migrateall)

Signed-off-by: Elias Huhsovitz <e.huhsovitz@proxmox.com>
---
 PVE/API2/Certificates.pm |  8 +++++---
 PVE/API2/NodeConfig.pm   |  6 ++++--
 PVE/API2/Nodes.pm        | 13 ++++++-------
 3 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/PVE/API2/Certificates.pm b/PVE/API2/Certificates.pm
index de8762c5..d567939c 100644
--- a/PVE/API2/Certificates.pm
+++ b/PVE/API2/Certificates.pm
@@ -7,6 +7,7 @@ use PVE::API2::ACME;
 use PVE::Certificate;
 use PVE::CertHelpers;
 use PVE::Exception qw(raise_param_exc);
+use PVE::INotify;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::Tools qw(extract_param file_get_contents file_set_contents);
 
@@ -66,7 +67,8 @@ __PACKAGE__->register_method({
     code => sub {
         my ($param) = @_;
 
-        my $node_path = "/etc/pve/nodes/$param->{node}";
+        my $node = PVE::INotify::resolve_nodename($param->{node});
+        my $node_path = "/etc/pve/nodes/$node";
 
         my $res = [];
         my $cert_paths = [
@@ -125,7 +127,7 @@ __PACKAGE__->register_method({
     code => sub {
         my ($param) = @_;
 
-        my $node = extract_param($param, 'node');
+        my $node = PVE::INotify::resolve_nodename(extract_param($param, 'node'));
         my $cert_prefix = PVE::CertHelpers::cert_path_prefix($node);
 
         my $certs = extract_param($param, 'certificates');
@@ -188,7 +190,7 @@ __PACKAGE__->register_method({
     code => sub {
         my ($param) = @_;
 
-        my $node = extract_param($param, 'node');
+        my $node = PVE::INotify::resolve_nodename(extract_param($param, 'node'));
         my $cert_prefix = PVE::CertHelpers::cert_path_prefix($node);
 
         my $code = sub {
diff --git a/PVE/API2/NodeConfig.pm b/PVE/API2/NodeConfig.pm
index cc726dac..cad81c3e 100644
--- a/PVE/API2/NodeConfig.pm
+++ b/PVE/API2/NodeConfig.pm
@@ -3,6 +3,7 @@ package PVE::API2::NodeConfig;
 use strict;
 use warnings;
 
+use PVE::INotify;
 use PVE::JSONSchema qw(get_standard_option);
 use PVE::NodeConfig;
 use PVE::Tools qw(extract_param);
@@ -61,7 +62,8 @@ __PACKAGE__->register_method({
     code => sub {
         my ($param) = @_;
 
-        my $config = PVE::NodeConfig::load_config($param->{node});
+        my $node = PVE::INotify::resolve_nodename($param->{node});
+        my $config = PVE::NodeConfig::load_config($node);
 
         if (defined(my $prop = $param->{property})) {
             return {} if !exists $config->{$prop};
@@ -91,7 +93,7 @@ __PACKAGE__->register_method({
         my ($param) = @_;
 
         my $delete = extract_param($param, 'delete');
-        my $node = extract_param($param, 'node');
+        my $node = PVE::INotify::resolve_nodename(extract_param($param, 'node'));
         my $digest = extract_param($param, 'digest');
 
         my $code = sub {
diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
index dfe3b4cf..90ce3c10 100644
--- a/PVE/API2/Nodes.pm
+++ b/PVE/API2/Nodes.pm
@@ -830,9 +830,9 @@ __PACKAGE__->register_method({
     },
     code => sub {
         my ($param) = @_;
-
+        my $node = PVE::INotify::resolve_nodename($param->{node});
         return PVE::RRD::create_rrd_graph(
-            "pve-node-9.0/$param->{node}", $param->{timeframe}, $param->{ds}, $param->{cf},
+            "pve-node-9.0/$node", $param->{timeframe}, $param->{ds}, $param->{cf},
         );
 
     },
@@ -873,9 +873,9 @@ __PACKAGE__->register_method({
     },
     code => sub {
         my ($param) = @_;
-
+        my $node = PVE::INotify::resolve_nodename($param->{node});
         return PVE::RRD::create_rrd_data(
-            "pve-node-9.0/$param->{node}", $param->{timeframe}, $param->{cf},
+            "pve-node-9.0/$node", $param->{timeframe}, $param->{cf},
         );
     },
 });
@@ -2718,10 +2718,9 @@ __PACKAGE__->register_method({
             }
         }
 
-        my $nodename = $param->{node};
-        $nodename = PVE::INotify::nodename() if $nodename eq 'localhost';
+        my $nodename = PVE::INotify::resolve_nodename($param->{node});
 
-        my $target = $param->{target};
+        my $target = PVE::INotify::resolve_nodename($param->{target});
         my $with_local_disks = $param->{'with-local-disks'};
         raise_param_exc({ target => "target is local node." }) if $target eq $nodename;
 
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH manager 3/3] api: nodes: use resolve_nodename helper for bulk operation
  2026-07-14 14:50 [PATCH common/manager 0/3] fix #7803: 'localhost' alias handling in node-specific endpoints Elias Huhsovitz
  2026-07-14 14:50 ` [PATCH common 1/3] inotify: add helper to resolve 'localhost' node alias Elias Huhsovitz
  2026-07-14 14:50 ` [PATCH manager 2/3] fix #7803: api: nodes: resolve 'localhost' alias in node-specific endpoints Elias Huhsovitz
@ 2026-07-14 14:50 ` Elias Huhsovitz
  2 siblings, 0 replies; 5+ messages in thread
From: Elias Huhsovitz @ 2026-07-14 14:50 UTC (permalink / raw)
  To: pve-devel; +Cc: Elias Huhsovitz

The startall, stopall, and suspendall endpoints already contained inline
logic to resolve the 'localhost' alias to the actual node name. Refactor
these endpoints to use the new PVE::INotify::resolve_nodename() helper,
improving consistency.

Signed-off-by: Elias Huhsovitz <e.huhsovitz@proxmox.com>
---
 PVE/API2/Ceph/MDS.pm | 3 +--
 PVE/API2/Nodes.pm    | 9 +++------
 2 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/PVE/API2/Ceph/MDS.pm b/PVE/API2/Ceph/MDS.pm
index 31b6fb7e..f9986d03 100644
--- a/PVE/API2/Ceph/MDS.pm
+++ b/PVE/API2/Ceph/MDS.pm
@@ -167,8 +167,7 @@ __PACKAGE__->register_method({
         my $rpcenv = PVE::RPCEnvironment::get();
         my $authuser = $rpcenv->get_user();
 
-        my $nodename = $param->{node};
-        $nodename = INotify::nodename() if $nodename eq 'localhost';
+        my $nodename = PVE::INotify::resolve_nodename($param->{node});
 
         my $mds_id = $param->{name} // $nodename;
 
diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
index 90ce3c10..143da68a 100644
--- a/PVE/API2/Nodes.pm
+++ b/PVE/API2/Nodes.pm
@@ -2182,8 +2182,7 @@ __PACKAGE__->register_method({
             }
         }
 
-        my $nodename = $param->{node};
-        $nodename = PVE::INotify::nodename() if $nodename eq 'localhost';
+        my $nodename = PVE::INotify::resolve_nodename($param->{node});
 
         my $force = $param->{force};
 
@@ -2380,8 +2379,7 @@ __PACKAGE__->register_method({
             }
         }
 
-        my $nodename = $param->{node};
-        $nodename = PVE::INotify::nodename() if $nodename eq 'localhost';
+        my $nodename = PVE::INotify::resolve_nodename($param->{node});
 
         my $code = sub {
 
@@ -2518,8 +2516,7 @@ __PACKAGE__->register_method({
             }
         }
 
-        my $nodename = $param->{node};
-        $nodename = PVE::INotify::nodename() if $nodename eq 'localhost';
+        my $nodename = PVE::INotify::resolve_nodename($param->{node});
 
         my $code = sub {
 
-- 
2.47.3





^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH manager 2/3] fix #7803: api: nodes: resolve 'localhost' alias in node-specific endpoints
  2026-07-14 14:50 ` [PATCH manager 2/3] fix #7803: api: nodes: resolve 'localhost' alias in node-specific endpoints Elias Huhsovitz
@ 2026-07-14 14:57   ` Shannon Sterz
  0 siblings, 0 replies; 5+ messages in thread
From: Shannon Sterz @ 2026-07-14 14:57 UTC (permalink / raw)
  To: Elias Huhsovitz, pve-devel

On Tue Jul 14, 2026 at 4:50 PM CEST, Elias Huhsovitz wrote:
> When 'localhost' is used as the node parameter, the API proxy correctly
> routes the request to the local node. However, several endpoint handlers
> used the literal string 'localhost' to construct file paths or validate
> cluster nodes, resulting in empty data or validation errors.
>
> Use the new PVE::INotify::resolve_nodename() helper to correctly resolve
> the alias before accessing the cluster filesystem or checking node
> existence. This fixes the following endpoints:
> - NodeConfig (get_config, set_options)
> - Certificates (info, upload_custom_cert, remove_custom_cert)
> - Nodes (rrd, rrddata, migrateall)
>
> Signed-off-by: Elias Huhsovitz <e.huhsovitz@proxmox.com>
> ---
>  PVE/API2/Certificates.pm |  8 +++++---
>  PVE/API2/NodeConfig.pm   |  6 ++++--
>  PVE/API2/Nodes.pm        | 13 ++++++-------
>  3 files changed, 15 insertions(+), 12 deletions(-)
>
> diff --git a/PVE/API2/Certificates.pm b/PVE/API2/Certificates.pm
> index de8762c5..d567939c 100644
> --- a/PVE/API2/Certificates.pm
> +++ b/PVE/API2/Certificates.pm
> @@ -7,6 +7,7 @@ use PVE::API2::ACME;
>  use PVE::Certificate;
>  use PVE::CertHelpers;
>  use PVE::Exception qw(raise_param_exc);
> +use PVE::INotify;
>  use PVE::JSONSchema qw(get_standard_option);
>  use PVE::Tools qw(extract_param file_get_contents file_set_contents);
>
> @@ -66,7 +67,8 @@ __PACKAGE__->register_method({
>      code => sub {
>          my ($param) = @_;
>
> -        my $node_path = "/etc/pve/nodes/$param->{node}";
> +        my $node = PVE::INotify::resolve_nodename($param->{node});
> +        my $node_path = "/etc/pve/nodes/$node";

this hunk overlaps with my commit in the tls rotation series [1]. since
your series tackles this problem in a more complete fashion, the commit
in my series can simply be dropped if your patches make it in first.

just thought i'd mention it here :)

[1]: https://lore.proxmox.com/pdm-devel/20260611120327.257523-4-s.sterz@proxmox.com/

>
>          my $res = [];
>          my $cert_paths = [
> @@ -125,7 +127,7 @@ __PACKAGE__->register_method({
>      code => sub {
>          my ($param) = @_;
>
> -        my $node = extract_param($param, 'node');
> +        my $node = PVE::INotify::resolve_nodename(extract_param($param, 'node'));
>          my $cert_prefix = PVE::CertHelpers::cert_path_prefix($node);
>
>          my $certs = extract_param($param, 'certificates');
> @@ -188,7 +190,7 @@ __PACKAGE__->register_method({
>      code => sub {
>          my ($param) = @_;
>
> -        my $node = extract_param($param, 'node');
> +        my $node = PVE::INotify::resolve_nodename(extract_param($param, 'node'));
>          my $cert_prefix = PVE::CertHelpers::cert_path_prefix($node);
>
>          my $code = sub {
> diff --git a/PVE/API2/NodeConfig.pm b/PVE/API2/NodeConfig.pm
> index cc726dac..cad81c3e 100644
> --- a/PVE/API2/NodeConfig.pm
> +++ b/PVE/API2/NodeConfig.pm
> @@ -3,6 +3,7 @@ package PVE::API2::NodeConfig;
>  use strict;
>  use warnings;
>
> +use PVE::INotify;
>  use PVE::JSONSchema qw(get_standard_option);
>  use PVE::NodeConfig;
>  use PVE::Tools qw(extract_param);
> @@ -61,7 +62,8 @@ __PACKAGE__->register_method({
>      code => sub {
>          my ($param) = @_;
>
> -        my $config = PVE::NodeConfig::load_config($param->{node});
> +        my $node = PVE::INotify::resolve_nodename($param->{node});
> +        my $config = PVE::NodeConfig::load_config($node);
>
>          if (defined(my $prop = $param->{property})) {
>              return {} if !exists $config->{$prop};
> @@ -91,7 +93,7 @@ __PACKAGE__->register_method({
>          my ($param) = @_;
>
>          my $delete = extract_param($param, 'delete');
> -        my $node = extract_param($param, 'node');
> +        my $node = PVE::INotify::resolve_nodename(extract_param($param, 'node'));
>          my $digest = extract_param($param, 'digest');
>
>          my $code = sub {
> diff --git a/PVE/API2/Nodes.pm b/PVE/API2/Nodes.pm
> index dfe3b4cf..90ce3c10 100644
> --- a/PVE/API2/Nodes.pm
> +++ b/PVE/API2/Nodes.pm
> @@ -830,9 +830,9 @@ __PACKAGE__->register_method({
>      },
>      code => sub {
>          my ($param) = @_;
> -
> +        my $node = PVE::INotify::resolve_nodename($param->{node});
>          return PVE::RRD::create_rrd_graph(
> -            "pve-node-9.0/$param->{node}", $param->{timeframe}, $param->{ds}, $param->{cf},
> +            "pve-node-9.0/$node", $param->{timeframe}, $param->{ds}, $param->{cf},
>          );
>
>      },
> @@ -873,9 +873,9 @@ __PACKAGE__->register_method({
>      },
>      code => sub {
>          my ($param) = @_;
> -
> +        my $node = PVE::INotify::resolve_nodename($param->{node});
>          return PVE::RRD::create_rrd_data(
> -            "pve-node-9.0/$param->{node}", $param->{timeframe}, $param->{cf},
> +            "pve-node-9.0/$node", $param->{timeframe}, $param->{cf},
>          );
>      },
>  });
> @@ -2718,10 +2718,9 @@ __PACKAGE__->register_method({
>              }
>          }
>
> -        my $nodename = $param->{node};
> -        $nodename = PVE::INotify::nodename() if $nodename eq 'localhost';
> +        my $nodename = PVE::INotify::resolve_nodename($param->{node});
>
> -        my $target = $param->{target};
> +        my $target = PVE::INotify::resolve_nodename($param->{target});
>          my $with_local_disks = $param->{'with-local-disks'};
>          raise_param_exc({ target => "target is local node." }) if $target eq $nodename;
>





^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-07-14 14:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 14:50 [PATCH common/manager 0/3] fix #7803: 'localhost' alias handling in node-specific endpoints Elias Huhsovitz
2026-07-14 14:50 ` [PATCH common 1/3] inotify: add helper to resolve 'localhost' node alias Elias Huhsovitz
2026-07-14 14:50 ` [PATCH manager 2/3] fix #7803: api: nodes: resolve 'localhost' alias in node-specific endpoints Elias Huhsovitz
2026-07-14 14:57   ` Shannon Sterz
2026-07-14 14:50 ` [PATCH manager 3/3] api: nodes: use resolve_nodename helper for bulk operation Elias Huhsovitz

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