From ed027b5844d384c37d15cebd96bbd46ecf1914b7 Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Thu, 19 May 2016 15:21:43 +0200 Subject: [PATCH] Setup: add gentoo support 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. --- 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 9d805fc..83e5728 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/.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.39.2