[pve-devel] [RFC container] Setup: add gentoo support

Wolfgang Bumiller w.bumiller at proxmox.com
Thu May 19 15:21:43 CEST 2016


With DHCPv6 we're in a similar boat as with Alpine: The
default templates only ship busybox' udhcpc which doesn't do
ipv6 at all, and if dhclient/dhcpcd are installed there'd
still be no way to configure ONLY dhcpv6 without including
dhcpv4. (We could just dump in a dhclientv6.sh script to
/lib64/netifrc/net/dhclientv6.sh if someone absolutely needs
it...)

Also the fact that the network configuration can in *theory*
be a full blown bash script is a bit inconvenient.
---
Tested with the default LXC gentoo template. Would be nice to hear
some feedback. The network/ipv6 configuration thing is a bit of a
nuisance. Also I'm not sure about whether iproute2 vs ifconfig in
/etc/conf.d/net... so some feedback on that would be useful, too.

For now the /etc/conf.d/net file is modified with section markers
and the replace option set, which means that if no PVE section is
present at all the file will be replaced in full, to deal with the
fact that the deafult file from the template isn't actually empty.

 src/PVE/LXC.pm              |   2 +-
 src/PVE/LXC/Config.pm       |   2 +-
 src/PVE/LXC/Setup.pm        |   4 ++
 src/PVE/LXC/Setup/Gentoo.pm | 152 ++++++++++++++++++++++++++++++++++++++++++++
 src/PVE/LXC/Setup/Makefile  |   2 +-
 5 files changed, 159 insertions(+), 3 deletions(-)
 create mode 100644 src/PVE/LXC/Setup/Gentoo.pm

diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index f712262..759ab6d 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -345,7 +345,7 @@ sub update_lxc_config {
     my $custom_idmap = grep { $_->[0] eq 'lxc.id_map' } @{$conf->{lxc}};
 
     my $ostype = $conf->{ostype} || die "missing 'ostype' - internal error";
-    if ($ostype =~ /^(?:debian | ubuntu | centos | fedora | opensuse | archlinux | alpine | unmanaged)$/x) {
+    if ($ostype =~ /^(?:debian | ubuntu | centos | fedora | opensuse | archlinux | alpine | gentoo | unmanaged)$/x) {
 	my $inc ="/usr/share/lxc/config/$ostype.common.conf";
 	$inc ="/usr/share/lxc/config/common.conf" if !-f $inc;
 	$raw .= "lxc.include = $inc\n";
diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index c467bef..6aaa975 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -253,7 +253,7 @@ my $confdesc = {
     ostype => {
 	optional => 1,
 	type => 'string',
-	enum => ['debian', 'ubuntu', 'centos', 'fedora', 'opensuse', 'archlinux', 'alpine', 'unmanaged'],
+	enum => [qw(debian ubuntu centos fedora opensuse archlinux alpine gentoo unmanaged)],
 	description => "OS type. This is used to setup configuration inside the container, and corresponds to lxc setup scripts in /usr/share/lxc/config/<ostype>.common.conf. Value 'unmanaged' can be used to skip and OS specific setup.",
     },
     console => {
diff --git a/src/PVE/LXC/Setup.pm b/src/PVE/LXC/Setup.pm
index 6568b90..b9e112b 100644
--- a/src/PVE/LXC/Setup.pm
+++ b/src/PVE/LXC/Setup.pm
@@ -12,6 +12,7 @@ use PVE::LXC::Setup::Fedora;
 use PVE::LXC::Setup::SUSE;
 use PVE::LXC::Setup::ArchLinux;
 use PVE::LXC::Setup::Alpine;
+use PVE::LXC::Setup::Gentoo;
 
 my $plugins = {
     debian    => 'PVE::LXC::Setup::Debian',
@@ -21,6 +22,7 @@ my $plugins = {
     opensuse  => 'PVE::LXC::Setup::SUSE',
     archlinux => 'PVE::LXC::Setup::ArchLinux',
     alpine    => 'PVE::LXC::Setup::Alpine',
+    gentoo    => 'PVE::LXC::Setup::Gentoo',
 };
 
 my $autodetect_type = sub {
@@ -46,6 +48,8 @@ my $autodetect_type = sub {
 	return "archlinux";
     } elsif (-f  "$rootdir/etc/alpine-release") {
 	return "alpine";
+    } elsif (-f  "$rootdir/etc/gentoo-release") {
+	return "gentoo";
     }
     die "unable to detect OS distribution\n";
 };
diff --git a/src/PVE/LXC/Setup/Gentoo.pm b/src/PVE/LXC/Setup/Gentoo.pm
new file mode 100644
index 0000000..762cb74
--- /dev/null
+++ b/src/PVE/LXC/Setup/Gentoo.pm
@@ -0,0 +1,152 @@
+package PVE::LXC::Setup::Gentoo;
+
+use strict;
+use warnings;
+
+use File::Path 'make_path';
+
+use PVE::LXC::Setup::Base;
+
+use base qw(PVE::LXC::Setup::Base);
+
+sub new {
+    my ($class, $conf, $rootdir) = @_;
+
+    my $version = PVE::Tools::file_read_firstline("$rootdir/etc/gentoo-release");
+    die "unable to read version info\n" if !defined($version);
+    if ($version =~ /^gentoo base system release (.*)$/i) {
+	$version = $1;
+    } else {
+	die "unrecognized gentoo version: $version\n";
+    }
+
+    my $self = { conf => $conf, rootdir => $rootdir, version => 0 };
+
+    $conf->{ostype} = "gentoo";
+
+    return bless $self, $class;
+}
+
+sub template_fixup {
+    my ($self, $conf) = @_;
+    $self->setup_securetty($conf, qw(lxc/console lxc/tty1 lxc/tty2 lxc/tty3 lxc/tty4));
+}
+
+sub setup_init {
+    my ($self, $conf) = @_;
+
+    my $filename = "/etc/inittab";
+    my $ttycount =  PVE::LXC::Config->get_tty_count($conf);
+    my $inittab = $self->ct_file_get_contents($filename);
+
+    my @lines = grep {
+	    # remove getty lines
+	    !/^\s*c?\d+:\d*:[^:]*:.*getty/
+    } split(/\n/, $inittab);
+
+    $inittab = join("\n", @lines) . "\n";
+
+    for (my $id = 1; $id <= $ttycount; $id++) {
+	next if $id == 7; # reserved for X11
+	$inittab .= "$id\::respawn:/sbin/agetty 38400 tty$id\n";
+    }
+
+    $self->ct_file_set_contents($filename, $inittab);
+}
+
+sub setup_network {
+    my ($self, $conf) = @_;
+
+    # Gentoo's /etc/conf.d/net is supposed to only contains variables, but is
+    # in fact sourced by a shell, so reading out existing modules/config values
+    # is pretty inconvenient.
+    # We SHOULD check for whether iproute2 or ifconfig is already being used,
+    # but for now we just assume ifconfig (since they also state iproute2 might
+    # not be available in a default setup, though the templates usually do have
+    # it installed - we might just get away with an if/else clause to insert
+    # ifconfig/iproute2 syntax as needed, that way we don't need to parse this
+    # file even to support both...)
+
+    my %modules = (ifconfig => 1);
+
+    my $data = '';
+    my %up;
+
+    my $filename = "/etc/conf.d/net";
+
+    foreach my $k (keys %$conf) {
+	next if $k !~ m/^net(\d+)$/;
+	my $d = PVE::LXC::Config->parse_lxc_network($conf->{$k});
+	my $name = $d->{name};
+	next if !$name;
+
+	my $has_ipv4 = 0;
+	my $has_ipv6 = 0;
+
+	my $config = '';
+	my $routes = '';
+
+	if (defined(my $ip = $d->{ip})) {
+	    if ($ip eq 'dhcp') {
+		#$modules{dhclient} = 1; # Well, we could...
+		$config .= "dhcp\n";
+		$up{$name} = 1;
+	    } elsif ($ip ne 'manual') {
+		$has_ipv4 = 1;
+		$config .= "$ip\n";
+		$up{$name} = 1;
+	    }
+	}
+	if (defined(my $gw = $d->{gw})) {
+	    if ($has_ipv4 && !PVE::Network::is_ip_in_cidr($gw, $d->{ip}, 4)) {
+		$routes .= "-host $gw dev $name\n";
+	    }
+	    $routes .= "default gw $gw\n";
+	    $up{$name} = 1;
+	}
+
+	if (defined(my $ip = $d->{ip6})) {
+	    if ($ip eq 'dhcp') {
+		# FIXME: The default templates seem to only ship busybox' udhcp
+		# client which means we're in the same boat as alpine linux.
+		# They also don't provide dhcpv6-only at all - for THAT however
+		# there are patches from way back in 2013 (bug#450326 on
+		# gentoo.org's netifrc)... but whatever, # that's only 10 years
+		# after the RFC3315 release (DHCPv6).
+		#
+		# So no dhcpv6(-only) setups here for now.
+
+		#$modules{dhclientv6} = 1;
+		#$config .= "dhcpv6\n";
+		#$up{$name} = 1;
+	    } elsif ($ip ne 'manual') {
+		$has_ipv6 = 1;
+		$config .= "$ip\n";
+		$up{$name} = 1;
+	    }
+	}
+	if (defined(my $gw = $d->{gw6})) {
+	    if ($has_ipv6 && !PVE::Network::is_ip_in_cidr($gw, $d->{ip6}, 4)) {
+		$routes .= "-6 -host $gw dev $name\n";
+	    }
+	    $routes .= "-6 default gw $gw\n";
+	    $up{$name} = 1;
+	}
+
+	chomp $config;
+	chomp $routes;
+	$data .= "config_$name=\"$config\"\n" if $config;
+	$data .= "routes_$name=\"$routes\"\n" if $routes;
+    }
+
+    $data = "modules=\"\$modules " . join(' ', sort keys %modules) . "\"\n" . $data;
+
+    # We replace the template's default file...
+    $self->ct_modify_file($filename, $data, replace => 1);
+
+    foreach my $iface (keys %up) {
+	$self->ct_symlink("net.lo", "/etc/init.d/net.$iface");
+    }
+}
+
+1;
diff --git a/src/PVE/LXC/Setup/Makefile b/src/PVE/LXC/Setup/Makefile
index f70c898..f971e0b 100644
--- a/src/PVE/LXC/Setup/Makefile
+++ b/src/PVE/LXC/Setup/Makefile
@@ -1,4 +1,4 @@
-SOURCES=Base.pm Debian.pm Ubuntu.pm CentOS.pm Fedora.pm SUSE.pm ArchLinux.pm Alpine.pm
+SOURCES=Base.pm Debian.pm Ubuntu.pm CentOS.pm Fedora.pm SUSE.pm ArchLinux.pm Alpine.pm Gentoo.pm
 
 .PHONY: install
 install:
-- 
2.1.4





More information about the pve-devel mailing list