]> git.proxmox.com Git - pve-container.git/blob - src/PVE/LXC/Setup/SUSE.pm
d/control: bump versioned dependency for guest-common
[pve-container.git] / src / PVE / LXC / Setup / SUSE.pm
1 package PVE::LXC::Setup::SUSE;
2
3 use strict;
4 use warnings;
5
6 use PVE::LXC::Setup::Base;
7
8 use base qw(PVE::LXC::Setup::Base);
9
10 sub new {
11 my ($class, $conf, $rootdir, $os_release) = @_;
12
13 my $version = $os_release->{VERSION_ID};
14 my $ostype = $os_release->{ID};
15
16 if ($version =~ m/^(\d+)\.(\d+)$/) {
17 my ($major, $minor) = ($1, $2);
18 if ($major >= 42) {
19 # OK
20 } elsif ($major == 13 && $minor <= 2) {
21 # OK
22 } elsif ($ostype eq 'sles' && $major == 12) {
23 # OK - shares base with LEAP (42)
24 } elsif ($major == 15) {
25 # OK for SLES and openSUSE Leap, see: https://lwn.net/Articles/720924/
26 } else {
27 die "unsupported suse release '$version'\n";
28 }
29 } elsif ($version =~ m/^(\d{4})(\d{2})(\d{2})$/) {
30 my ($year, $month, $day) = ($1, $2, $3);
31 if ($year >= 2017 && $month <= 12 && $day <= 31) {
32 # OK
33 } else {
34 die "unsupported suse tumbleweed release '$version'\n";
35 }
36 } else {
37 die "unrecognized suse release";
38 }
39
40 my $self = { conf => $conf, rootdir => $rootdir, version => $version, os_release => $os_release };
41
42 $conf->{ostype} = 'opensuse';
43
44 return bless $self, $class;
45 }
46
47 sub template_fixup {
48 my ($self, $conf) = @_;
49
50 $self->setup_securetty($conf);
51
52 # temporary fix for systemd-firstboot
53 $self->ct_file_set_contents('/etc/locale.conf', "LANG=C.utf8") if !$self->ct_file_exists('/etc/locale.conf');
54 $self->ct_symlink('/usr/share/zoneinfo/UTC', '/etc/localtime') if !$self->ct_file_exists('/etc/localtime');
55
56 $self->remove_lxc_name_from_etc_hosts();
57 }
58
59 sub setup_init {
60 my ($self, $conf) = @_;
61
62 $self->fixup_old_getty();
63
64 $self->setup_container_getty_service($conf);
65 }
66
67 sub setup_network {
68 my ($self, $conf) = @_;
69
70 my ($gw, $gw6);
71
72 $self->ct_make_path('/etc/sysconfig/network');
73
74 foreach my $k (keys %$conf) {
75 next if $k !~ m/^net(\d+)$/;
76 my $d = PVE::LXC::Config->parse_lxc_network($conf->{$k});
77 next if !$d->{name};
78
79 my $filename = "/etc/sysconfig/network/ifcfg-$d->{name}";
80 my $routefile = "/etc/sysconfig/network/ifroute-$d->{name}";
81 my $routes = '';
82
83 my @DHCPMODES = ('static', 'dhcp4', 'dhcp6', 'dhcp');
84 my ($NONE, $DHCP4, $DHCP6, $BOTH) = (0, 1, 2, 3);
85 my $dhcp = $NONE;
86 my @addrs = ();
87
88 my $data = '';
89 my $is_configured = 0;
90
91 if ($d->{ip} && $d->{ip} ne 'manual') {
92 $is_configured = 1;
93 if ($d->{ip} eq 'dhcp') {
94 $dhcp |= $DHCP4;
95 } else {
96 push @addrs, $d->{ip};
97 if (defined($d->{gw})) {
98 if (!PVE::Network::is_ip_in_cidr($d->{gw}, $d->{ip}, 4)) {
99 $routes .= "$d->{gw} 0.0.0.0 255.255.255.255 $d->{name}\n";
100 }
101 $routes .= "default $d->{gw} 0.0.0.0 $d->{name}\n";
102 }
103 }
104 }
105
106 if ($d->{ip6} && $d->{ip6} ne 'manual') {
107 $is_configured = 1;
108 if ($d->{ip6} eq 'auto') {
109 # FIXME: Not sure what to do here...
110 } elsif ($d->{ip6} eq 'dhcp') {
111 $dhcp |= $DHCP6;
112 } else {
113 push @addrs, $d->{ip6};
114 if (defined($d->{gw6})) {
115 if (!PVE::Network::is_ip_in_cidr($d->{gw6}, $d->{ip6}, 6) &&
116 !PVE::Network::is_ip_in_cidr($d->{gw6}, 'fe80::/10', 6)) {
117 $routes .= "$d->{gw6}/128 - - $d->{name}\n";
118 }
119 $routes .= "default $d->{gw6} - $d->{name}\n";
120 }
121 }
122 }
123
124 if (@addrs > 1) {
125 for my $i (1..@addrs) {
126 $data .= "IPADDR_${i}=$addrs[$i-1]\n";
127 }
128 } elsif (@addrs) {
129 $data .= "IPADDR=$addrs[0]\n";
130 } else {
131 # check for non-manual config with no dhcp and no addresses
132 next if $is_configured && $dhcp == $NONE;
133 }
134
135 $data = "STARTMODE=" . ($is_configured ? 'onboot' : 'manual') . "\n"
136 . "BOOTPROTO=$DHCPMODES[$dhcp]\n"
137 . $data;
138 $self->ct_file_set_contents($filename, $data);
139
140 # To keep user-defined routes in route-$iface we mark ours:
141 $self->ct_modify_file($routefile, $routes, delete => 1, prepend => 1);
142 }
143 }
144
145 1;