]> git.proxmox.com Git - pve-container.git/blame - src/PVE/LXC/Setup/Redhat.pm
redhat: use the fully qualified hostname
[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
2063d380 88 $self->ct_mkpath('/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
7af97ad5 149 my ($searchdomains) = PVE::LXC::Setup::Base::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");
c0eae401 156 } else {
2063d380 157 my $data = $self->ct_file_get_contents($sysconfig_network);
fa13a37a 158 if ($data !~ s/^HOSTNAME=\s*(\S+)\s*$/HOSTNAME=$hostname/m) {
c0eae401
DM
159 $data .= "HOSTNAME=$hostname\n";
160 }
fa13a37a
WB
161 my ($has_ipv4, $has_ipv6);
162 foreach my $k (keys %$conf) {
163 next if $k !~ m/^net(\d+)$/;
27916659 164 my $d = PVE::LXC::parse_lxc_network($conf->{$k});
fa13a37a
WB
165 next if !$d->{name};
166 $has_ipv4 = 1 if defined($d->{ip});
167 $has_ipv6 = 1 if defined($d->{ip6});
168 }
169 if ($has_ipv4) {
170 if ($data !~ s/(NETWORKING)=\S+/$1=yes/) {
171 $data .= "NETWORKING=yes\n";
172 }
173 }
174 if ($has_ipv6) {
175 if ($data !~ s/(NETWORKING_IPV6)=\S+/$1=yes/) {
176 $data .= "NETWORKING_IPV6=yes\n";
177 }
178 }
2063d380 179 $self->ct_file_set_contents($sysconfig_network, $data);
c0eae401
DM
180 }
181
2063d380 182 $self->ct_file_set_contents($hosts_fn, $etc_hosts_data);
c0eae401
DM
183}
184
185sub setup_network {
186 my ($self, $conf) = @_;
187
c0eae401
DM
188 my ($gw, $gw6);
189
2063d380 190 $self->ct_mkpath('/etc/sysconfig/network-scripts');
c0eae401
DM
191
192 foreach my $k (keys %$conf) {
193 next if $k !~ m/^net(\d+)$/;
27916659 194 my $d = PVE::LXC::parse_lxc_network($conf->{$k});
fa13a37a
WB
195 next if !$d->{name};
196
2063d380 197 my $filename = "/etc/sysconfig/network-scripts/ifcfg-$d->{name}";
685d7b1c
WB
198 my $routefile = "/etc/sysconfig/network-scripts/route-$d->{name}";
199 my $routes = '';
fa13a37a
WB
200 my $had_v4 = 0;
201
202 if ($d->{ip} && $d->{ip} ne 'manual') {
c0eae401
DM
203 my $data = "DEVICE=$d->{name}\n";
204 $data .= "ONBOOT=yes\n";
fa13a37a
WB
205 if ($d->{ip} eq 'dhcp') {
206 $data .= "BOOTPROTO=dhcp\n";
207 } else {
208 $data .= "BOOTPROTO=none\n";
c0eae401
DM
209 my $ipinfo = PVE::LXC::parse_ipv4_cidr($d->{ip});
210 $data .= "IPADDR=$ipinfo->{address}\n";
211 $data .= "NETMASK=$ipinfo->{netmask}\n";
212 if (defined($d->{gw})) {
213 $data .= "GATEWAY=$d->{gw}\n";
214 }
215 }
2063d380 216 $self->ct_file_set_contents($filename, $data);
685d7b1c
WB
217 if (!PVE::Network::is_ip_in_cidr($d->{gw}, $d->{ip}, 4)) {
218 $routes .= "$d->{gw} dev $d->{name}\n";
219 $routes .= "default via $d->{gw}\n";
220 }
fa13a37a
WB
221 # If we also have an IPv6 configuration it'll end up in an alias
222 # interface becuase otherwise RH doesn't support mixing dhcpv4 with
223 # a static ipv6 address.
224 $filename .= ':0';
225 $had_v4 = 1;
226 }
227
228 if ($d->{ip6} && $d->{ip6} ne 'manual') {
229 # If we're only on ipv6 delete the :0 alias
2063d380 230 $self->ct_unlink("$filename:0") if !$had_v4;
fa13a37a
WB
231
232 my $data = "DEVICE=$d->{name}\n";
233 $data .= "ONBOOT=yes\n";
234 $data .= "BOOTPROTO=none\n";
235 $data .= "IPV6INIT=yes\n";
c6b8740b
WB
236 if ($d->{ip6} eq 'auto') {
237 $data .= "IPV6_AUTOCONF=yes\n";
238 } else {
239 $data .= "IPV6_AUTOCONF=no\n";
240 }
fa13a37a
WB
241 if ($d->{ip6} eq 'dhcp') {
242 $data .= "DHCPV6C=yes\n";
243 } else {
da78375e 244 $data .= "IPV6ADDR=$d->{ip6}\n";
fa13a37a
WB
245 if (defined($d->{gw6})) {
246 $data .= "IPV6_DEFAULTGW=$d->{gw6}\n";
247 }
c0eae401 248 }
2063d380 249 $self->ct_file_set_contents($filename, $data);
685d7b1c
WB
250 if (!PVE::Network::is_ip_in_cidr($d->{gw6}, $d->{ip6}, 6)) {
251 $routes .= "$d->{gw6} dev $d->{name}\n";
252 $routes .= "default via $d->{gw6}\n";
253 }
254 }
255
256 # To keep user-defined routes in route-$iface we mark ours:
257 my $head = "# --- BEGIN PVE ROUTES ---\n";
258 my $tail = "# --- END PVE ROUTES ---\n";
259 $routes = $head . $routes . $tail if $routes;
260 if ($self->ct_file_exists($routefile)) {
261 # if it exists we update by first removing our old rules
262 my $old = $self->ct_file_get_contents($routefile);
263 $old =~ s/(?:^|(?<=\n))\Q$head\E.*\Q$tail\E//gs;
264 chomp $old;
265 if ($old) {
266 $self->ct_file_set_contents($routefile, $routes . $old . "\n");
267 } else {
268 # or delete if we aren't adding routes and the file's now empty
269 $self->ct_unlink($routefile);
270 }
271 } elsif ($routes) {
272 $self->ct_file_set_contents($routefile, $routes);
c0eae401
DM
273 }
274 }
275}
276
2771;