]> git.proxmox.com Git - pve-container.git/blame - src/PVE/LXC/Setup/Redhat.pm
added Setup::Fedora
[pve-container.git] / src / PVE / LXC / Setup / Redhat.pm
CommitLineData
7af97ad5 1package PVE::LXC::Setup::Redhat;
c0eae401
DM
2
3use strict;
4use warnings;
5use Data::Dumper;
6use PVE::Tools;
685d7b1c 7use PVE::Network;
c0eae401 8use PVE::LXC;
c0eae401 9
7af97ad5 10use PVE::LXC::Setup::Base;
c0eae401 11
7af97ad5 12use base qw(PVE::LXC::Setup::Base);
c0eae401
DM
13
14sub new {
15 my ($class, $conf, $rootdir) = @_;
16
17 my $release = PVE::Tools::file_read_firstline("$rootdir/etc/redhat-release");
18 die "unable to read version info\n" if !defined($release);
19
20 my $version;
21
fa099c21 22 if ($release =~ m/release\s+(\d+\.\d+)(\.\d+)?/) {
9143dec4 23 if ($1 >= 6 && $1 < 8) {
c0eae401
DM
24 $version = $1;
25 }
26 }
27
28 die "unsupported redhat release '$release'\n" if !$version;
29
30 my $self = { conf => $conf, rootdir => $rootdir, version => $version };
31
27916659 32 $conf->{ostype} = "centos";
c0eae401
DM
33
34 return bless $self, $class;
35}
36
142444d5 37my $tty_conf = <<__EOD__;
c0eae401
DM
38# tty - getty
39#
40# This service maintains a getty on the specified device.
41#
42# Do not edit this file directly. If you want to change the behaviour,
43# please create a file tty.override and put your changes there.
44
45stop on runlevel [S016]
46
47respawn
48instance \$TTY
b9bc7cfa 49exec /sbin/mingetty \$TTY
c0eae401
DM
50usage 'tty TTY=/dev/ttyX - where X is console id'
51__EOD__
142444d5
DM
52
53my $start_ttys_conf = <<__EOD__;
c0eae401
DM
54#
55# This service starts the configured number of gettys.
56#
57# Do not edit this file directly. If you want to change the behaviour,
58# please create a file start-ttys.override and put your changes there.
59
60start on stopped rc RUNLEVEL=[2345]
61
62env ACTIVE_CONSOLES=/dev/tty[1-6]
63env X_TTY=/dev/tty1
64task
65script
66 . /etc/sysconfig/init
67 for tty in \$(echo \$ACTIVE_CONSOLES) ; do
68 [ "\$RUNLEVEL" = "5" -a "\$tty" = "\$X_TTY" ] && continue
69 initctl start tty TTY=\$tty
70 done
71end script
72__EOD__
73
57569b85
DM
74my $power_status_changed_conf = <<__EOD__;
75# power-status-changed - shutdown on SIGPWR
76#
77start on power-status-changed
78
79exec /sbin/shutdown -h now "SIGPWR received"
80__EOD__
81
142444d5
DM
82sub template_fixup {
83 my ($self, $conf) = @_;
84
142444d5
DM
85 if ($self->{version} < 7) {
86 # re-create emissing files for tty
87
f08b2779 88 $self->ct_make_path('/etc/init');
142444d5 89
2063d380
WB
90 my $filename = "/etc/init/tty.conf";
91 $self->ct_file_set_contents($filename, $tty_conf)
92 if ! $self->ct_file_exists($filename);
142444d5 93
2063d380
WB
94 $filename = "/etc/init/start-ttys.conf";
95 $self->ct_file_set_contents($filename, $start_ttys_conf)
96 if ! $self->ct_file_exists($filename);
57569b85 97
2063d380
WB
98 $filename = "/etc/init/power-status-changed.conf";
99 $self->ct_file_set_contents($filename, $power_status_changed_conf)
100 if ! $self->ct_file_exists($filename);
142444d5
DM
101
102 # do not start udevd
2063d380
WB
103 $filename = "/etc/rc.d/rc.sysinit";
104 my $data = $self->ct_file_get_contents($filename);
142444d5 105 $data =~ s!^(/sbin/start_udev.*)$!#$1!gm;
2063d380 106 $self->ct_file_set_contents($filename, $data);
142444d5
DM
107
108 # edit /etc/securetty (enable login on console)
b7cd927f 109 $self->setup_securetty($conf, qw(lxc/console lxc/tty1 lxc/tty2 lxc/tty3 lxc/tty4));
142444d5
DM
110 }
111}
112
142444d5
DM
113sub setup_init {
114 my ($self, $conf) = @_;
115
142444d5
DM
116 # edit/etc/securetty
117
9143dec4 118 $self->setup_systemd_console($conf);
c0eae401
DM
119}
120
121sub set_hostname {
122 my ($self, $conf) = @_;
123
ead433af 124 # Redhat wants the fqdn in /etc/sysconfig/network's HOSTNAME
27916659 125 my $hostname = $conf->{hostname} || 'localhost';
c0eae401 126
2063d380
WB
127 my $hostname_fn = "/etc/hostname";
128 my $sysconfig_network = "/etc/sysconfig/network";
c0eae401
DM
129
130 my $oldname;
2063d380
WB
131 if ($self->ct_file_exists($hostname_fn)) {
132 $oldname = $self->ct_file_read_firstline($hostname_fn) || 'localhost';
c0eae401 133 } else {
2063d380 134 my $data = $self->ct_file_get_contents($sysconfig_network);
c0eae401
DM
135 if ($data =~ m/^HOSTNAME=\s*(\S+)\s*$/m) {
136 $oldname = $1;
137 }
138 }
139
2063d380 140 my $hosts_fn = "/etc/hosts";
c0eae401 141 my $etc_hosts_data = '';
2063d380
WB
142 if ($self->ct_file_exists($hosts_fn)) {
143 $etc_hosts_data = $self->ct_file_get_contents($hosts_fn);
c0eae401
DM
144 }
145
146 my ($ipv4, $ipv6) = PVE::LXC::get_primary_ips($conf);
147 my $hostip = $ipv4 || $ipv6;
148
23d928a1 149 my ($searchdomains) = $self->lookup_dns_conf($conf);
c0eae401 150
7af97ad5 151 $etc_hosts_data = PVE::LXC::Setup::Base::update_etc_hosts($etc_hosts_data, $hostip, $oldname,
c0eae401
DM
152 $hostname, $searchdomains);
153
2063d380
WB
154 if ($self->ct_file_exists($hostname_fn)) {
155 $self->ct_file_set_contents($hostname_fn, "$hostname\n");
f0f32274
WB
156 }
157
158 if ($self->ct_file_exists($sysconfig_network)) {
2063d380 159 my $data = $self->ct_file_get_contents($sysconfig_network);
f0f32274 160 if ($data !~ s/^HOSTNAME=\h*(\S+)\h*$/HOSTNAME=$hostname/m) {
c0eae401
DM
161 $data .= "HOSTNAME=$hostname\n";
162 }
2063d380 163 $self->ct_file_set_contents($sysconfig_network, $data);
c0eae401
DM
164 }
165
2063d380 166 $self->ct_file_set_contents($hosts_fn, $etc_hosts_data);
c0eae401
DM
167}
168
169sub setup_network {
170 my ($self, $conf) = @_;
171
c0eae401
DM
172 my ($gw, $gw6);
173
f08b2779 174 $self->ct_make_path('/etc/sysconfig/network-scripts');
c0eae401 175
f0f32274
WB
176 my ($has_ipv4, $has_ipv6);
177
c0eae401
DM
178 foreach my $k (keys %$conf) {
179 next if $k !~ m/^net(\d+)$/;
27916659 180 my $d = PVE::LXC::parse_lxc_network($conf->{$k});
fa13a37a 181 next if !$d->{name};
f0f32274
WB
182 $has_ipv4 = 1 if defined($d->{ip});
183 $has_ipv6 = 1 if defined($d->{ip6});
fa13a37a 184
2063d380 185 my $filename = "/etc/sysconfig/network-scripts/ifcfg-$d->{name}";
685d7b1c
WB
186 my $routefile = "/etc/sysconfig/network-scripts/route-$d->{name}";
187 my $routes = '';
d5a932a5
WB
188
189 my $header = "DEVICE=$d->{name}\nONBOOT=yes\n";
190 my $data = '';
191 my $bootproto = '';
fa13a37a
WB
192
193 if ($d->{ip} && $d->{ip} ne 'manual') {
fa13a37a 194 if ($d->{ip} eq 'dhcp') {
d5a932a5 195 $bootproto = 'dhcp';
fa13a37a 196 } else {
d5a932a5 197 $bootproto = 'none';
c0eae401
DM
198 my $ipinfo = PVE::LXC::parse_ipv4_cidr($d->{ip});
199 $data .= "IPADDR=$ipinfo->{address}\n";
200 $data .= "NETMASK=$ipinfo->{netmask}\n";
201 if (defined($d->{gw})) {
202 $data .= "GATEWAY=$d->{gw}\n";
9da070e2
WB
203 if (!PVE::Network::is_ip_in_cidr($d->{gw}, $d->{ip}, 4)) {
204 $routes .= "$d->{gw} dev $d->{name}\n";
205 $routes .= "default via $d->{gw}\n";
206 }
c0eae401
DM
207 }
208 }
fa13a37a
WB
209 }
210
211 if ($d->{ip6} && $d->{ip6} ne 'manual') {
d5a932a5 212 $bootproto = 'none' if !$bootproto;
fa13a37a 213 $data .= "IPV6INIT=yes\n";
c6b8740b
WB
214 if ($d->{ip6} eq 'auto') {
215 $data .= "IPV6_AUTOCONF=yes\n";
216 } else {
217 $data .= "IPV6_AUTOCONF=no\n";
218 }
fa13a37a
WB
219 if ($d->{ip6} eq 'dhcp') {
220 $data .= "DHCPV6C=yes\n";
221 } else {
da78375e 222 $data .= "IPV6ADDR=$d->{ip6}\n";
fa13a37a
WB
223 if (defined($d->{gw6})) {
224 $data .= "IPV6_DEFAULTGW=$d->{gw6}\n";
9da070e2
WB
225 if (!PVE::Network::is_ip_in_cidr($d->{gw6}, $d->{ip6}, 6)) {
226 $routes .= "$d->{gw6} dev $d->{name}\n";
227 $routes .= "default via $d->{gw6}\n";
228 }
fa13a37a 229 }
c0eae401 230 }
685d7b1c
WB
231 }
232
1db21128 233 next unless $data || $bootproto;
d5a932a5
WB
234 $header .= "BOOTPROTO=$bootproto\n";
235 $self->ct_file_set_contents($filename, $header . $data);
236
685d7b1c
WB
237 # To keep user-defined routes in route-$iface we mark ours:
238 my $head = "# --- BEGIN PVE ROUTES ---\n";
239 my $tail = "# --- END PVE ROUTES ---\n";
240 $routes = $head . $routes . $tail if $routes;
241 if ($self->ct_file_exists($routefile)) {
242 # if it exists we update by first removing our old rules
243 my $old = $self->ct_file_get_contents($routefile);
244 $old =~ s/(?:^|(?<=\n))\Q$head\E.*\Q$tail\E//gs;
245 chomp $old;
246 if ($old) {
247 $self->ct_file_set_contents($routefile, $routes . $old . "\n");
248 } else {
249 # or delete if we aren't adding routes and the file's now empty
250 $self->ct_unlink($routefile);
251 }
252 } elsif ($routes) {
253 $self->ct_file_set_contents($routefile, $routes);
c0eae401
DM
254 }
255 }
f0f32274
WB
256
257 my $sysconfig_network = "/etc/sysconfig/network";
258 if ($self->ct_file_exists($sysconfig_network)) {
259 my $data = $self->ct_file_get_contents($sysconfig_network);
260 if ($has_ipv4) {
261 if ($data !~ s/(NETWORKING)=\S+/$1=yes/) {
262 $data .= "NETWORKING=yes\n";
263 }
264 }
265 if ($has_ipv6) {
266 if ($data !~ s/(NETWORKING_IPV6)=\S+/$1=yes/) {
267 $data .= "NETWORKING_IPV6=yes\n";
268 }
269 }
270 $self->ct_file_set_contents($sysconfig_network, $data);
271 }
c0eae401
DM
272}
273
2741;