]> git.proxmox.com Git - pve-container.git/blame - src/PVE/LXC/Setup/Debian.pm
update inittab instead of replacing it
[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 36sub setup_init {
633a7bd8 37 my ($self, $conf) = @_;
d66768a2 38
2063d380 39 my $filename = "/etc/inittab";
fe8a16b8 40 return if !$self->ct_file_exists($filename);
d66768a2 41
fe8a16b8
WB
42 my $ttycount = PVE::LXC::get_tty_count($conf);
43 my $inittab = $self->ct_file_get_contents($filename);
44
45 my @lines = grep {
46 # remove getty lines
47 !/^\s*\d+:\d+:[^:]*:.*getty/ &&
48 # remove power lines
49 !/^\s*p[fno0]:/
50 } split(/\n/, $inittab);
51
52 $inittab = join("\n", @lines) . "\n";
53
54 $inittab .= "p0::powerfail:/sbin/init 0\n";
55
56 my $version = $self->{version};
57 my $levels = '2345';
58 for my $id (1..$ttycount) {
59 if ($version < 7) {
60 $inittab .= "$id:$levels:respawn:/sbin/getty -L 38400 tty$id\n";
61 } else {
62 $inittab .= "$id:$levels:respawn:/sbin/getty --noclear 38400 tty$id\n";
d66768a2 63 }
fe8a16b8 64 $levels = '23';
d66768a2 65 }
fe8a16b8
WB
66
67 $self->ct_file_set_contents($filename, $inittab);
d66768a2
DM
68}
69
55fa4e09 70sub setup_network {
633a7bd8 71 my ($self, $conf) = @_;
55fa4e09 72
55fa4e09
DM
73 my $networks = {};
74 foreach my $k (keys %$conf) {
75 next if $k !~ m/^net(\d+)$/;
93285df8 76 my $ind = $1;
27916659 77 my $d = PVE::LXC::parse_lxc_network($conf->{$k});
55fa4e09
DM
78 if ($d->{name}) {
79 my $net = {};
93285df8 80 if (defined($d->{ip})) {
ecf84da0 81 if ($d->{ip} =~ /^(?:dhcp|manual)$/) {
0178cffa
WB
82 $net->{address} = $d->{ip};
83 } else {
84 my $ipinfo = PVE::LXC::parse_ipv4_cidr($d->{ip});
85 $net->{address} = $ipinfo->{address};
86 $net->{netmask} = $ipinfo->{netmask};
87 }
55fa4e09 88 }
93285df8 89 if (defined($d->{'gw'})) {
a1b1a247 90 $net->{gateway} = $d->{'gw'};
55fa4e09 91 }
93285df8 92 if (defined($d->{ip6})) {
c6b8740b 93 if ($d->{ip6} =~ /^(?:auto|dhcp|manual)$/) {
0178cffa
WB
94 $net->{address6} = $d->{ip6};
95 } elsif ($d->{ip6} !~ /^($IPV6RE)\/(\d+)$/) {
a1b1a247 96 die "unable to parse ipv6 address/prefix\n";
0178cffa
WB
97 } else {
98 $net->{address6} = $1;
99 $net->{netmask6} = $2;
a1b1a247 100 }
a1b1a247
WB
101 }
102 if (defined($d->{'gw6'})) {
103 $net->{gateway6} = $d->{'gw6'};
55fa4e09 104 }
0178cffa 105 $networks->{$d->{name}} = $net if keys %$net;
55fa4e09
DM
106 }
107 }
108
f44d23a5 109 return if !scalar(keys %$networks);
55fa4e09 110
2063d380 111 my $filename = "/etc/network/interfaces";
55fa4e09
DM
112 my $interfaces = "";
113
114 my $section;
115
116 my $done_v4_hash = {};
117 my $done_v6_hash = {};
118
119 my $print_section = sub {
120 my ($new) = @_;
121
122 return if !$section;
123
124 my $net = $networks->{$section->{ifname}};
125
126 if ($section->{type} eq 'ipv4') {
127 $done_v4_hash->{$section->{ifname}} = 1;
128
129 $interfaces .= "auto $section->{ifname}\n" if $new;
130
ecf84da0 131 if ($net->{address} =~ /^(dhcp|manual)$/) {
0178cffa
WB
132 $interfaces .= "iface $section->{ifname} inet $1\n";
133 } elsif ($net->{address}) {
55fa4e09 134 $interfaces .= "iface $section->{ifname} inet static\n";
a1b1a247
WB
135 $interfaces .= "\taddress $net->{address}\n" if defined($net->{address});
136 $interfaces .= "\tnetmask $net->{netmask}\n" if defined($net->{netmask});
137 $interfaces .= "\tgateway $net->{gateway}\n" if defined($net->{gateway});
55fa4e09
DM
138 foreach my $attr (@{$section->{attr}}) {
139 $interfaces .= "\t$attr\n";
140 }
55fa4e09
DM
141 }
142
143 $interfaces .= "\n";
144
145 } elsif ($section->{type} eq 'ipv6') {
146 $done_v6_hash->{$section->{ifname}} = 1;
147
c6b8740b 148 if ($net->{address6} =~ /^(auto|dhcp|manual)$/) {
0178cffa
WB
149 $interfaces .= "iface $section->{ifname} inet6 $1\n";
150 } elsif ($net->{address6}) {
55fa4e09 151 $interfaces .= "iface $section->{ifname} inet6 static\n";
a1b1a247
WB
152 $interfaces .= "\taddress $net->{address6}\n" if defined($net->{address6});
153 $interfaces .= "\tnetmask $net->{netmask6}\n" if defined($net->{netmask6});
154 $interfaces .= "\tgateway $net->{gateway6}\n" if defined($net->{gateway6});
55fa4e09
DM
155 foreach my $attr (@{$section->{attr}}) {
156 $interfaces .= "\t$attr\n";
157 }
158 }
159
160 $interfaces .= "\n";
161 } else {
162 die "unknown section type '$section->{type}'";
163 }
164
165 $section = undef;
166 };
167
2063d380 168 if (my $fh = $self->ct_open_file($filename, "r")) {
55fa4e09
DM
169 while (defined (my $line = <$fh>)) {
170 chomp $line;
171 if ($line =~ m/^#/) {
172 $interfaces .= "$line\n";
173 next;
174 }
175 if ($line =~ m/^\s*$/) {
176 if ($section) {
177 &$print_section();
178 } else {
179 $interfaces .= "$line\n";
180 }
181 next;
182 }
0178cffa 183 if ($line =~ m/^\s*iface\s+(\S+)\s+inet\s+(\S+)\s*$/) {
55fa4e09 184 my $ifname = $1;
0178cffa 185 &$print_section(); # print previous section
55fa4e09
DM
186 if (!$networks->{$ifname}) {
187 $interfaces .= "$line\n";
188 next;
189 }
190 $section = { type => 'ipv4', ifname => $ifname, attr => []};
191 next;
192 }
0178cffa 193 if ($line =~ m/^\s*iface\s+(\S+)\s+inet6\s+(\S+)\s*$/) {
55fa4e09 194 my $ifname = $1;
0178cffa 195 &$print_section(); # print previous section
55fa4e09
DM
196 if (!$networks->{$ifname}) {
197 $interfaces .= "$line\n";
198 next;
199 }
200 $section = { type => 'ipv6', ifname => $ifname, attr => []};
201 next;
202 }
0178cffa
WB
203 # Handle other section delimiters:
204 if ($line =~ m/^\s*(?:mapping\s
205 |auto\s
206 |allow-
207 |source\s
208 |source-directory\s
209 )/x) {
210 &$print_section();
211 $interfaces .= "$line\n";
212 next;
213 }
55fa4e09
DM
214 if ($section && $line =~ m/^\s*((\S+)\s(.*))$/) {
215 my ($adata, $aname) = ($1, $2);
216 if ($aname eq 'address' || $aname eq 'netmask' ||
217 $aname eq 'gateway' || $aname eq 'broadcast') {
218 # skip
219 } else {
220 push @{$section->{attr}}, $adata;
221 }
222 next;
223 }
224
225 $interfaces .= "$line\n";
226 }
227 &$print_section();
228
229 }
230
93285df8 231 my $need_separator = 1;
55fa4e09
DM
232 foreach my $ifname (sort keys %$networks) {
233 my $net = $networks->{$ifname};
93285df8 234
55fa4e09 235 if (!$done_v4_hash->{$ifname}) {
93285df8 236 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
55fa4e09
DM
237 $section = { type => 'ipv4', ifname => $ifname, attr => []};
238 &$print_section(1);
239 }
a1b1a247 240 if (!$done_v6_hash->{$ifname} && defined($net->{address6})) {
93285df8 241 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
55fa4e09
DM
242 $section = { type => 'ipv6', ifname => $ifname, attr => []};
243 &$print_section(1);
244 }
245 }
246
2063d380 247 $self->ct_file_set_contents($filename, $interfaces);
55fa4e09 248}
1c7f4f65
DM
249
2501;