]> git.proxmox.com Git - pve-container.git/blob - src/PVE/LXC/Setup/Debian.pm
setup/debian: remove superfluous parameter
[pve-container.git] / src / PVE / LXC / Setup / Debian.pm
1 package PVE::LXC::Setup::Debian;
2
3 use strict;
4 use warnings;
5 use Data::Dumper;
6 use PVE::Tools qw($IPV6RE);
7 use PVE::LXC;
8 use File::Path;
9
10 use PVE::LXC::Setup::Base;
11
12 use base qw(PVE::LXC::Setup::Base);
13
14 sub new {
15 my ($class, $conf, $rootdir) = @_;
16
17 my $version = PVE::Tools::file_read_firstline("$rootdir/etc/debian_version");
18
19 die "unable to read version info\n" if !defined($version);
20
21 die "unable to parse version info\n"
22 if $version !~ m/^(\d+(\.\d+)?)(\.\d+)?/;
23
24 $version = $1;
25
26 die "unsupported debian version '$version'\n"
27 if !($version >= 4 && $version < 9);
28
29 my $self = { conf => $conf, rootdir => $rootdir, version => $version };
30
31 $conf->{ostype} = "debian";
32
33 return bless $self, $class;
34 }
35
36 sub setup_init {
37 my ($self, $conf) = @_;
38
39 my $filename = "/etc/inittab";
40 return if !$self->ct_file_exists($filename);
41
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 for (my $id = 1; $id <= $ttycount; $id++) {
58 next if $id == 7; # reserved for X11
59 my $levels = ($id == 1) ? '2345' : '23';
60 if ($version < 7) {
61 $inittab .= "$id:$levels:respawn:/sbin/getty -L 38400 tty$id\n";
62 } else {
63 $inittab .= "$id:$levels:respawn:/sbin/getty --noclear 38400 tty$id\n";
64 }
65 }
66
67 $self->ct_file_set_contents($filename, $inittab);
68 }
69
70 sub setup_network {
71 my ($self, $conf) = @_;
72
73 my $networks = {};
74 foreach my $k (keys %$conf) {
75 next if $k !~ m/^net(\d+)$/;
76 my $ind = $1;
77 my $d = PVE::LXC::parse_lxc_network($conf->{$k});
78 if ($d->{name}) {
79 my $net = {};
80 if (defined($d->{ip})) {
81 if ($d->{ip} =~ /^(?:dhcp|manual)$/) {
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 }
88 }
89 if (defined($d->{'gw'})) {
90 $net->{gateway} = $d->{'gw'};
91 }
92 if (defined($d->{ip6})) {
93 if ($d->{ip6} =~ /^(?:auto|dhcp|manual)$/) {
94 $net->{address6} = $d->{ip6};
95 } elsif ($d->{ip6} !~ /^($IPV6RE)\/(\d+)$/) {
96 die "unable to parse ipv6 address/prefix\n";
97 } else {
98 $net->{address6} = $1;
99 $net->{netmask6} = $2;
100 }
101 }
102 if (defined($d->{'gw6'})) {
103 $net->{gateway6} = $d->{'gw6'};
104 }
105 $networks->{$d->{name}} = $net if keys %$net;
106 }
107 }
108
109 return if !scalar(keys %$networks);
110
111 my $filename = "/etc/network/interfaces";
112 my $interfaces = "";
113
114 my $section;
115
116 my $done_auto = {};
117 my $done_v4_hash = {};
118 my $done_v6_hash = {};
119
120 my $print_section = sub {
121 return if !$section;
122
123 my $ifname = $section->{ifname};
124 my $net = $networks->{$ifname};
125
126 if (!$done_auto->{$ifname}) {
127 $interfaces .= "auto $ifname\n";
128 $done_auto->{$ifname} = 1;
129 }
130
131 if ($section->{type} eq 'ipv4') {
132 $done_v4_hash->{$ifname} = 1;
133
134 if ($net->{address} =~ /^(dhcp|manual)$/) {
135 $interfaces .= "iface $ifname inet $1\n";
136 } else {
137 $interfaces .= "iface $ifname inet static\n";
138 $interfaces .= "\taddress $net->{address}\n" if defined($net->{address});
139 $interfaces .= "\tnetmask $net->{netmask}\n" if defined($net->{netmask});
140 $interfaces .= "\tgateway $net->{gateway}\n" if defined($net->{gateway});
141 foreach my $attr (@{$section->{attr}}) {
142 $interfaces .= "\t$attr\n";
143 }
144 }
145
146 $interfaces .= "\n";
147
148 } elsif ($section->{type} eq 'ipv6') {
149 $done_v6_hash->{$ifname} = 1;
150
151 if ($net->{address6} =~ /^(auto|dhcp|manual)$/) {
152 $interfaces .= "iface $ifname inet6 $1\n";
153 } else {
154 $interfaces .= "iface $ifname inet6 static\n";
155 $interfaces .= "\taddress $net->{address6}\n" if defined($net->{address6});
156 $interfaces .= "\tnetmask $net->{netmask6}\n" if defined($net->{netmask6});
157 $interfaces .= "\tgateway $net->{gateway6}\n" if defined($net->{gateway6});
158 foreach my $attr (@{$section->{attr}}) {
159 $interfaces .= "\t$attr\n";
160 }
161 }
162
163 $interfaces .= "\n";
164 } else {
165 die "unknown section type '$section->{type}'";
166 }
167
168 $section = undef;
169 };
170
171 if (my $fh = $self->ct_open_file($filename, "r")) {
172 while (defined (my $line = <$fh>)) {
173 chomp $line;
174 if ($line =~ m/^#/) {
175 $interfaces .= "$line\n";
176 next;
177 }
178 if ($line =~ m/^\s*$/) {
179 if ($section) {
180 &$print_section();
181 } else {
182 $interfaces .= "$line\n";
183 }
184 next;
185 }
186 if ($line =~ m/^\s*iface\s+(\S+)\s+inet\s+(\S+)\s*$/) {
187 my $ifname = $1;
188 &$print_section(); # print previous section
189 if (!$networks->{$ifname}) {
190 $interfaces .= "$line\n";
191 next;
192 }
193 $section = { type => 'ipv4', ifname => $ifname, attr => []};
194 next;
195 }
196 if ($line =~ m/^\s*iface\s+(\S+)\s+inet6\s+(\S+)\s*$/) {
197 my $ifname = $1;
198 &$print_section(); # print previous section
199 if (!$networks->{$ifname}) {
200 $interfaces .= "$line\n";
201 next;
202 }
203 $section = { type => 'ipv6', ifname => $ifname, attr => []};
204 next;
205 }
206 # Handle 'auto'
207 if ($line =~ m/^\s*auto\s*(.*)$/) {
208 foreach my $iface (split(/\s+/, $1)) {
209 $done_auto->{$iface} = 1;
210 }
211 &$print_section();
212 $interfaces .= "$line\n";
213 next;
214 }
215 # Handle other section delimiters:
216 if ($line =~ m/^\s*(?:mapping\s
217 |allow-
218 |source\s
219 |source-directory\s
220 )/x) {
221 &$print_section();
222 $interfaces .= "$line\n";
223 next;
224 }
225 if ($section && $line =~ m/^\s*((\S+)\s(.*))$/) {
226 my ($adata, $aname) = ($1, $2);
227 if ($aname eq 'address' || $aname eq 'netmask' ||
228 $aname eq 'gateway' || $aname eq 'broadcast') {
229 # skip
230 } else {
231 push @{$section->{attr}}, $adata;
232 }
233 next;
234 }
235
236 $interfaces .= "$line\n";
237 }
238 &$print_section();
239 }
240
241 my $need_separator = length($interfaces) && ($interfaces !~ /\n\n$/);
242 foreach my $ifname (sort keys %$networks) {
243 my $net = $networks->{$ifname};
244
245 if (!$done_v4_hash->{$ifname} && defined($net->{address})) {
246 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
247 $section = { type => 'ipv4', ifname => $ifname, attr => []};
248 &$print_section();
249 }
250 if (!$done_v6_hash->{$ifname} && defined($net->{address6})) {
251 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
252 $section = { type => 'ipv6', ifname => $ifname, attr => []};
253 &$print_section();
254 }
255 }
256
257 $self->ct_file_set_contents($filename, $interfaces);
258 }
259
260 1;