]> git.proxmox.com Git - pve-container.git/blame - src/PVE/LXC/Setup/Debian.pm
allow older debian versions (>= 4 (etch))
[pve-container.git] / src / PVE / LXC / Setup / Debian.pm
CommitLineData
7af97ad5 1package PVE::LXC::Setup::Debian;
1c7f4f65
DM
2
3use strict;
4use warnings;
55fa4e09 5use Data::Dumper;
a1b1a247 6use PVE::Tools qw($IPV6RE);
55fa4e09
DM
7use PVE::LXC;
8use File::Path;
1c7f4f65 9
7af97ad5 10use PVE::LXC::Setup::Base;
1c7f4f65 11
7af97ad5 12use base qw(PVE::LXC::Setup::Base);
1c7f4f65 13
633a7bd8 14sub new {
5b4657d0 15 my ($class, $conf, $rootdir) = @_;
633a7bd8 16
5b4657d0 17 my $version = PVE::Tools::file_read_firstline("$rootdir/etc/debian_version");
633a7bd8
DM
18
19 die "unable to read version info\n" if !defined($version);
adc8f577
DM
20
21 die "unable to parse version info\n"
22 if $version !~ m/^(\d+(\.\d+)?)(\.\d+)?/;
23
24 $version = $1;
25
27916659 26 die "unsupported debian version '$version'\n"
4596e30d 27 if !($version >= 4 && $version < 9);
633a7bd8 28
5b4657d0
DM
29 my $self = { conf => $conf, rootdir => $rootdir, version => $version };
30
27916659 31 $conf->{ostype} = "debian";
633a7bd8
DM
32
33 return bless $self, $class;
34}
35
d66768a2
DM
36my $default_inittab = <<__EOD__;
37
38# The default runlevel.
39id:2:initdefault:
40
41# Boot-time system configuration/initialization script.
42# This is run first except when booting in emergency (-b) mode.
43si::sysinit:/etc/init.d/rcS
44
45# /etc/init.d executes the S and K scripts upon change
46# of runlevel.
47#
48# Runlevel 0 is halt.
49# Runlevel 1 is single-user.
50# Runlevels 2-5 are multi-user.
51# Runlevel 6 is reboot.
52
53l0:0:wait:/etc/init.d/rc 0
54l1:1:wait:/etc/init.d/rc 1
55l2:2:wait:/etc/init.d/rc 2
56l3:3:wait:/etc/init.d/rc 3
57l4:4:wait:/etc/init.d/rc 4
58l5:5:wait:/etc/init.d/rc 5
59l6:6:wait:/etc/init.d/rc 6
60# Normally not reached, but fallthrough in case of emergency.
61z6:6:respawn:/sbin/sulogin
62
63# What to do when CTRL-ALT-DEL is pressed.
64ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
65
66# What to do when the power fails/returns.
67p0::powerfail:/sbin/init 0
68
69# /sbin/getty invocations for the runlevels.
70#
71# The "id" field MUST be the same as the last
72# characters of the device (after "tty").
73#
74# Format:
75# <id>:<runlevels>:<action>:<process>
76#
77__EOD__
78
79sub setup_init {
633a7bd8 80 my ($self, $conf) = @_;
d66768a2 81
2063d380 82 my $filename = "/etc/inittab";
d66768a2 83
2063d380 84 if ($self->ct_file_exists($filename)) {
d66768a2
DM
85 my $inittab = $default_inittab;
86
0d0ca400 87 my $ttycount = PVE::LXC::get_tty_count($conf);
d66768a2
DM
88 for (my $i = 1; $i <= $ttycount; $i++) {
89 next if $i == 7; # reserved for X11
90 my $levels = ($i == 1) ? '2345' : '23';
5202218d
DM
91 if ($self->{version} < 7) {
92 $inittab .= "$i:$levels:respawn:/sbin/getty -L 38400 tty$i\n";
93 } else {
94 $inittab .= "$i:$levels:respawn:/sbin/getty --noclear 38400 tty$i\n";
95 }
d66768a2
DM
96 }
97
2063d380 98 $self->ct_file_set_contents($filename, $inittab);
d66768a2
DM
99 }
100}
101
55fa4e09 102sub setup_network {
633a7bd8 103 my ($self, $conf) = @_;
55fa4e09 104
55fa4e09
DM
105 my $networks = {};
106 foreach my $k (keys %$conf) {
107 next if $k !~ m/^net(\d+)$/;
93285df8 108 my $ind = $1;
27916659 109 my $d = PVE::LXC::parse_lxc_network($conf->{$k});
55fa4e09
DM
110 if ($d->{name}) {
111 my $net = {};
93285df8 112 if (defined($d->{ip})) {
ecf84da0 113 if ($d->{ip} =~ /^(?:dhcp|manual)$/) {
0178cffa
WB
114 $net->{address} = $d->{ip};
115 } else {
116 my $ipinfo = PVE::LXC::parse_ipv4_cidr($d->{ip});
117 $net->{address} = $ipinfo->{address};
118 $net->{netmask} = $ipinfo->{netmask};
119 }
55fa4e09 120 }
93285df8 121 if (defined($d->{'gw'})) {
a1b1a247 122 $net->{gateway} = $d->{'gw'};
55fa4e09 123 }
93285df8 124 if (defined($d->{ip6})) {
c6b8740b 125 if ($d->{ip6} =~ /^(?:auto|dhcp|manual)$/) {
0178cffa
WB
126 $net->{address6} = $d->{ip6};
127 } elsif ($d->{ip6} !~ /^($IPV6RE)\/(\d+)$/) {
a1b1a247 128 die "unable to parse ipv6 address/prefix\n";
0178cffa
WB
129 } else {
130 $net->{address6} = $1;
131 $net->{netmask6} = $2;
a1b1a247 132 }
a1b1a247
WB
133 }
134 if (defined($d->{'gw6'})) {
135 $net->{gateway6} = $d->{'gw6'};
55fa4e09 136 }
0178cffa 137 $networks->{$d->{name}} = $net if keys %$net;
55fa4e09
DM
138 }
139 }
140
f44d23a5 141 return if !scalar(keys %$networks);
55fa4e09 142
2063d380 143 my $filename = "/etc/network/interfaces";
55fa4e09
DM
144 my $interfaces = "";
145
146 my $section;
147
148 my $done_v4_hash = {};
149 my $done_v6_hash = {};
150
151 my $print_section = sub {
152 my ($new) = @_;
153
154 return if !$section;
155
156 my $net = $networks->{$section->{ifname}};
157
158 if ($section->{type} eq 'ipv4') {
159 $done_v4_hash->{$section->{ifname}} = 1;
160
161 $interfaces .= "auto $section->{ifname}\n" if $new;
162
ecf84da0 163 if ($net->{address} =~ /^(dhcp|manual)$/) {
0178cffa
WB
164 $interfaces .= "iface $section->{ifname} inet $1\n";
165 } elsif ($net->{address}) {
55fa4e09 166 $interfaces .= "iface $section->{ifname} inet static\n";
a1b1a247
WB
167 $interfaces .= "\taddress $net->{address}\n" if defined($net->{address});
168 $interfaces .= "\tnetmask $net->{netmask}\n" if defined($net->{netmask});
169 $interfaces .= "\tgateway $net->{gateway}\n" if defined($net->{gateway});
55fa4e09
DM
170 foreach my $attr (@{$section->{attr}}) {
171 $interfaces .= "\t$attr\n";
172 }
55fa4e09
DM
173 }
174
175 $interfaces .= "\n";
176
177 } elsif ($section->{type} eq 'ipv6') {
178 $done_v6_hash->{$section->{ifname}} = 1;
179
c6b8740b 180 if ($net->{address6} =~ /^(auto|dhcp|manual)$/) {
0178cffa
WB
181 $interfaces .= "iface $section->{ifname} inet6 $1\n";
182 } elsif ($net->{address6}) {
55fa4e09 183 $interfaces .= "iface $section->{ifname} inet6 static\n";
a1b1a247
WB
184 $interfaces .= "\taddress $net->{address6}\n" if defined($net->{address6});
185 $interfaces .= "\tnetmask $net->{netmask6}\n" if defined($net->{netmask6});
186 $interfaces .= "\tgateway $net->{gateway6}\n" if defined($net->{gateway6});
55fa4e09
DM
187 foreach my $attr (@{$section->{attr}}) {
188 $interfaces .= "\t$attr\n";
189 }
190 }
191
192 $interfaces .= "\n";
193 } else {
194 die "unknown section type '$section->{type}'";
195 }
196
197 $section = undef;
198 };
199
2063d380 200 if (my $fh = $self->ct_open_file($filename, "r")) {
55fa4e09
DM
201 while (defined (my $line = <$fh>)) {
202 chomp $line;
203 if ($line =~ m/^#/) {
204 $interfaces .= "$line\n";
205 next;
206 }
207 if ($line =~ m/^\s*$/) {
208 if ($section) {
209 &$print_section();
210 } else {
211 $interfaces .= "$line\n";
212 }
213 next;
214 }
0178cffa 215 if ($line =~ m/^\s*iface\s+(\S+)\s+inet\s+(\S+)\s*$/) {
55fa4e09 216 my $ifname = $1;
0178cffa 217 &$print_section(); # print previous section
55fa4e09
DM
218 if (!$networks->{$ifname}) {
219 $interfaces .= "$line\n";
220 next;
221 }
222 $section = { type => 'ipv4', ifname => $ifname, attr => []};
223 next;
224 }
0178cffa 225 if ($line =~ m/^\s*iface\s+(\S+)\s+inet6\s+(\S+)\s*$/) {
55fa4e09 226 my $ifname = $1;
0178cffa 227 &$print_section(); # print previous section
55fa4e09
DM
228 if (!$networks->{$ifname}) {
229 $interfaces .= "$line\n";
230 next;
231 }
232 $section = { type => 'ipv6', ifname => $ifname, attr => []};
233 next;
234 }
0178cffa
WB
235 # Handle other section delimiters:
236 if ($line =~ m/^\s*(?:mapping\s
237 |auto\s
238 |allow-
239 |source\s
240 |source-directory\s
241 )/x) {
242 &$print_section();
243 $interfaces .= "$line\n";
244 next;
245 }
55fa4e09
DM
246 if ($section && $line =~ m/^\s*((\S+)\s(.*))$/) {
247 my ($adata, $aname) = ($1, $2);
248 if ($aname eq 'address' || $aname eq 'netmask' ||
249 $aname eq 'gateway' || $aname eq 'broadcast') {
250 # skip
251 } else {
252 push @{$section->{attr}}, $adata;
253 }
254 next;
255 }
256
257 $interfaces .= "$line\n";
258 }
259 &$print_section();
260
261 }
262
93285df8 263 my $need_separator = 1;
55fa4e09
DM
264 foreach my $ifname (sort keys %$networks) {
265 my $net = $networks->{$ifname};
93285df8 266
55fa4e09 267 if (!$done_v4_hash->{$ifname}) {
93285df8 268 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
55fa4e09
DM
269 $section = { type => 'ipv4', ifname => $ifname, attr => []};
270 &$print_section(1);
271 }
a1b1a247 272 if (!$done_v6_hash->{$ifname} && defined($net->{address6})) {
93285df8 273 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
55fa4e09
DM
274 $section = { type => 'ipv6', ifname => $ifname, attr => []};
275 &$print_section(1);
276 }
277 }
278
2063d380 279 $self->ct_file_set_contents($filename, $interfaces);
55fa4e09 280}
1c7f4f65
DM
281
2821;