public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
* [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3
@ 2023-11-15 14:21 Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-network 1/3] fix subnets && netbox ipam tests Alexandre Derumier
                   ` (14 more replies)
  0 siblings, 15 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:21 UTC (permalink / raw)
  To: pve-devel

pve-network : apply on last stefan DHCP WIP3 serie
qemu-server : remork of my last patch series , applied to current master
pve-container: apply to master

changelog:
 - pve-network: the dhcp reservation removal is now done on dhcp_mapping_add.
 - qemu-server: rebase with dhcp_removal + some cleanup


BTW, I have seen some case where dnsmasq attribute some dynamic leases in the range
(maybe it was a bug/race where client was asking to dhcp serer before the reversation was done).

But if a dynamic lease exist for an ip, the static reservation is not working, and a new dynamic lease
is sent instead.

So, I really think that we should disable dynamic leases in dnsmasq (not sure exactly how)


pve-network:

Alexandre Derumier (3):
  fix subnets && netbox ipam tests
  add add_dhcp_mapping
  dhcp: delete remove_mapping

 src/PVE/API2/Network/SDN/Ipam.pm              |  1 -
 src/PVE/Network/SDN/Dhcp.pm                   | 22 ++----
 src/PVE/Network/SDN/Dhcp/Dnsmasq.pm           | 74 +++++++++----------
 src/PVE/Network/SDN/Dhcp/Plugin.pm            |  7 +-
 src/PVE/Network/SDN/Vnets.pm                  | 15 ++++
 src/test/ipams/netbox/expected.add_ip         |  2 +-
 .../ipams/netbox/expected.add_ip_notgateway   |  2 +-
 .../ipams/netbox/expected.add_next_freeip     |  2 +-
 src/test/ipams/netbox/expected.update_ip      |  2 +-
 src/test/run_test_subnets.pl                  |  8 +-
 10 files changed, 63 insertions(+), 72 deletions(-)


qemu-server:

Alexandre Derumier (6):
  vmnic add|remove : add|del ip in ipam
  vm_start : vm-network-scripts: add_dhcp_reservation
  nic hotplug: add_dhcp_mapping
  api2: create|restore|clone: add_free_ip
  vm_destroy: delete ip from ipam
  nic online bridge/vlan change: link disconnect/reconnect

 PVE/API2/Qemu.pm              |  6 +++
 PVE/QemuServer.pm             | 86 +++++++++++++++++++++++++++++++++++
 vm-network-scripts/pve-bridge |  2 +
 3 files changed, 94 insertions(+)


pve-container:

Alexandre Derumier (6):
  nic hotplug : add|del ips in ipam
  vm_destroy: remove ips from ipam for all interfaces
  vm_create|restore: create ips in ipam
  vm_clone : create ips in ipams
  vm_apply_pending: add|del ips from ipam for offline changes
  lxc-pve-prestart-hook : add_dhcp_mapping

 src/PVE/API2/LXC.pm       | 10 ++++++++-
 src/PVE/LXC.pm            | 46 +++++++++++++++++++++++++++++++++++++++
 src/PVE/LXC/Config.pm     | 27 +++++++++++++++++++++++
 src/lxc-pve-prestart-hook | 15 +++++++++++++
 4 files changed, 97 insertions(+), 1 deletion(-)



-- 
2.39.2




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

* [pve-devel] [PATCH pve-network 1/3] fix subnets && netbox ipam tests
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
@ 2023-11-15 14:21 ` Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del ips in ipam Alexandre Derumier
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:21 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/test/ipams/netbox/expected.add_ip            | 2 +-
 src/test/ipams/netbox/expected.add_ip_notgateway | 2 +-
 src/test/ipams/netbox/expected.add_next_freeip   | 2 +-
 src/test/ipams/netbox/expected.update_ip         | 2 +-
 src/test/run_test_subnets.pl                     | 8 ++++----
 5 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/test/ipams/netbox/expected.add_ip b/src/test/ipams/netbox/expected.add_ip
index e9323ca..cd46c53 100644
--- a/src/test/ipams/netbox/expected.add_ip
+++ b/src/test/ipams/netbox/expected.add_ip
@@ -1,5 +1,5 @@
 bless( {
-                  '_content' => '{"address":"10.0.0.1/24","description":"mydescription mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
+                  '_content' => '{"address":"10.0.0.1/24","description":"gateway","dns_name":"myhostname"}',
                   '_headers' => bless( {
                                          'authorization' => 'token 0123456789abcdef0123456789abcdef01234567',
                                          'content-type' => 'application/json; charset=UTF-8'
diff --git a/src/test/ipams/netbox/expected.add_ip_notgateway b/src/test/ipams/netbox/expected.add_ip_notgateway
index e9323ca..5ea43cd 100644
--- a/src/test/ipams/netbox/expected.add_ip_notgateway
+++ b/src/test/ipams/netbox/expected.add_ip_notgateway
@@ -1,5 +1,5 @@
 bless( {
-                  '_content' => '{"address":"10.0.0.1/24","description":"mydescription mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
+                  '_content' => '{"address":"10.0.0.1/24","description":"mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
                   '_headers' => bless( {
                                          'authorization' => 'token 0123456789abcdef0123456789abcdef01234567',
                                          'content-type' => 'application/json; charset=UTF-8'
diff --git a/src/test/ipams/netbox/expected.add_next_freeip b/src/test/ipams/netbox/expected.add_next_freeip
index 86840eb..fbbafbb 100644
--- a/src/test/ipams/netbox/expected.add_next_freeip
+++ b/src/test/ipams/netbox/expected.add_next_freeip
@@ -1,5 +1,5 @@
 bless( {
-                  '_content' => '{"description":"mydescription mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
+                  '_content' => '{"description":"mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
                   '_headers' => bless( {
                                          'authorization' => 'token 0123456789abcdef0123456789abcdef01234567',
                                          'content-type' => 'application/json; charset=UTF-8'
diff --git a/src/test/ipams/netbox/expected.update_ip b/src/test/ipams/netbox/expected.update_ip
index 5679e8d..d3bc1ad 100644
--- a/src/test/ipams/netbox/expected.update_ip
+++ b/src/test/ipams/netbox/expected.update_ip
@@ -1,5 +1,5 @@
 bless( {
-                  '_content' => '{"address":"10.0.0.1/24","description":"mydescription mac:da:65:8f:18:9b:6f","dns_name":"myhostname"}',
+                  '_content' => '{"address":"10.0.0.1/24","description":"gateway","dns_name":"myhostname"}',
                   '_headers' => bless( {
                                          'authorization' => 'token 0123456789abcdef0123456789abcdef01234567',
                                          'content-type' => 'application/json; charset=UTF-8'
diff --git a/src/test/run_test_subnets.pl b/src/test/run_test_subnets.pl
index c98359a..578b5c1 100755
--- a/src/test/run_test_subnets.pl
+++ b/src/test/run_test_subnets.pl
@@ -176,7 +176,7 @@ foreach my $path (@plugins) {
     $test = "add_second_ip $ip2";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ip2.'":{"hostname":"'.$hostname.'","ip":"'.$ip2.'","mac":"'.$mac.'"}}}}}}}';
 
     eval {
 	PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip2, $hostname, $mac, $description);
@@ -195,7 +195,7 @@ foreach my $path (@plugins) {
     $test = "find_next_freeip ($ipnextfree)";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ip.'":{"gateway":1},"'.$ipnextfree.'":{},"'.$ip2.'":{"hostname":"'.$hostname.'","ip":"'.$ip2.'","mac":"'.$mac.'"}}}}}}}';
 
     eval {
 	$ip3 = PVE::Network::SDN::Subnets::add_next_free_ip($zone, $subnetid, $subnet, $hostname, $mac, $description);
@@ -212,7 +212,7 @@ foreach my $path (@plugins) {
     $test = "del_ip $ip";
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ipnextfree.'":{},"'.$ip2.'":{"hostname":"'.$hostname.'","ip":"'.$ip2.'","mac":"'.$mac.'"}}}}}}}';
 
     eval {
 	PVE::Network::SDN::Subnets::del_ip($zone, $subnetid, $subnet, $ip, $hostname);
@@ -264,7 +264,7 @@ foreach my $path (@plugins) {
 
     $name = "$testid $test";
     $result = undef;
-    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ipnextfree.'":{},"'.$ip2.'":{}}}}}}}';
+    $expected = '{"zones":{"myzone":{"subnets":{"'.$subnet_cidr.'":{"ips":{"'.$ipnextfree.'":{},"'.$ip2.'":{"hostname":"'.$hostname.'","ip":"'.$ip2.'","mac":"'.$mac.'"}}}}}}}';
 
     eval {
 	PVE::Network::SDN::Subnets::add_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description);
-- 
2.39.2




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

* [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del ips in ipam
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-network 1/3] fix subnets && netbox ipam tests Alexandre Derumier
@ 2023-11-15 14:21 ` Alexandre Derumier
  2023-11-15 14:56   ` Stefan Hanreich
  2023-11-15 14:21 ` [pve-devel] [PATCH qemu-server 1/6] vmnic add|remove : add|del ip " Alexandre Derumier
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:21 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/PVE/LXC.pm        | 17 +++++++++++++++++
 src/PVE/LXC/Config.pm | 12 ++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 7ec816b..7ccef08 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -961,6 +961,12 @@ sub update_net {
 	    safe_string_ne($oldnet->{name}, $newnet->{name})) {
 
 	    PVE::Network::veth_delete($veth);
+
+	    if ($have_sdn) {
+		eval { PVE::Network::SDN::Vnets::del_ips_from_mac($oldnet->{bridge}, $oldnet->{hwaddr}, $conf->{hostname}) };
+		warn $@ if $@;
+	    }
+
 	    delete $conf->{$opt};
 	    PVE::LXC::Config->write_config($vmid, $conf);
 
@@ -974,14 +980,23 @@ sub update_net {
 	    ) {
 
 		if ($oldnet->{bridge}) {
+
 		    PVE::Network::tap_unplug($veth);
 		    foreach (qw(bridge tag firewall)) {
 			delete $oldnet->{$_};
 		    }
 		    $conf->{$opt} = PVE::LXC::Config->print_lxc_network($oldnet);
 		    PVE::LXC::Config->write_config($vmid, $conf);
+
+		    if ($have_sdn) {
+			eval { PVE::Network::SDN::Vnets::del_ips_from_mac($oldnet->{bridge}, $oldnet->{hwaddr}, $conf->{hostname}) };
+			warn $@ if $@;
+		    }
 		}
 
+		if ($have_sdn) {
+		    PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge}, $conf->{hostname}, $newnet->{hwaddr}, "vmid: $vmid", undef, 1);
+		}
 		PVE::LXC::net_tap_plug($veth, $newnet);
 
 		# This includes the rate:
@@ -1012,6 +1027,8 @@ sub hotplug_net {
     my $eth = $newnet->{name};
 
     if ($have_sdn) {
+	PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge}, $conf->{hostname}, $newnet->{hwaddr}, "vmid: $vmid", undef, 1);
+	PVE::Network::SDN::Vnets::add_dhcp_mapping($newnet->{bridge}, $newnet->{hwaddr});
 	PVE::Network::SDN::Zones::veth_create($veth, $vethpeer, $newnet->{bridge}, $newnet->{hwaddr});
     } else {
 	PVE::Network::veth_create($veth, $vethpeer, $newnet->{bridge}, $newnet->{hwaddr});
diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index 56e1f10..c884313 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -22,6 +22,12 @@ use constant {
     FITHAW   => 0xc0045878,
 };
 
+my $have_sdn;
+eval {
+    require PVE::Network::SDN::Vnets;
+    $have_sdn = 1;
+};
+
 my $nodename = PVE::INotify::nodename();
 my $lock_handles =  {};
 my $lockdir = "/run/lock/lxc";
@@ -1383,6 +1389,12 @@ sub vmconfig_hotplug_pending {
 	    } elsif ($opt =~ m/^net(\d)$/) {
 		my $netid = $1;
 		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($net->{bridge}, $net->{hwaddr}, $conf->{hostname}) };
+		    warn $@ if $@;
+		}
 	    } else {
 		die "skip\n"; # skip non-hotpluggable opts
 	    }
-- 
2.39.2




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

* [pve-devel] [PATCH qemu-server 1/6] vmnic add|remove : add|del ip in ipam
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-network 1/3] fix subnets && netbox ipam tests Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del ips in ipam Alexandre Derumier
@ 2023-11-15 14:21 ` Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-network 2/3] add add_dhcp_mapping Alexandre Derumier
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:21 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/QemuServer.pm | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index c465fb6..beea2cb 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -64,6 +64,7 @@ use PVE::QemuServer::USB;
 my $have_sdn;
 eval {
     require PVE::Network::SDN::Zones;
+    require PVE::Network::SDN::Vnets;
     $have_sdn = 1;
 };
 
@@ -4998,6 +4999,10 @@ sub vmconfig_hotplug_pending {
 	    } elsif ($opt =~ m/^net(\d+)$/) {
 		die "skip\n" if !$hotplug_features->{network};
 		vm_deviceunplug($vmid, $conf, $opt);
+		if($have_sdn) {
+		    my $net = PVE::QemuServer::parse_net($conf->{$opt});
+		    PVE::Network::SDN::Vnets::del_ips_from_mac($net->{bridge}, $net->{macaddr}, $conf->{name});
+		}
 	    } elsif (is_valid_drivename($opt)) {
 		die "skip\n" if !$hotplug_features->{disk} || $opt =~ m/(ide|sata)(\d+)/;
 		vm_deviceunplug($vmid, $conf, $opt);
@@ -5203,6 +5208,12 @@ sub vmconfig_apply_pending {
 		die "internal error";
 	    } elsif (defined($conf->{$opt}) && is_valid_drivename($opt)) {
 		vmconfig_delete_or_detach_drive($vmid, $storecfg, $conf, $opt, $force);
+	    } elsif (defined($conf->{$opt}) && $opt =~ m/^net\d+$/) {
+		if($have_sdn) {
+		    my $net = PVE::QemuServer::parse_net($conf->{$opt});
+		    eval { PVE::Network::SDN::Vnets::del_ips_from_mac($net->{bridge}, $net->{macaddr}, $conf->{name}) };
+		    warn if $@;
+		}
 	    }
 	};
 	if (my $err = $@) {
@@ -5222,6 +5233,20 @@ sub vmconfig_apply_pending {
 	eval {
 	    if (defined($conf->{$opt}) && is_valid_drivename($opt)) {
 		vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
+	    } elsif (defined($conf->{pending}->{$opt}) && $opt =~ m/^net\d+$/) {
+		if($have_sdn) {
+                    my $new_net = PVE::QemuServer::parse_net($conf->{pending}->{$opt});
+		    if ($conf->{$opt}){
+		        my $old_net = PVE::QemuServer::parse_net($conf->{$opt});
+
+			if ($old_net->{bridge} ne $new_net->{bridge} ||
+			    $old_net->{macaddr} ne $new_net->{macaddr}) {
+			    PVE::Network::SDN::Vnets::del_ips_from_mac($old_net->{bridge}, $old_net->{macaddr}, $conf->{name});
+			}
+		   }
+		   #fixme: reuse ip if mac change && same bridge
+		   PVE::Network::SDN::Vnets::add_next_free_cidr($new_net->{bridge}, $conf->{name}, $new_net->{macaddr}, $vmid, undef, 1);
+		}
 	    }
 	};
 	if (my $err = $@) {
@@ -5265,6 +5290,11 @@ sub vmconfig_update_net {
             # for non online change, we try to hot-unplug
 	    die "skip\n" if !$hotplug;
 	    vm_deviceunplug($vmid, $conf, $opt);
+
+	    if($have_sdn) {
+		PVE::Network::SDN::Vnets::del_ips_from_mac($oldnet->{bridge}, $oldnet->{macaddr}, $conf->{name});
+	    }
+
 	} else {
 
 	    die "internal error" if $opt !~ m/net(\d+)/;
@@ -5276,6 +5306,13 @@ sub vmconfig_update_net {
 		safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
 		PVE::Network::tap_unplug($iface);
 
+		if (safe_string_ne($oldnet->{bridge}, $newnet->{bridge})) {
+		    if ($have_sdn) {
+			PVE::Network::SDN::Vnets::del_ips_from_mac($oldnet->{bridge}, $oldnet->{macaddr}, $conf->{name});
+			PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge}, $conf->{name}, $newnet->{macaddr}, "vmid:$vmid", undef, 1);
+		    }
+		}
+
 		if ($have_sdn) {
 		    PVE::Network::SDN::Zones::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
 		} else {
@@ -5296,6 +5333,9 @@ sub vmconfig_update_net {
     }
 
     if ($hotplug) {
+	if ($have_sdn) {
+	    PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge}, $conf->{name}, $newnet->{macaddr}, "vmid:$vmid", undef, 1);
+	}
 	vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet, $arch, $machine_type);
     } else {
 	die "skip\n";
-- 
2.39.2




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

* [pve-devel] [PATCH pve-network 2/3] add add_dhcp_mapping
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (2 preceding siblings ...)
  2023-11-15 14:21 ` [pve-devel] [PATCH qemu-server 1/6] vmnic add|remove : add|del ip " Alexandre Derumier
@ 2023-11-15 14:21 ` Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-container 2/6] vm_destroy: remove ips from ipam for all interfaces Alexandre Derumier
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:21 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/PVE/Network/SDN/Dhcp.pm         |  9 ++++---
 src/PVE/Network/SDN/Dhcp/Dnsmasq.pm | 40 ++++++++++++++++++++++++-----
 src/PVE/Network/SDN/Dhcp/Plugin.pm  |  2 +-
 src/PVE/Network/SDN/Vnets.pm        | 15 +++++++++++
 4 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/src/PVE/Network/SDN/Dhcp.pm b/src/PVE/Network/SDN/Dhcp.pm
index b178927..99561b3 100644
--- a/src/PVE/Network/SDN/Dhcp.pm
+++ b/src/PVE/Network/SDN/Dhcp.pm
@@ -8,6 +8,7 @@ use PVE::Cluster qw(cfs_read_file);
 use PVE::Network::SDN;
 use PVE::Network::SDN::SubnetPlugin;
 use PVE::Network::SDN::Dhcp qw(config);
+use PVE::Network::SDN::Ipams;
 use PVE::Network::SDN::Subnets qw(sdn_subnets_config config get_dhcp_ranges);
 use PVE::Network::SDN::Dhcp::Plugin;
 use PVE::Network::SDN::Dhcp::Dnsmasq;
@@ -30,9 +31,11 @@ sub add_mapping {
 
     return if !$zone->{ipam} || !$zone->{dhcp};
 
-    my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($zone->{dhcp});
-    $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip4) if $ip4;
-    $dhcp_plugin->add_ip_mapping($zoneid, $mac, $ip6) if $ip6;
+    my $dhcptype = $zone->{dhcp};
+
+    my $macdb = PVE::Network::SDN::Ipams::read_macdb();
+    my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($dhcptype);
+    $dhcp_plugin->add_ip_mapping($zoneid, $macdb, $mac, $ip4, $ip6)
 }
 
 sub remove_mapping {
diff --git a/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm b/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
index 21a6ddd..b672dd3 100644
--- a/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
+++ b/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
@@ -53,21 +53,49 @@ sub del_ip_mapping {
 }
 
 sub add_ip_mapping {
-    my ($class, $dhcpid, $mac, $ip) = @_;
+    my ($class, $dhcpid, $macdb, $mac, $ip4, $ip6) = @_;
 
     my $ethers_file = "$DNSMASQ_CONFIG_ROOT/$dhcpid/ethers";
     my $ethers_tmp_file = "$ethers_file.tmp";
 
+    my $change = undef;
+    my $match4 = undef;
+    my $match6 = undef;
+
     my $appendFn = sub {
 	open(my $in, '<', $ethers_file) or die "Could not open file '$ethers_file' $!\n";
 	open(my $out, '>', $ethers_tmp_file) or die "Could not open file '$ethers_tmp_file' $!\n";
 
         while (my $line = <$in>) {
-	    next if $line =~ m/^$mac/;
-	    print $out $line;
+	    chomp($line);
+	    my ($parsed_mac, $parsed_ip) = split(/,/, $line);
+	    #delete removed mac
+	    if (!defined($macdb->{macs}->{$parsed_mac})) {
+		$change = 1;
+		next;
+	    }
+
+	    #delete changed ip
+	    my $ipversion = Net::IP::ip_is_ipv4($parsed_ip) ? "ip4" : "ip6";
+	    if ($macdb->{macs}->{$parsed_mac}->{$ipversion} && $macdb->{macs}->{$parsed_mac}->{$ipversion} ne $parsed_ip) {
+		$change = 1;
+		next;
+	    }
+	    print $out "$parsed_mac,$parsed_ip\n";
+	    #check if mac/ip already exist
+	    $match4 = 1 if $parsed_mac eq $mac && $macdb->{macs}->{$mac}->{'ip4'} && $macdb->{macs}->{$mac}->{'ip4'} eq $ip4;
+	    $match6 = 1 if $parsed_mac eq $mac && $macdb->{macs}->{$mac}->{'ip6'} && $macdb->{macs}->{$mac}->{'ip6'} eq $ip6;
+  	}
+
+	if(!$match4 && $ip4) {
+	    print $out "$mac,$ip4\n";
+	    $change = 1;
 	}
 
-	print $out "$mac,$ip\n";
+	if(!$match6 && $ip6) {
+	    print $out "$mac,$ip6\n";
+	    $change = 1;
+	}
 	close $in;
 	close $out;
 	move $ethers_tmp_file, $ethers_file;
@@ -77,12 +105,12 @@ sub add_ip_mapping {
     PVE::Tools::lock_file($ethers_file, 10, $appendFn);
 
     if ($@) {
-	warn "Unable to add $mac/$ip to the dnsmasq configuration: $@\n";
+	warn "Unable to add $mac to the dnsmasq configuration: $@\n";
 	return;
     }
 
     my $service_name = "dnsmasq\@$dhcpid";
-    PVE::Tools::run_command(['systemctl', 'reload', $service_name]);
+    PVE::Tools::run_command(['systemctl', 'reload', $service_name]) if $change;
 }
 
 sub configure_subnet {
diff --git a/src/PVE/Network/SDN/Dhcp/Plugin.pm b/src/PVE/Network/SDN/Dhcp/Plugin.pm
index 7b9e9b7..8d0f7ba 100644
--- a/src/PVE/Network/SDN/Dhcp/Plugin.pm
+++ b/src/PVE/Network/SDN/Dhcp/Plugin.pm
@@ -23,7 +23,7 @@ sub private {
 }
 
 sub add_ip_mapping {
-    my ($class, $dhcp_config, $mac, $ip) = @_;
+    my ($class, $dhcpid, $macdb, $mac, $ip4, $ip6) = @_;
     die 'implement in sub class';
 }
 
diff --git a/src/PVE/Network/SDN/Vnets.pm b/src/PVE/Network/SDN/Vnets.pm
index 9ec16eb..ad585f0 100644
--- a/src/PVE/Network/SDN/Vnets.pm
+++ b/src/PVE/Network/SDN/Vnets.pm
@@ -7,6 +7,7 @@ use Net::IP;
 
 use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
 use PVE::Network::SDN;
+use PVE::Network::SDN::Dhcp;
 use PVE::Network::SDN::Subnets;
 use PVE::Network::SDN::Zones;
 
@@ -176,4 +177,18 @@ sub del_ips_from_mac {
     PVE::Network::SDN::Vnets::del_ip($vnetid, $ip6, $hostname, $mac) if $ip6;
 }
 
+sub add_dhcp_mapping {
+    my ($vnetid, $mac) = @_;
+
+    my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
+    return if !$vnet;
+    my $zoneid = $vnet->{zone};
+    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
+
+    return if !$zone->{ipam} || !$zone->{dhcp};
+
+    my ($ip4,$ip6) = PVE::Network::SDN::Vnets::get_ips_from_mac($vnetid, $mac);
+    PVE::Network::SDN::Dhcp::add_mapping($vnetid, $mac, $ip4, $ip6) if $ip4 || $ip6;
+}
+
 1;
-- 
2.39.2




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

* [pve-devel] [PATCH pve-container 2/6] vm_destroy: remove ips from ipam for all interfaces
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (3 preceding siblings ...)
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-network 2/3] add add_dhcp_mapping Alexandre Derumier
@ 2023-11-15 14:21 ` Alexandre Derumier
  2023-11-15 14:21 ` [pve-devel] [PATCH qemu-server 2/6] vm_start : vm-network-scripts: add_dhcp_reservation Alexandre Derumier
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:21 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/PVE/LXC.pm | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 7ccef08..6f1c6b9 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -46,6 +46,7 @@ use PVE::LXC::Tools;
 my $have_sdn;
 eval {
     require PVE::Network::SDN::Zones;
+    require PVE::Network::SDN::Vnets;
     $have_sdn = 1;
 };
 
@@ -898,6 +899,8 @@ sub destroy_lxc_container {
 	});
     }
 
+    delete_ifaces_ipams_ips($conf, $vmid);
+
     rmdir "/var/lib/lxc/$vmid/rootfs";
     unlink "/var/lib/lxc/$vmid/config";
     rmdir "/var/lib/lxc/$vmid";
@@ -2729,4 +2732,17 @@ sub thaw($) {
     }
 }
 
+sub delete_ifaces_ipams_ips {
+    my ($conf, $vmid) = @_;
+
+    return if !$have_sdn;
+
+    for my $opt (keys %$conf) {
+	next if $opt !~ m/^net(\d+)$/;
+	my $net = PVE::QemuServer::parse_net($conf->{$opt});
+	eval { PVE::Network::SDN::Vnets::del_ips_from_mac($net->{bridge}, $net->{hwaddr}, $conf->{hostname}) };
+	warn $@ if $@;
+    }
+}
+
 1;
-- 
2.39.2




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

* [pve-devel] [PATCH qemu-server 2/6] vm_start : vm-network-scripts: add_dhcp_reservation
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (4 preceding siblings ...)
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-container 2/6] vm_destroy: remove ips from ipam for all interfaces Alexandre Derumier
@ 2023-11-15 14:21 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-network 3/3] dhcp: delete remove_mapping Alexandre Derumier
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:21 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 vm-network-scripts/pve-bridge | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/vm-network-scripts/pve-bridge b/vm-network-scripts/pve-bridge
index d37ce33..e8f8798 100755
--- a/vm-network-scripts/pve-bridge
+++ b/vm-network-scripts/pve-bridge
@@ -10,6 +10,7 @@ use PVE::Network;
 my $have_sdn;
 eval {
     require PVE::Network::SDN::Zones;
+    require PVE::Network::SDN::Vnets;
     $have_sdn = 1;
 };
 
@@ -44,6 +45,7 @@ my $net = PVE::QemuServer::parse_net($netconf);
 die "unable to parse network config '$netid'\n" if !$net;
 
 if ($have_sdn) {
+    PVE::Network::SDN::Vnets::add_dhcp_mapping($net->{bridge}, $net->{macaddr});
     PVE::Network::SDN::Zones::tap_create($iface, $net->{bridge});
     PVE::Network::SDN::Zones::tap_plug($iface, $net->{bridge}, $net->{tag}, $net->{firewall}, $net->{trunks}, $net->{rate});
 } else {
-- 
2.39.2




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

* [pve-devel] [PATCH pve-network 3/3] dhcp: delete remove_mapping
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (5 preceding siblings ...)
  2023-11-15 14:21 ` [pve-devel] [PATCH qemu-server 2/6] vm_start : vm-network-scripts: add_dhcp_reservation Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 3/6] nic hotplug: add_dhcp_mapping Alexandre Derumier
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

The cleanup of old mac is now done when we add a new mac/ip

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/PVE/API2/Network/SDN/Ipam.pm    |  1 -
 src/PVE/Network/SDN/Dhcp.pm         | 15 -------------
 src/PVE/Network/SDN/Dhcp/Dnsmasq.pm | 34 -----------------------------
 src/PVE/Network/SDN/Dhcp/Plugin.pm  |  5 -----
 4 files changed, 55 deletions(-)

diff --git a/src/PVE/API2/Network/SDN/Ipam.pm b/src/PVE/API2/Network/SDN/Ipam.pm
index 66131e3..68d99a6 100644
--- a/src/PVE/API2/Network/SDN/Ipam.pm
+++ b/src/PVE/API2/Network/SDN/Ipam.pm
@@ -104,7 +104,6 @@ __PACKAGE__->register_method ({
 	my $vnet = extract_param($param, 'vnet');
 	my $mac = extract_param($param, 'mac');
 
-	PVE::Network::SDN::Dhcp::remove_mapping($vnet, $mac);
 	PVE::Network::SDN::Vnets::del_ips_from_mac($vnet, $mac);
 
 	return undef;
diff --git a/src/PVE/Network/SDN/Dhcp.pm b/src/PVE/Network/SDN/Dhcp.pm
index 99561b3..06d03e2 100644
--- a/src/PVE/Network/SDN/Dhcp.pm
+++ b/src/PVE/Network/SDN/Dhcp.pm
@@ -38,21 +38,6 @@ sub add_mapping {
     $dhcp_plugin->add_ip_mapping($zoneid, $macdb, $mac, $ip4, $ip6)
 }
 
-sub remove_mapping {
-    my ($vnetid, $mac) = @_;
-
-    my $vnet = PVE::Network::SDN::Vnets::get_vnet($vnetid);
-    return if !$vnet;
-
-    my $zoneid = $vnet->{zone};
-    my $zone = PVE::Network::SDN::Zones::get_zone($zoneid);
-
-    return if !$zone->{ipam} || !$zone->{dhcp};
-
-    my $dhcp_plugin = PVE::Network::SDN::Dhcp::Plugin->lookup($zone->{dhcp});
-    $dhcp_plugin->del_ip_mapping($zoneid, $mac);
-}
-
 sub regenerate_config {
     my ($reload) = @_;
 
diff --git a/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm b/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
index b672dd3..46172c5 100644
--- a/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
+++ b/src/PVE/Network/SDN/Dhcp/Dnsmasq.pm
@@ -18,40 +18,6 @@ sub type {
     return 'dnsmasq';
 }
 
-sub del_ip_mapping {
-    my ($class, $dhcpid, $mac) = @_;
-
-    my $ethers_file = "$DNSMASQ_CONFIG_ROOT/$dhcpid/ethers";
-    my $ethers_tmp_file = "$ethers_file.tmp";
-
-    my $removeFn = sub {
-	open(my $in, '<', $ethers_file) or die "Could not open file '$ethers_file' $!\n";
-	open(my $out, '>', $ethers_tmp_file) or die "Could not open file '$ethers_tmp_file' $!\n";
-
-        while (my $line = <$in>) {
-	    next if $line =~ m/^$mac/;
-	    print $out $line;
-	}
-
-	close $in;
-	close $out;
-
-	move $ethers_tmp_file, $ethers_file;
-
-	chmod 0644, $ethers_file;
-    };
-
-    PVE::Tools::lock_file($ethers_file, 10, $removeFn);
-
-    if ($@) {
-	warn "Unable to remove $mac from the dnsmasq configuration: $@\n";
-	return;
-    }
-
-    my $service_name = "dnsmasq\@$dhcpid";
-    PVE::Tools::run_command(['systemctl', 'reload', $service_name]);
-}
-
 sub add_ip_mapping {
     my ($class, $dhcpid, $macdb, $mac, $ip4, $ip6) = @_;
 
diff --git a/src/PVE/Network/SDN/Dhcp/Plugin.pm b/src/PVE/Network/SDN/Dhcp/Plugin.pm
index 8d0f7ba..d05378d 100644
--- a/src/PVE/Network/SDN/Dhcp/Plugin.pm
+++ b/src/PVE/Network/SDN/Dhcp/Plugin.pm
@@ -27,11 +27,6 @@ sub add_ip_mapping {
     die 'implement in sub class';
 }
 
-sub del_ip_mapping {
-    my ($class, $dhcp_config, $mac) = @_;
-    die 'implement in sub class';
-}
-
 sub configure_range {
     my ($class, $dhcp_config, $subnet_config, $range_config) = @_;
     die 'implement in sub class';
-- 
2.39.2




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

* [pve-devel] [PATCH qemu-server 3/6] nic hotplug: add_dhcp_mapping
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (6 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-network 3/3] dhcp: delete remove_mapping Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 3/6] vm_create|restore: create ips in ipam Alexandre Derumier
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/QemuServer.pm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index beea2cb..d157f9e 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -5336,6 +5336,7 @@ sub vmconfig_update_net {
 	if ($have_sdn) {
 	    PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge}, $conf->{name}, $newnet->{macaddr}, "vmid:$vmid", undef, 1);
 	}
+	PVE::Network::SDN::Vnets::add_dhcp_mapping($newnet->{bridge}, $newnet->{macaddr});
 	vm_deviceplug($storecfg, $conf, $vmid, $opt, $newnet, $arch, $machine_type);
     } else {
 	die "skip\n";
-- 
2.39.2




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

* [pve-devel] [PATCH pve-container 3/6] vm_create|restore: create ips in ipam
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (7 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 3/6] nic hotplug: add_dhcp_mapping Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 4/6] api2: create|restore|clone: add_free_ip Alexandre Derumier
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

also delete ips on create failure

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/PVE/API2/LXC.pm |  4 ++++
 src/PVE/LXC.pm      | 13 +++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 28d14de..ccacbd2 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -475,9 +475,11 @@ __PACKAGE__->register_method({
 		    if ($restore) {
 			print "merging backed-up and given configuration..\n";
 			PVE::LXC::Create::restore_configuration($vmid, $storage_cfg, $archive, $rootdir, $conf, !$is_root, $unique, $skip_fw_config_restore);
+			PVE::LXC::create_ifaces_ipams_ips($conf, $vmid) if $unique;
 			my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir);
 			$lxc_setup->template_fixup($conf);
 		    } else {
+			PVE::LXC::create_ifaces_ipams_ips($conf, $vmid);
 			my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir); # detect OS
 			PVE::LXC::Config->write_config($vmid, $conf); # safe config (after OS detection)
 			$lxc_setup->post_create_hook($password, $ssh_keys);
@@ -503,6 +505,8 @@ __PACKAGE__->register_method({
 		PVE::LXC::Config->write_config($vmid, $conf);
 	    };
 	    if (my $err = $@) {
+		eval { PVE::LXC::delete_ifaces_ipams_ips($conf, $vmid) };
+		warn $@ if $@;
 		PVE::LXC::destroy_disks($storage_cfg, $vollist);
 		if ($destroy_config_on_error) {
 		    eval { PVE::LXC::Config->destroy_config($vmid) };
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 6f1c6b9..a270dcc 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -2732,6 +2732,19 @@ sub thaw($) {
     }
 }
 
+sub create_ifaces_ipams_ips {
+    my ($conf, $vmid) = @_;
+
+    return if !$have_sdn;
+
+    for my $opt (keys %$conf) {
+	next if $opt !~ m/^net(\d+)$/;
+	my $net = PVE::QemuServer::parse_net($conf->{$opt});
+	next if $net->{type} ne 'veth';
+        PVE::Network::SDN::Vnets::add_next_free_cidr($net->{bridge}, $conf->{hostname}, $net->{hwaddr}, "vmid: $vmid", undef, 1);
+    }
+}
+
 sub delete_ifaces_ipams_ips {
     my ($conf, $vmid) = @_;
 
-- 
2.39.2




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

* [pve-devel] [PATCH qemu-server 4/6] api2: create|restore|clone: add_free_ip
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (8 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 3/6] vm_create|restore: create ips in ipam Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 4/6] vm_clone : create ips in ipams Alexandre Derumier
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/API2/Qemu.pm  |  6 ++++++
 PVE/QemuServer.pm | 15 +++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 38bdaab..a0f8243 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -991,6 +991,8 @@ __PACKAGE__->register_method({
 		    eval { PVE::QemuServer::template_create($vmid, $restored_conf) };
 		    warn $@ if $@;
 		}
+
+		PVE::QemuServer::create_ifaces_ipams_ips($restored_conf, $vmid) if $unique;
 	    };
 
 	    # ensure no old replication state are exists
@@ -1066,6 +1068,8 @@ __PACKAGE__->register_method({
 		}
 
 		PVE::AccessControl::add_vm_to_pool($vmid, $pool) if $pool;
+
+		PVE::QemuServer::create_ifaces_ipams_ips($conf, $vmid);
 	    };
 
 	    PVE::QemuConfig->lock_config_full($vmid, 1, $realcmd);
@@ -3763,6 +3767,8 @@ __PACKAGE__->register_method({
 
 		PVE::QemuConfig->write_config($newid, $newconf);
 
+		PVE::QemuServer::create_ifaces_ipams_ips($newconf, $vmid);
+
 		if ($target) {
 		    # always deactivate volumes - avoid lvm LVs to be active on several nodes
 		    PVE::Storage::deactivate_volumes($storecfg, $vollist, $snapname) if !$running;
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index d157f9e..7248346 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -8629,4 +8629,19 @@ sub del_nets_bridge_fdb {
     }
 }
 
+sub create_ifaces_ipams_ips {
+    my ($conf, $vmid) = @_;
+
+    return if !$have_sdn;
+
+    foreach my $opt (keys %$conf) {
+        if ($opt =~ m/^net(\d+)$/) {
+            my $value = $conf->{$opt};
+            my $net = PVE::QemuServer::parse_net($value);
+            eval { PVE::Network::SDN::Vnets::add_next_free_cidr($net->{bridge}, $conf->{name}, $net->{macaddr}, $vmid, undef, 1) };
+            warn $@ if $@;
+        }
+    }
+}
+
 1;
-- 
2.39.2




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

* [pve-devel] [PATCH pve-container 4/6] vm_clone : create ips in ipams
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (9 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 4/6] api2: create|restore|clone: add_free_ip Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 5/6] vm_apply_pending: add|del ips from ipam for offline changes Alexandre Derumier
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

also delete ips in case of failure

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/PVE/API2/LXC.pm | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index ccacbd2..f18d23b 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -1830,7 +1830,9 @@ __PACKAGE__->register_method({
 		$lock_and_reload->($newid, sub {
 		    my $conf = shift;
 		    my $rootdir = PVE::LXC::mount_all($newid, $storecfg, $conf, 1);
+
 		    eval {
+			PVE::LXC::create_ifaces_ipams_ips($conf, $vmid);
 			my $lxc_setup = PVE::LXC::Setup->new($conf, $rootdir);
 			$lxc_setup->post_clone_hook($conf);
 		    };
@@ -1850,7 +1852,7 @@ __PACKAGE__->register_method({
 	    warn $@ if $@;
 
 	    if ($err) {
-		# Now cleanup the config & disks:
+		# Now cleanup the config & disks & ipam:
 		sleep 1; # some storages like rbd need to wait before release volume - really?
 
 		foreach my $volid (@$newvollist) {
@@ -1860,6 +1862,8 @@ __PACKAGE__->register_method({
 
 		eval {
 		    $lock_and_reload->($newid, sub {
+			my $conf = shift;
+			PVE::LXC::delete_ifaces_ipams_ips($conf, $newid);
 			PVE::LXC::Config->destroy_config($newid);
 			PVE::Firewall::remove_vmfw_conf($newid);
 		    });
-- 
2.39.2




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

* [pve-devel] [PATCH pve-container 5/6] vm_apply_pending: add|del ips from ipam for offline changes
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (10 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 4/6] vm_clone : create ips in ipams Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 5/6] vm_destroy: delete ip from ipam Alexandre Derumier
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/PVE/LXC/Config.pm | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index c884313..f9e5303 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -1471,6 +1471,12 @@ sub vmconfig_apply_pending {
 	    } elsif ($opt =~ m/^unused(\d+)$/) {
 		PVE::LXC::delete_mountpoint_volume($storecfg, $vmid, $conf->{$opt})
 		    if !$class->is_volume_in_use($conf, $conf->{$opt}, 1, 1);
+	    } elsif ($opt =~ m/^net(\d+)$/) {
+		if ($have_sdn) {
+		    my $net = $class->parse_lxc_network($conf->{$opt});
+		    eval { PVE::Network::SDN::Vnets::del_ips_from_mac($net->{bridge}, $net->{hwaddr}, $conf->{hostname}) };
+		    warn $@ if $@;
+		}
 	    }
 	};
 	if (my $err = $@) {
@@ -1493,6 +1499,15 @@ sub vmconfig_apply_pending {
 		my $netid = $1;
 		my $net = $class->parse_lxc_network($conf->{pending}->{$opt});
 		$conf->{pending}->{$opt} = $class->print_lxc_network($net);
+		if ($have_sdn) {
+		    if($conf->{$opt}) {
+			my $old_net = $class->parse_lxc_network($conf->{$opt});
+			if ($old_net->{bridge} ne $net->{bridge} || $old_net->{hwaddr} ne $net->{hwaddr}) {
+			    PVE::Network::SDN::Vnets::del_ips_from_mac($old_net->{bridge}, $old_net->{hwaddr}, $conf->{name});
+			}
+		    }
+		    PVE::Network::SDN::Vnets::add_next_free_cidr($net->{bridge}, $conf->{hostname}, $net->{hwaddr}, "vmid: $vmid", undef, 1);
+		}
 	    }
 	};
 	if (my $err = $@) {
-- 
2.39.2




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

* [pve-devel] [PATCH qemu-server 5/6] vm_destroy: delete ip from ipam
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (11 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 5/6] vm_apply_pending: add|del ips from ipam for offline changes Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 6/6] lxc-pve-prestart-hook : add_dhcp_mapping Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 6/6] nic online bridge/vlan change: link disconnect/reconnect Alexandre Derumier
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

Co-Authored-By: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/QemuServer.pm | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 7248346..4c52026 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -2341,6 +2341,9 @@ sub destroy_vm {
 	});
     }
 
+    eval { delete_ifaces_ipams_ips($conf, $vmid)};
+    warn $@ if $@;
+
     if (defined $replacement_conf) {
 	PVE::QemuConfig->write_config($vmid, $replacement_conf);
     } else {
@@ -8644,4 +8647,18 @@ sub create_ifaces_ipams_ips {
     }
 }
 
+sub delete_ifaces_ipams_ips {
+    my ($conf, $vmid) = @_;
+
+    return if !$have_sdn;
+
+    foreach my $opt (keys %$conf) {
+	if ($opt =~ m/^net(\d+)$/) {
+	    my $net = PVE::QemuServer::parse_net($conf->{$opt});
+	    eval { PVE::Network::SDN::Vnets::del_ips_from_mac($net->{bridge}, $net->{macaddr}, $conf->{name}) };
+	    warn $@ if $@;
+	}
+    }
+}
+
 1;
-- 
2.39.2




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

* [pve-devel] [PATCH pve-container 6/6] lxc-pve-prestart-hook : add_dhcp_mapping
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (12 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 5/6] vm_destroy: delete ip from ipam Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 6/6] nic online bridge/vlan change: link disconnect/reconnect Alexandre Derumier
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 src/lxc-pve-prestart-hook | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/src/lxc-pve-prestart-hook b/src/lxc-pve-prestart-hook
index 936d0bf..fc577e4 100755
--- a/src/lxc-pve-prestart-hook
+++ b/src/lxc-pve-prestart-hook
@@ -21,6 +21,12 @@ use PVE::Storage;
 use PVE::Syscall qw(:fsmount);
 use PVE::Tools qw(AT_FDCWD O_PATH);
 
+my $have_sdn;
+eval {
+    require PVE::Network::SDN::Vnets;
+    $have_sdn = 1;
+};
+
 my $WARNFD;
 sub log_warn {
     my ($vmid, $message) = @_;
@@ -140,6 +146,15 @@ PVE::LXC::Tools::lxc_hook('pre-start', 'lxc', sub {
 	}
 	PVE::Tools::file_set_contents($devlist_file, $devlist);
     }
+
+    if ($have_sdn) {
+	for my $k (keys %$conf) {
+	    next if $k !~ /^net(\d+)/;
+	    my $net = PVE::LXC::Config->parse_lxc_network($conf->{$k});
+	    next if $net->{type} ne 'veth';
+	    PVE::Network::SDN::Vnets::add_dhcp_mapping($net->{bridge}, $net->{hwaddr});
+	}
+    }
 });
 
 # Leftover cgroups prevent lxc from starting without any useful information
-- 
2.39.2




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

* [pve-devel] [PATCH qemu-server 6/6] nic online bridge/vlan change: link disconnect/reconnect
  2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
                   ` (13 preceding siblings ...)
  2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 6/6] lxc-pve-prestart-hook : add_dhcp_mapping Alexandre Derumier
@ 2023-11-15 14:22 ` Alexandre Derumier
  14 siblings, 0 replies; 18+ messages in thread
From: Alexandre Derumier @ 2023-11-15 14:22 UTC (permalink / raw)
  To: pve-devel

We want to notify guest of the change, so it can resubmit dhcp request,
or send gratuitous arp,...

Signed-off-by: Alexandre Derumier <aderumier@odiso.com>
---
 PVE/QemuServer.pm | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 4c52026..1f785a1 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -5309,6 +5309,12 @@ sub vmconfig_update_net {
 		safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
 		PVE::Network::tap_unplug($iface);
 
+		#set link_down in guest if bridge or vlan change to notify guest (dhcp renew for example)
+		if (safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
+		    safe_num_ne($oldnet->{tag}, $newnet->{tag})) {
+		    qemu_set_link_status($vmid, $opt, 0);
+		}
+
 		if (safe_string_ne($oldnet->{bridge}, $newnet->{bridge})) {
 		    if ($have_sdn) {
 			PVE::Network::SDN::Vnets::del_ips_from_mac($oldnet->{bridge}, $oldnet->{macaddr}, $conf->{name});
@@ -5321,6 +5327,13 @@ sub vmconfig_update_net {
 		} else {
 		    PVE::Network::tap_plug($iface, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall}, $newnet->{trunks}, $newnet->{rate});
 		}
+
+		#set link_up in guest if bridge or vlan change to notify guest (dhcp renew for example)
+		if (safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
+		    safe_num_ne($oldnet->{tag}, $newnet->{tag})) {
+		    qemu_set_link_status($vmid, $opt, 1);
+		}
+
 	    } elsif (safe_num_ne($oldnet->{rate}, $newnet->{rate})) {
 		# Rate can be applied on its own but any change above needs to
 		# include the rate in tap_plug since OVS resets everything.
-- 
2.39.2




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

* Re: [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del ips in ipam
  2023-11-15 14:21 ` [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del ips in ipam Alexandre Derumier
@ 2023-11-15 14:56   ` Stefan Hanreich
  2023-11-15 15:19     ` DERUMIER, Alexandre
  0 siblings, 1 reply; 18+ messages in thread
From: Stefan Hanreich @ 2023-11-15 14:56 UTC (permalink / raw)
  To: Proxmox VE development discussion, Alexandre Derumier

On 11/15/23 15:21, Alexandre Derumier wrote:
> +		if ($have_sdn) {
> +		    PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge}, $conf->{hostname}, $newnet->{hwaddr}, "vmid: $vmid", undef, 1);
> +		}

Maybe I missed something, but with Containers we can select either
Static or DHCP. How is this handled?

How should we actually handle this? I would suppose it would make sense
that this logic only kicks in when the NIC is actually set to DHCP,
otherwise we shouldn't do anything?

Also, this is still passing $description rather an a $vmid

> +	PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge}, $conf->{hostname}, $newnet->{hwaddr}, "vmid: $vmid", undef, 1);

^ description instead of vmid as well




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

* Re: [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del ips in ipam
  2023-11-15 14:56   ` Stefan Hanreich
@ 2023-11-15 15:19     ` DERUMIER, Alexandre
  0 siblings, 0 replies; 18+ messages in thread
From: DERUMIER, Alexandre @ 2023-11-15 15:19 UTC (permalink / raw)
  To: pve-devel, aderumier, s.hanreich

-------- Message initial --------
De: Stefan Hanreich <s.hanreich@proxmox.com>
À: Proxmox VE development discussion <pve-devel@lists.proxmox.com>,
Alexandre Derumier <aderumier@odiso.com>
Objet: Re: [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del
ips in ipam
Date: 15/11/2023 15:56:18

On 11/15/23 15:21, Alexandre Derumier wrote:
> + if ($have_sdn) {
> +     PVE::Network::SDN::Vnets::add_next_free_cidr($newnet->{bridge},
> $conf->{hostname}, $newnet->{hwaddr}, "vmid: $vmid", undef, 1);
> + }

>>Maybe I missed something, but with Containers we can select either
>>Static or DHCP. How is this handled?

I don't handle it currently. 


>>How should we actually handle this? I would suppose it would make
>>sense
>>that this logic only kicks in when the NIC is actually set to DHCP,
>>otherwise we shouldn't do anything?

I'm not sure, but maybe we you disable static ip field instead and
force dhcp, if a vnet have dhcp enabled.

if not, user could set a static ip which could be use by another vm in
the dhcp range.



>>Also, this is still passing $description rather an a $vmid

oh, sorry, I totally forgot to change it, I'll fix it.




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

end of thread, other threads:[~2023-11-15 15:20 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-15 14:21 [pve-devel] [PATCH series pve-network/qemu-server/pve-container] DHCP WIP3 Alexandre Derumier
2023-11-15 14:21 ` [pve-devel] [PATCH pve-network 1/3] fix subnets && netbox ipam tests Alexandre Derumier
2023-11-15 14:21 ` [pve-devel] [PATCH pve-container 1/6] nic hotplug : add|del ips in ipam Alexandre Derumier
2023-11-15 14:56   ` Stefan Hanreich
2023-11-15 15:19     ` DERUMIER, Alexandre
2023-11-15 14:21 ` [pve-devel] [PATCH qemu-server 1/6] vmnic add|remove : add|del ip " Alexandre Derumier
2023-11-15 14:21 ` [pve-devel] [PATCH pve-network 2/3] add add_dhcp_mapping Alexandre Derumier
2023-11-15 14:21 ` [pve-devel] [PATCH pve-container 2/6] vm_destroy: remove ips from ipam for all interfaces Alexandre Derumier
2023-11-15 14:21 ` [pve-devel] [PATCH qemu-server 2/6] vm_start : vm-network-scripts: add_dhcp_reservation Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH pve-network 3/3] dhcp: delete remove_mapping Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 3/6] nic hotplug: add_dhcp_mapping Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 3/6] vm_create|restore: create ips in ipam Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 4/6] api2: create|restore|clone: add_free_ip Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 4/6] vm_clone : create ips in ipams Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 5/6] vm_apply_pending: add|del ips from ipam for offline changes Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 5/6] vm_destroy: delete ip from ipam Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH pve-container 6/6] lxc-pve-prestart-hook : add_dhcp_mapping Alexandre Derumier
2023-11-15 14:22 ` [pve-devel] [PATCH qemu-server 6/6] nic online bridge/vlan change: link disconnect/reconnect Alexandre Derumier

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