From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) by lore.proxmox.com (Postfix) with ESMTPS id 5E7CC1FF170 for ; Thu, 10 Jul 2025 12:33:56 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 69A5B30416; Thu, 10 Jul 2025 12:34:41 +0200 (CEST) Date: Thu, 10 Jul 2025 12:34:06 +0200 From: Wolfgang Bumiller To: Filip Schauer Message-ID: References: <20250709123435.64796-1-f.schauer@proxmox.com> <20250709123435.64796-10-f.schauer@proxmox.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20250709123435.64796-10-f.schauer@proxmox.com> X-SPAM-LEVEL: Spam detection results: 0 AWL 0.077 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment RCVD_IN_VALIDITY_CERTIFIED_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_RPBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. RCVD_IN_VALIDITY_SAFE_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to Validity was blocked. See https://knowledge.validity.com/hc/en-us/articles/20961730681243 for more information. SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: Re: [pve-devel] [PATCH container v3 09/13] manage DHCP for containers with custom entrypoint X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: Proxmox VE development discussion Cc: pve-devel@lists.proxmox.com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: pve-devel-bounces@lists.proxmox.com Sender: "pve-devel" On Wed, Jul 09, 2025 at 02:34:26PM +0200, Filip Schauer wrote: > Containers that do not use the default `/sbin/init` entrypoint may lack ^ This commit message needs updating to reflect the changes in this version. > in-container network management. A previous commit already handles > static IP addresses. Now this commit also handles DHCP. This is done > using a `dhclient` process for each network interface. > > Signed-off-by: Filip Schauer > --- > Changed since v2: > * rebase onto newest master (5a8b3f962f16) and re-format with > proxmox-perltidy > * add an "ipmanagehost" property to pct.conf to control whether network > interface IP configuration should be handled by the host. > * manage_dhclient: add a FIXME comment regarding the AppArmor profile: > "use a profile that confines writes to /var/lib/lxc/$vmid and rootfs" > * kill_dhclients: untaint pid from pidfile > * fix manage_dhclient called with 'stop' instead of 'start' for IPv6 > when container is started > > src/PVE/LXC.pm | 103 +++++++++++++++++++++++++++++++++++++----- > src/PVE/LXC/Config.pm | 17 ++++--- > 2 files changed, 101 insertions(+), 19 deletions(-) > > diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm > index 7c9caf6..4f19a21 100644 > --- a/src/PVE/LXC.pm > +++ b/src/PVE/LXC.pm > @@ -837,15 +837,12 @@ sub update_lxc_config { > } > > if ((!defined($d->{link_down}) || $d->{link_down} != 1) && $conf->{ipmanagehost}) { > - if (defined($d->{ip})) { > - die "$k: DHCP is not supported with a custom entrypoint\n" if $d->{ip} eq 'dhcp'; > - $raw .= "lxc.net.$ind.ipv4.address = $d->{ip}\n" if $d->{ip} ne 'manual'; > - } > + $raw .= "lxc.net.$ind.ipv4.address = $d->{ip}\n" > + if defined($d->{ip}) && $d->{ip} !~ /^(dhcp|manual)$/; > $raw .= "lxc.net.$ind.ipv4.gateway = $d->{gw}\n" if defined($d->{gw}); > if (defined($d->{ip6})) { > - die "$k: DHCPv6 and SLAAC are not supported with a custom entrypoint\n" > - if $d->{ip6} =~ /^(auto|dhcp)$/; > - $raw .= "lxc.net.$ind.ipv6.address = $d->{ip6}\n" if $d->{ip6} ne 'manual'; > + die "$k: SLAAC is not supported with a custom entrypoint\n" if $d->{ip6} eq 'auto'; > + $raw .= "lxc.net.$ind.ipv6.address = $d->{ip6}\n" if $d->{ip6} !~ /^(dhcp|manual)$/; > } > $raw .= "lxc.net.$ind.ipv6.gateway = $d->{gw6}\n" if defined($d->{gw6}); > $raw .= "lxc.net.$ind.flags = up\n"; > @@ -1028,6 +1025,8 @@ sub vm_stop_cleanup { > PVE::Storage::deactivate_volumes($storage_cfg, $vollist); > }; > warn $@ if $@; # avoid errors - just warn > + > + kill_dhclients($vmid, '*') if $conf->{ipmanagehost}; > } > > sub net_tap_plug : prototype($$) { > @@ -1259,6 +1258,52 @@ sub get_interfaces { > return $res; > } > > +sub manage_dhclient { > + my ($action, $vmid, $ipversion, $eth, $rootdir) = @_; > + > + File::Path::make_path("/var/lib/lxc/$vmid/hook") if $action eq 'start'; > + my $pidfile = "/var/lib/lxc/$vmid/hook/dhclient$ipversion-$eth.pid"; > + my $leasefile = "/var/lib/lxc/$vmid/hook/dhclient$ipversion-$eth.leases"; > + my $scriptfile = '/usr/share/lxc/hooks/dhclient-script'; > + PVE::Tools::run_command([ > + 'lxc-attach', > + '-n', > + $vmid, > + '-s', > + 'NETWORK|UTSNAME', > + '--', > + 'aa-exec', > + '-p', > + 'unconfined', # FIXME: use a profile that confines writes to /var/lib/lxc/$vmid and rootfs > + '/sbin/dhclient', > + $action eq 'start' ? '-1' : '-r', > + "-$ipversion", > + '-pf', > + $pidfile, > + '-lf', > + $leasefile, > + '-e', > + "ROOTFS=$rootdir", > + '-sf', > + $scriptfile, > + $eth, > + ]); > +} > + > +sub kill_dhclients { > + my ($vmid, $eth) = @_; > + > + foreach my $pidfile (glob("/var/lib/lxc/$vmid/hook/dhclient*-$eth.pid")) { > + my $pid = eval { file_get_contents($pidfile) }; > + if (!$@) { > + chomp $pid; > + next if $pid !~ /^(\d+)$/; > + kill 9, $1; > + unlink($pidfile); > + } > + } > +} > + > sub update_ipconfig { > my ($vmid, $conf, $opt, $eth, $newnet, $rootdir) = @_; > > @@ -1295,11 +1340,21 @@ sub update_ipconfig { > > # step 1: add new IP, if this fails we cancel > my $is_real_ip = ($newip && $newip !~ /^(?:auto|dhcp|manual)$/); > - if ($change_ip && $is_real_ip) { > - eval { &$ipcmd($family_opt, 'addr', 'add', $newip, 'dev', $eth); }; > - if (my $err = $@) { > - warn $err; > - return; > + if ($change_ip) { > + if ($conf->{ipmanagehost}) { > + if ($newip && $newip eq 'dhcp') { > + manage_dhclient('start', $vmid, $ipversion, $eth, $rootdir); > + } elsif ($oldip && $oldip eq 'dhcp') { > + manage_dhclient('stop', $vmid, $ipversion, $eth, $rootdir); > + } > + } > + > + if ($is_real_ip) { > + eval { &$ipcmd($family_opt, 'addr', 'add', $newip, 'dev', $eth); }; > + if (my $err = $@) { > + warn $err; > + return; > + } > } > } > > @@ -2827,6 +2882,30 @@ sub vm_start { > } > PVE::GuestHelpers::exec_hookscript($conf, $vmid, 'post-start'); > > + if ($conf->{ipmanagehost}) { > + my @dhcpv4_interfaces = (); > + my @dhcpv6_interfaces = (); > + foreach my $k (sort keys %$conf) { > + next if $k !~ m/^net(\d+)$/; > + my $d = PVE::LXC::Config->parse_lxc_network($conf->{$k}); > + push @dhcpv4_interfaces, $d->{name} if $d->{ip} && $d->{ip} eq 'dhcp'; > + push @dhcpv6_interfaces, $d->{name} if $d->{ip6} && $d->{ip6} eq 'dhcp'; > + } > + > + my $pid = PVE::LXC::find_lxc_pid($vmid); > + my $rootdir = "/proc/$pid/root"; > + > + foreach my $eth (@dhcpv4_interfaces) { > + eval { manage_dhclient('start', $vmid, 4, $eth, $rootdir) }; > + PVE::RESTEnvironment::log_warn("DHCP failed - $@") if $@; > + } > + > + foreach my $eth (@dhcpv6_interfaces) { > + eval { manage_dhclient('start', $vmid, 6, $eth, $rootdir) }; > + PVE::RESTEnvironment::log_warn("DHCP failed - $@") if $@; > + } > + } > + > return; > } > > diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm > index c2f56e4..39c3243 100644 > --- a/src/PVE/LXC/Config.pm > +++ b/src/PVE/LXC/Config.pm > @@ -1291,12 +1291,13 @@ sub update_pct_config { > if ($mtu > $bridge_mtu); > } > > - if ((!defined($res->{link_down}) || $res->{link_down} != 1) && $conf->{ipmanagehost}) { > - die "$opt: DHCP is not supported with a custom entrypoint\n" > - if defined($res->{ip}) && $res->{ip} eq 'dhcp'; > - > - die "$opt: DHCPv6 and SLAAC are not supported with a custom entrypoint\n" > - if defined($res->{ip6}) && $res->{ip6} =~ /^(auto|dhcp)$/; > + if ( > + (!defined($res->{link_down}) || $res->{link_down} != 1) > + && $conf->{ipmanagehost} > + && defined($res->{ip6}) > + && $res->{ip6} eq 'auto' > + ) { > + die "$opt: SLAAC is not supported with a custom entrypoint\n"; > } > } elsif ($opt =~ m/^dev(\d+)$/) { > my $device = $class->parse_device($value); > @@ -1575,9 +1576,11 @@ sub vmconfig_hotplug_pending { > $cgroup->change_cpu_shares(undef); > } elsif ($opt =~ m/^net(\d)$/) { > my $netid = $1; > + my $net = parse_lxc_network($conf->{$opt}); > + PVE::LXC::kill_dhclients($vmid, $net->{name}) if $conf->{ipmanagehost}; > + > PVE::Network::veth_delete("veth${vmid}i$netid"); > if ($have_sdn) { > - my $net = PVE::LXC::Config->parse_lxc_network($conf->{$opt}); > print "delete ips from $opt\n"; > eval { > PVE::Network::SDN::Vnets::del_ips_from_mac( > -- > 2.47.2 > > > > _______________________________________________ > pve-devel mailing list > pve-devel@lists.proxmox.com > https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel > > _______________________________________________ pve-devel mailing list pve-devel@lists.proxmox.com https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel