1 package PVE
::LXCSetup
::Debian
;
6 use PVE
::Tools
qw($IPV6RE);
10 use PVE
::LXCSetup
::Base
;
12 use base
qw(PVE::LXCSetup::Base);
15 my ($class, $conf, $rootdir) = @_;
17 my $version = PVE
::Tools
::file_read_firstline
("$rootdir/etc/debian_version");
19 die "unable to read version info\n" if !defined($version);
21 die "unable to parse version info\n"
22 if $version !~ m/^(\d+(\.\d+)?)(\.\d+)?/;
26 die "unsupported debian version '$version'\n" if $version < 6;
28 my $self = { conf
=> $conf, rootdir
=> $rootdir, version
=> $version };
30 $conf->{'lxc.include'} = "/usr/share/lxc/config/debian.common.conf";
32 return bless $self, $class;
35 my $default_inittab = <<__EOD__;
37 # The default runlevel.
40 # Boot-time system configuration/initialization script.
41 # This is run first except when booting in emergency (-b) mode.
42 si::sysinit:/etc/init.d/rcS
44 # /etc/init.d executes the S and K scripts upon change
48 # Runlevel 1 is single-user.
49 # Runlevels 2-5 are multi-user.
50 # Runlevel 6 is reboot.
52 l0:0:wait:/etc/init.d/rc 0
53 l1:1:wait:/etc/init.d/rc 1
54 l2:2:wait:/etc/init.d/rc 2
55 l3:3:wait:/etc/init.d/rc 3
56 l4:4:wait:/etc/init.d/rc 4
57 l5:5:wait:/etc/init.d/rc 5
58 l6:6:wait:/etc/init.d/rc 6
59 # Normally not reached, but fallthrough in case of emergency.
60 z6:6:respawn:/sbin/sulogin
62 # What to do when CTRL-ALT-DEL is pressed.
63 ca:12345:ctrlaltdel:/sbin/shutdown -t1 -a -r now
65 # What to do when the power fails/returns.
66 p0::powerfail:/sbin/init 0
68 # /sbin/getty invocations for the runlevels.
70 # The "id" field MUST be the same as the last
71 # characters of the device (after "tty").
74 # <id>:<runlevels>:<action>:<process>
79 my ($self, $conf) = @_;
81 my $rootdir = $self->{rootdir
};
83 my $filename = "$rootdir/etc/inittab";
86 my $inittab = $default_inittab;
88 my $ttycount = defined($conf->{'lxc.tty'}) ?
$conf->{'lxc.tty'} : 4;
89 for (my $i = 1; $i <= $ttycount; $i++) {
90 next if $i == 7; # reserved for X11
91 my $levels = ($i == 1) ?
'2345' : '23';
92 if ($self->{version
} < 7) {
93 $inittab .= "$i:$levels:respawn:/sbin/getty -L 38400 tty$i\n";
95 $inittab .= "$i:$levels:respawn:/sbin/getty --noclear 38400 tty$i\n";
99 PVE
::Tools
::file_set_contents
($filename, $inittab);
104 my ($self, $conf) = @_;
106 my $rootdir = $self->{rootdir
};
109 foreach my $k (keys %$conf) {
110 next if $k !~ m/^net(\d+)$/;
115 if (defined($d->{ip
})) {
116 if ($d->{ip
} =~ /^(?:dhcp|manual)$/) {
117 $net->{address
} = $d->{ip
};
119 my $ipinfo = PVE
::LXC
::parse_ipv4_cidr
($d->{ip
});
120 $net->{address
} = $ipinfo->{address
};
121 $net->{netmask
} = $ipinfo->{netmask
};
124 if (defined($d->{'gw'})) {
125 $net->{gateway
} = $d->{'gw'};
127 if (defined($d->{ip6
})) {
128 if ($d->{ip6
} =~ /^(?:dhcp|manual)$/) {
129 $net->{address6
} = $d->{ip6
};
130 } elsif ($d->{ip6
} !~ /^($IPV6RE)\/(\d
+)$/) {
131 die "unable to parse ipv6 address/prefix\n";
133 $net->{address6
} = $1;
134 $net->{netmask6
} = $2;
137 if (defined($d->{'gw6'})) {
138 $net->{gateway6
} = $d->{'gw6'};
140 $networks->{$d->{name
}} = $net if keys %$net;
144 return if !scalar(keys %$networks);
146 my $filename = "$rootdir/etc/network/interfaces";
151 my $done_v4_hash = {};
152 my $done_v6_hash = {};
154 my $print_section = sub {
159 my $net = $networks->{$section->{ifname
}};
161 if ($section->{type
} eq 'ipv4') {
162 $done_v4_hash->{$section->{ifname
}} = 1;
164 $interfaces .= "auto $section->{ifname}\n" if $new;
166 if ($net->{address
} =~ /^(dhcp|manual)$/) {
167 $interfaces .= "iface $section->{ifname} inet $1\n";
168 } elsif ($net->{address
}) {
169 $interfaces .= "iface $section->{ifname} inet static\n";
170 $interfaces .= "\taddress $net->{address}\n" if defined($net->{address
});
171 $interfaces .= "\tnetmask $net->{netmask}\n" if defined($net->{netmask
});
172 $interfaces .= "\tgateway $net->{gateway}\n" if defined($net->{gateway
});
173 foreach my $attr (@{$section->{attr
}}) {
174 $interfaces .= "\t$attr\n";
180 } elsif ($section->{type
} eq 'ipv6') {
181 $done_v6_hash->{$section->{ifname
}} = 1;
183 if ($net->{address6
} =~ /^(dhcp|manual)$/) {
184 $interfaces .= "iface $section->{ifname} inet6 $1\n";
185 } elsif ($net->{address6
}) {
186 $interfaces .= "iface $section->{ifname} inet6 static\n";
187 $interfaces .= "\taddress $net->{address6}\n" if defined($net->{address6
});
188 $interfaces .= "\tnetmask $net->{netmask6}\n" if defined($net->{netmask6
});
189 $interfaces .= "\tgateway $net->{gateway6}\n" if defined($net->{gateway6
});
190 foreach my $attr (@{$section->{attr
}}) {
191 $interfaces .= "\t$attr\n";
197 die "unknown section type '$section->{type}'";
203 if (my $fh = IO
::File-
>new($filename, "r")) {
204 while (defined (my $line = <$fh>)) {
206 if ($line =~ m/^#/) {
207 $interfaces .= "$line\n";
210 if ($line =~ m/^\s*$/) {
214 $interfaces .= "$line\n";
218 if ($line =~ m/^\s*iface\s+(\S+)\s+inet\s+(\S+)\s*$/) {
220 &$print_section(); # print previous section
221 if (!$networks->{$ifname}) {
222 $interfaces .= "$line\n";
225 $section = { type
=> 'ipv4', ifname
=> $ifname, attr
=> []};
228 if ($line =~ m/^\s*iface\s+(\S+)\s+inet6\s+(\S+)\s*$/) {
230 &$print_section(); # print previous section
231 if (!$networks->{$ifname}) {
232 $interfaces .= "$line\n";
235 $section = { type
=> 'ipv6', ifname
=> $ifname, attr
=> []};
238 # Handle other section delimiters:
239 if ($line =~ m
/^\s
*(?
:mapping\s
246 $interfaces .= "$line\n";
249 if ($section && $line =~ m/^\s*((\S+)\s(.*))$/) {
250 my ($adata, $aname) = ($1, $2);
251 if ($aname eq 'address' || $aname eq 'netmask' ||
252 $aname eq 'gateway' || $aname eq 'broadcast') {
255 push @{$section->{attr
}}, $adata;
260 $interfaces .= "$line\n";
266 my $need_separator = 1;
267 foreach my $ifname (sort keys %$networks) {
268 my $net = $networks->{$ifname};
270 if (!$done_v4_hash->{$ifname}) {
271 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
272 $section = { type
=> 'ipv4', ifname
=> $ifname, attr
=> []};
275 if (!$done_v6_hash->{$ifname} && defined($net->{address6
})) {
276 if ($need_separator) { $interfaces .= "\n"; $need_separator = 0; };
277 $section = { type
=> 'ipv6', ifname
=> $ifname, attr
=> []};
282 PVE
::Tools
::file_set_contents
($filename, $interfaces);