public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH container manager] Show dynamic container IPs in GUI
@ 2023-04-18  9:31 Leo Nunner
  2023-04-18  9:31 ` [pve-devel] [PATCH container] api: network: get interfaces from containers Leo Nunner
  2023-04-18  9:31 ` [pve-devel] [PATCH manager] lxc: show dynamically assigned IPs in network tab Leo Nunner
  0 siblings, 2 replies; 5+ messages in thread
From: Leo Nunner @ 2023-04-18  9:31 UTC (permalink / raw)
  To: pve-devel

This patch adds an endpoint to the LXC API to read the current
interface configuration (with current name, ipv(4|6), mac) from
inside a running container. The GUI fetches this data, merges it with
the existing configuration and then displays it.

pve-container:

Leo Nunner (1):
  api: network: get interfaces from containers

 src/PVE/API2/LXC.pm | 50 +++++++++++++++++++++++++++++++++++++++++++++
 src/PVE/LXC.pm      | 26 +++++++++++++++++++++++
 2 files changed, 76 insertions(+)

pve-manager:

Leo Nunner (1):
  lxc: show dynamically assigned IPs in network tab

 www/manager6/lxc/Network.js | 57 +++++++++++++++++++++++++++----------
 1 file changed, 42 insertions(+), 15 deletions(-)

-- 
2.30.2





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

* [pve-devel] [PATCH container] api: network: get interfaces from containers
  2023-04-18  9:31 [pve-devel] [PATCH container manager] Show dynamic container IPs in GUI Leo Nunner
@ 2023-04-18  9:31 ` Leo Nunner
  2023-04-18  9:41   ` Lukas Wagner
  2023-04-18  9:31 ` [pve-devel] [PATCH manager] lxc: show dynamically assigned IPs in network tab Leo Nunner
  1 sibling, 1 reply; 5+ messages in thread
From: Leo Nunner @ 2023-04-18  9:31 UTC (permalink / raw)
  To: pve-devel

Adds an 'interfaces' endpoint in the API
(/nodes/{node}/lxc/{vmid}/interfaces'), which returns a list of
interface names, together with a MAC, IPv4 and IPv6 address. This list
may be expanded in the future. Note that this is only returned for
*running* containers, stopped containers simply return an empty list.

Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
 src/PVE/API2/LXC.pm | 50 +++++++++++++++++++++++++++++++++++++++++++++
 src/PVE/LXC.pm      | 26 +++++++++++++++++++++++
 2 files changed, 76 insertions(+)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 50c9eaf..078d506 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -2495,6 +2495,56 @@ __PACKAGE__->register_method({
 	return PVE::GuestHelpers::config_with_pending_array($conf, $pending_delete_hash);
     }});
 
+__PACKAGE__->register_method({
+    name => 'ip',
+    path => '{vmid}/interfaces',
+    method => 'GET',
+    protected => 1,
+    permissions => {
+	check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+    },
+    description => 'Get IP addresses of the specified container interface.',
+    parameters => {
+	additionalProperties => 0,
+	properties => {
+	    node => get_standard_option('pve-node'),
+	    vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid }),
+	},
+    },
+    returns => {
+	type => "array",
+	items => {
+	    type => 'object',
+	    properties => {
+		name => {
+		    type => 'string',
+		    description => 'The name of the interface',
+		    optional => 0,
+		},
+		hwaddr => {
+		    type => 'string',
+		    description => 'The MAC address of the interface',
+		    optional => 0,
+		},
+		inet => {
+		    type => 'string',
+		    description => 'The IPv4 address of the interface',
+		    optional => 1,
+		},
+		inet6 => {
+		    type => 'string',
+		    description => 'The IPv6 address of the interface',
+		    optional => 1,
+		},
+	    }
+	},
+    },
+    code => sub {
+	my ($param) = @_;
+
+	return PVE::LXC::get_interfaces($param->{vmid});
+    }});
+
 __PACKAGE__->register_method({
     name => 'mtunnel',
     path => '{vmid}/mtunnel',
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index c4d53e8..bf57ede 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1034,6 +1034,32 @@ sub hotplug_net {
     PVE::LXC::Config->write_config($vmid, $conf);
 }
 
+sub get_interfaces {
+    my ($vmid) = @_;
+
+    my $pid = eval { find_lxc_pid($vmid); };
+    return if $@;
+
+    my $output;
+    # enters the network namespace of the container and executes 'ip a'
+    run_command(['nsenter', '-t', $pid, '--net', '--', 'ip', '--json', 'a'],
+	outfunc => sub { $output .= shift; });
+
+    my $config = JSON::decode_json($output);
+
+    my $res;
+    foreach my $interface ($config->@*) {
+	my $obj = { name => $interface->{ifname} };
+	foreach my $ip ($interface->{addr_info}->@*) {
+	    $obj->{$ip->{family}} = $ip->{local} . "/" . $ip->{prefixlen};
+	}
+	$obj->{hwaddr} = $interface->{address};
+	push @$res, $obj
+    }
+
+    return $res;
+}
+
 sub update_ipconfig {
     my ($vmid, $conf, $opt, $eth, $newnet, $rootdir) = @_;
 
-- 
2.30.2





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

* [pve-devel] [PATCH manager] lxc: show dynamically assigned IPs in network tab
  2023-04-18  9:31 [pve-devel] [PATCH container manager] Show dynamic container IPs in GUI Leo Nunner
  2023-04-18  9:31 ` [pve-devel] [PATCH container] api: network: get interfaces from containers Leo Nunner
@ 2023-04-18  9:31 ` Leo Nunner
  2023-04-18  9:47   ` Lukas Wagner
  1 sibling, 1 reply; 5+ messages in thread
From: Leo Nunner @ 2023-04-18  9:31 UTC (permalink / raw)
  To: pve-devel

adds a call to /nodes/{node}/lxc/{vmid}/interfaces and merges the
returned data with the existing configuration. This will update the
IPv4 and IPv6 address, as well as the interface name (in case the
container changed it).

Signed-off-by: Leo Nunner <l.nunner@proxmox.com>
---
RFC: I *hope* that the MAC can serve as the "primary key" here, I'm
guessing that there's a higher chance that the interface name changes than
for the MAC changing…

 www/manager6/lxc/Network.js | 57 +++++++++++++++++++++++++++----------
 1 file changed, 42 insertions(+), 15 deletions(-)

diff --git a/www/manager6/lxc/Network.js b/www/manager6/lxc/Network.js
index b2cd9410..6c7929ba 100644
--- a/www/manager6/lxc/Network.js
+++ b/www/manager6/lxc/Network.js
@@ -356,25 +356,52 @@ Ext.define('PVE.lxc.NetworkView', {
 
 	Proxmox.Utils.setErrorMask(me, true);
 
+	let nodename = me.pveSelNode.data.node;
+	let vmid = me.pveSelNode.data.vmid;
+
 	Proxmox.Utils.API2Request({
-	    url: me.url,
+	    url: '/nodes/' + nodename + '/lxc/' + vmid + '/interfaces',
+	    method: 'GET',
 	    failure: function(response, opts) {
 		Proxmox.Utils.setErrorMask(me, gettext('Error') + ': ' + response.htmlStatus);
 	    },
-	    success: function(response, opts) {
-		Proxmox.Utils.setErrorMask(me, false);
-		let result = Ext.decode(response.responseText);
-		me.dataCache = result.data || {};
-		let records = [];
-		for (const [key, value] of Object.entries(me.dataCache)) {
-		    if (key.match(/^net\d+/)) {
-			let net = PVE.Parser.parseLxcNetwork(value);
-			net.id = key;
-			records.push(net);
-		    }
-		}
-		me.store.loadData(records);
-		me.down('button[name=addButton]').setDisabled(records.length >= 32);
+	    success: function(ifResponse, ifOpts) {
+		Proxmox.Utils.API2Request({
+		    url: me.url,
+		    failure: function(response, opts) {
+			Proxmox.Utils.setErrorMask(me, gettext('Error') + ': ' + response.htmlStatus);
+		    },
+		    success: function(confResponse, confOpts) {
+			Proxmox.Utils.setErrorMask(me, false);
+
+			let interfaces = [];
+			for (const [, iface] of Object.entries(ifResponse?.result?.data || {})) {
+			    interfaces[iface.hwaddr] = iface;
+			}
+
+			let result = Ext.decode(confResponse.responseText);
+			me.dataCache = result.data || {};
+			let records = [];
+			for (const [key, value] of Object.entries(me.dataCache)) {
+			    if (key.match(/^net\d+/)) {
+				let net = PVE.Parser.parseLxcNetwork(value);
+				net.id = key;
+
+				let iface;
+				if ((iface = interfaces[net.hwaddr.toLowerCase()])) {
+				    net.name = iface.name;
+				    net.ip = iface.inet;
+				    net.ip6 = iface.inet6;
+				}
+
+				records.push(net);
+			    }
+			}
+
+			me.store.loadData(records);
+			me.down('button[name=addButton]').setDisabled(records.length >= 32);
+		    },
+		});
 	    },
 	});
     },
-- 
2.30.2





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

* Re: [pve-devel] [PATCH container] api: network: get interfaces from containers
  2023-04-18  9:31 ` [pve-devel] [PATCH container] api: network: get interfaces from containers Leo Nunner
@ 2023-04-18  9:41   ` Lukas Wagner
  0 siblings, 0 replies; 5+ messages in thread
From: Lukas Wagner @ 2023-04-18  9:41 UTC (permalink / raw)
  To: Proxmox VE development discussion, Leo Nunner

On 4/18/23 11:31, Leo Nunner wrote:
> +    foreach my $interface ($config->@*) {
> +	my $obj = { name => $interface->{ifname} };
> +	foreach my $ip ($interface->{addr_info}->@*) {
> +	    $obj->{$ip->{family}} = $ip->{local} . "/" . $ip->{prefixlen};
> +	}
> +	$obj->{hwaddr} = $interface->{address};
> +	push @$res, $obj
> +    }

Nit, according to our style guide [1], `for` is to be preferred over `foreach`.

[1] https://pve.proxmox.com/wiki/Perl_Style_Guide#Perl_syntax_choices

-- 
- Lukas




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

* Re: [pve-devel] [PATCH manager] lxc: show dynamically assigned IPs in network tab
  2023-04-18  9:31 ` [pve-devel] [PATCH manager] lxc: show dynamically assigned IPs in network tab Leo Nunner
@ 2023-04-18  9:47   ` Lukas Wagner
  0 siblings, 0 replies; 5+ messages in thread
From: Lukas Wagner @ 2023-04-18  9:47 UTC (permalink / raw)
  To: Proxmox VE development discussion, Leo Nunner


On 4/18/23 11:31, Leo Nunner wrote:
>   	Proxmox.Utils.API2Request({
> -	    url: me.url,
> +	    url: '/nodes/' + nodename + '/lxc/' + vmid + '/interfaces',

Nit, I think a template string here would be nicer ;)

url: `/nodes/${nodename}/lxc/${vmid}/interfaces`

-- 
- Lukas




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

end of thread, other threads:[~2023-04-18  9:47 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-04-18  9:31 [pve-devel] [PATCH container manager] Show dynamic container IPs in GUI Leo Nunner
2023-04-18  9:31 ` [pve-devel] [PATCH container] api: network: get interfaces from containers Leo Nunner
2023-04-18  9:41   ` Lukas Wagner
2023-04-18  9:31 ` [pve-devel] [PATCH manager] lxc: show dynamically assigned IPs in network tab Leo Nunner
2023-04-18  9:47   ` Lukas Wagner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal