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