]>
Commit | Line | Data |
---|---|---|
7af97ad5 | 1 | package PVE::LXC::Setup::Redhat; |
c0eae401 DM |
2 | |
3 | use strict; | |
4 | use warnings; | |
5 | use Data::Dumper; | |
6 | use PVE::Tools; | |
685d7b1c | 7 | use PVE::Network; |
c0eae401 | 8 | use PVE::LXC; |
c0eae401 | 9 | |
7af97ad5 | 10 | use PVE::LXC::Setup::Base; |
c0eae401 | 11 | |
7af97ad5 | 12 | use base qw(PVE::LXC::Setup::Base); |
c0eae401 DM |
13 | |
14 | sub 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 | 37 | my $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 | ||
45 | stop on runlevel [S016] | |
46 | ||
47 | respawn | |
48 | instance \$TTY | |
b9bc7cfa | 49 | exec /sbin/mingetty \$TTY |
c0eae401 DM |
50 | usage 'tty TTY=/dev/ttyX - where X is console id' |
51 | __EOD__ | |
142444d5 DM |
52 | |
53 | my $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 | ||
60 | start on stopped rc RUNLEVEL=[2345] | |
61 | ||
62 | env ACTIVE_CONSOLES=/dev/tty[1-6] | |
63 | env X_TTY=/dev/tty1 | |
64 | task | |
65 | script | |
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 | |
71 | end script | |
72 | __EOD__ | |
73 | ||
57569b85 DM |
74 | my $power_status_changed_conf = <<__EOD__; |
75 | # power-status-changed - shutdown on SIGPWR | |
76 | # | |
77 | start on power-status-changed | |
78 | ||
79 | exec /sbin/shutdown -h now "SIGPWR received" | |
80 | __EOD__ | |
81 | ||
142444d5 DM |
82 | sub 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 |
113 | sub 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 | ||
121 | sub 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 | ||
169 | sub 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 | ||
274 | 1; |