[pve-devel] [PATCH] fix hotplug ip configuration V3

Alexandre Derumier aderumier at odiso.com
Mon Jun 29 17:20:05 CEST 2015


changelog:
V2: find lxc pid from /proc/

V3: fix parse_lxc_network  (name is mandatory, bridge optionnal)
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 src/PVE/LXC.pm | 191 ++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 162 insertions(+), 29 deletions(-)

diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 76c512d..34650e1 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -775,11 +775,11 @@ sub vmstatus {
 sub print_lxc_network {
     my $net = shift;
 
-    die "no network bridge defined\n" if !$net->{bridge};
+    die "no network name defined\n" if !$net->{name};
 
-    my $res = "bridge=$net->{bridge}";
+    my $res = "name=$net->{name}";
 
-    foreach my $k (qw(hwaddr mtu name ip gw ip6 gw6 firewall tag)) {
+    foreach my $k (qw(hwaddr mtu bridge ip gw ip6 gw6 firewall tag)) {
 	next if !defined($net->{$k});
 	$res .= ",$k=$net->{$k}";
     }
@@ -852,6 +852,25 @@ sub find_lxc_console_pids {
     return $res;
 }
 
+sub find_lxc_pid {
+    my ($vmid) = @_;
+
+    my $res = undef;
+
+    PVE::Tools::dir_glob_foreach('/proc', '\d+', sub {
+        my ($pid) = @_;
+
+        my $cmdline = PVE::Tools::file_read_firstline("/proc/$pid/cmdline");
+        return if !$cmdline;
+
+        if($cmdline =~ m/^init \[2\]/) {
+            my $line = PVE::Tools::file_read_firstline("/proc/$pid/cpuset");
+            $res = $pid if $line eq "/lxc/$vmid";
+        }
+    });
+    return $res;
+}
+
 my $ipv4_reverse_mask = [
     '0.0.0.0',
     '128.0.0.0',
@@ -988,6 +1007,12 @@ sub update_lxc_config {
 
     my @nohotplug;
 
+    my $rootdir = undef;
+    if($running){
+	my $pid = find_lxc_pid($vmid);
+	$rootdir = "/proc/$pid/root/";
+    }
+
     if (defined($delete)) {
 	foreach my $opt (@$delete) {
 	    if ($opt eq 'hostname' || $opt eq 'memory') {
@@ -1025,6 +1050,7 @@ sub update_lxc_config {
 	my $value = $param->{$opt};
 	if ($opt eq 'hostname') {
 	    $conf->{'lxc.utsname'} = $value;
+
 	} elsif ($opt eq 'onboot') {
 	    $conf->{'pve.onboot'} = $value ? 1 : 0;
 	} elsif ($opt eq 'startup') {
@@ -1071,11 +1097,13 @@ sub update_lxc_config {
 	} elsif ($opt =~ m/^net(\d+)$/) {
 	    my $netid = $1;
 	    my $net = PVE::LXC::parse_lxc_network($value);
-	    my $oldnet = $conf->{$opt} ? $conf->{$opt} : undef;
 	    $net->{'veth.pair'} = "veth${vmid}.$netid";
-	    $conf->{$opt} = $net;
-	    next if !$running;
-	    update_net($vmid, $net, $oldnet, $netid);
+ 	    if(!$running) {
+		$conf->{$opt} = $net;
+	    }else{
+		update_net($vmid, $conf, $opt, $net, $netid, $rootdir);
+	    }
+
 	} else {
 	    die "implement me"
 	}
@@ -1143,35 +1171,49 @@ my $safe_string_ne = sub {
 };
 
 sub update_net {
-    my ($vmid, $newnet, $oldnet, $netid) = @_;
+    my ($vmid, $conf, $opt, $newnet, $netid, $rootdir) = @_;
 
     my $veth = $newnet->{'veth.pair'};
     my $vethpeer = $veth."p";
     my $eth = $newnet->{name};
 
-    if ($oldnet) {
-	if (&$safe_string_ne($oldnet->{hwaddr}, $newnet->{hwaddr}) ||
-	    &$safe_string_ne($oldnet->{name}, $newnet->{name})) { 
+    if ($conf->{$opt}) {
+	if (&$safe_string_ne($conf->{$opt}->{hwaddr}, $newnet->{hwaddr}) ||
+	    &$safe_string_ne($conf->{$opt}->{name}, $newnet->{name})) { 
 
             PVE::Network::veth_delete($veth);
-	    hotplug_net($vmid, $newnet);
+	    delete $conf->{$opt};
+	    PVE::LXC::write_config($vmid, $conf);
 
-	} elsif (&$safe_string_ne($oldnet->{bridge}, $newnet->{bridge}) ||
-                &$safe_num_ne($oldnet->{tag}, $newnet->{tag}) ||
-                &$safe_num_ne($oldnet->{firewall}, $newnet->{firewall})) {
+	    hotplug_net($vmid, $conf, $opt, $newnet);
+
+	} elsif (&$safe_string_ne($conf->{$opt}->{bridge}, $newnet->{bridge}) ||
+                &$safe_num_ne($conf->{$opt}->{tag}, $newnet->{tag}) ||
+                &$safe_num_ne($conf->{$opt}->{firewall}, $newnet->{firewall})) {
+
+		if ($conf->{$opt}->{bridge}){
+		    PVE::Network::tap_unplug($veth);
+		    delete $conf->{$opt}->{bridge};
+		    delete $conf->{$opt}->{tag};
+		    delete $conf->{$opt}->{firewall};
+		    PVE::LXC::write_config($vmid, $conf);
+		}
 
-                PVE::Network::tap_unplug($veth);
                 PVE::Network::tap_plug($veth, $newnet->{bridge}, $newnet->{tag}, $newnet->{firewall});
+		$conf->{$opt}->{bridge} = $newnet->{bridge} if $newnet->{bridge};
+		$conf->{$opt}->{tag} = $newnet->{tag} if $newnet->{tag};
+		$conf->{$opt}->{firewall} = $newnet->{firewall} if $newnet->{firewall};
+		PVE::LXC::write_config($vmid, $conf);
 	}
     } else {
-	hotplug_net($vmid, $newnet);
+	hotplug_net($vmid, $conf, $opt, $newnet);
     }
 
-    update_ipconfig($vmid, $eth, $oldnet, $newnet);
+    update_ipconfig($vmid, $conf, $opt, $eth, $newnet, $rootdir);
 }
 
 sub hotplug_net {
-    my ($vmid, $newnet) = @_;
+    my ($vmid, $conf, $opt, $newnet) = @_;
 
     my $veth = $newnet->{'veth.pair'};
     my $vethpeer = $veth."p";
@@ -1187,24 +1229,115 @@ sub hotplug_net {
     #link up peer in container
     $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'link', 'set', $eth ,'up'  ];
     PVE::Tools::run_command($cmd);
+
+    $conf->{$opt}->{type} = 'veth';
+    $conf->{$opt}->{bridge} = $newnet->{bridge} if $newnet->{bridge};
+    $conf->{$opt}->{tag} = $newnet->{tag} if $newnet->{tag};
+    $conf->{$opt}->{firewall} = $newnet->{firewall} if $newnet->{firewall};
+    $conf->{$opt}->{hwaddr} = $newnet->{hwaddr} if $newnet->{hwaddr};
+    $conf->{$opt}->{name} = $newnet->{name} if $newnet->{name};
+    $conf->{$opt}->{'veth.pair'} = $newnet->{'veth.pair'} if $newnet->{'veth.pair'};
+
+    delete $conf->{$opt}->{ip} if $conf->{$opt}->{ip};
+    delete $conf->{$opt}->{ip6} if $conf->{$opt}->{ip6};
+    delete $conf->{$opt}->{gw} if $conf->{$opt}->{gw};
+    delete $conf->{$opt}->{gw6} if $conf->{$opt}->{gw6};
+
+    PVE::LXC::write_config($vmid, $conf);
 }
 
 sub update_ipconfig {
-    my ($vmid, $eth, $oldnet, $newnet) = @_;
+    my ($vmid, $conf, $opt, $eth, $newnet, $rootdir) = @_;
+
+    my $lxc_setup = PVE::LXCSetup->new($conf, $rootdir);
+
+    if (&$safe_string_ne($conf->{$opt}->{ip}, $newnet->{ip})) {
+
+	if ($conf->{$opt}->{ip}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'addr', 'del', $conf->{$opt}->{ip}, 'dev', $eth  ];
+	    PVE::Tools::run_command($cmd);
+
+	    delete $conf->{$opt}->{ip};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+	}
 
+	if ($newnet->{ip}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'addr', 'add', $newnet->{ip}, 'dev', $eth  ];
+	    PVE::Tools::run_command($cmd);
 
-    if (&$safe_string_ne($oldnet->{ip}, $newnet->{ip})) {
-        my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'addr', 'add', $newnet->{ip}, 'dev', $eth  ];
-        PVE::Tools::run_command($cmd);
+	    $conf->{$opt}->{ip} = $newnet->{ip};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+	}
     }
 
-    if (&$safe_string_ne($oldnet->{gw}, $newnet->{gw})) {
-        my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'route', 'add', 'default', 'via', $newnet->{gw} ];
-        PVE::Tools::run_command($cmd);
+
+    if (&$safe_string_ne($conf->{$opt}->{gw}, $newnet->{gw})) {
+
+	if ($conf->{$opt}->{gw}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'route', 'del', 'default', 'via', $conf->{$opt}->{gw} ];
+	    PVE::Tools::run_command($cmd);
+
+	    delete $conf->{$opt}->{gw};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+
+	}
+
+	if ($newnet->{gw}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'route', 'add', 'default', 'via', $newnet->{gw} ];
+	    PVE::Tools::run_command($cmd);
+
+	    $conf->{$opt}->{gw} = $newnet->{gw};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+        }
+    }
+
+    if (&$safe_string_ne($conf->{$opt}->{ip6}, $newnet->{ip6})) {
+
+	if ($conf->{$opt}->{ip6}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'addr', 'del', $conf->{$opt}->{ip6}, 'dev', $eth  ];
+	    PVE::Tools::run_command($cmd);
+
+	    delete $conf->{$opt}->{ip6};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+	}
+
+	if ($newnet->{ip6}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'addr', 'add', $newnet->{ip6}, 'dev', $eth  ];
+	    PVE::Tools::run_command($cmd);
+
+	    $conf->{$opt}->{ip6} = $newnet->{ip6};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+	}
+    }
+
+
+    if (&$safe_string_ne($conf->{$opt}->{gw6}, $newnet->{gw6})) {
+
+	if ($conf->{$opt}->{gw6}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'route', 'del', 'default', 'via', $conf->{$opt}->{gw6} ];
+	    PVE::Tools::run_command($cmd);
+
+	    delete $conf->{$opt}->{gw6};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+
+	}
+
+	if ($newnet->{gw6}) {
+	    my $cmd = ['lxc-attach', '-n', $vmid, '-s', 'NETWORK', '--', '/sbin/ip', 'route', 'add', 'default', 'via', $newnet->{gw6} ];
+	    PVE::Tools::run_command($cmd);
+
+	    $conf->{$opt}->{gw6} = $newnet->{gw6};
+	    PVE::LXC::write_config($vmid, $conf);
+	    $lxc_setup->setup_network($conf);
+        }
     }
-    #fix me : ip,gateway removal
-    #fix me : ipv6
-    #fix me : write /etc/network/interfaces ?
 
 }
 
-- 
2.1.4




More information about the pve-devel mailing list