]>
Commit | Line | Data |
---|---|---|
81a6ec3f | 1 | package PVE::LXC::Setup::CentOS; |
c0eae401 DM |
2 | |
3 | use strict; | |
4 | use warnings; | |
179b842e | 5 | |
c0eae401 | 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 | ||
3e1146a0 | 22 | if (($release =~ m/release\s+(\d+\.\d+)(\.\d+)?/) || ($release =~ m/release\s+(\d+)/)) { |
6566b196 | 23 | if ($1 >= 5 && $1 <= 9) { |
c0eae401 DM |
24 | $version = $1; |
25 | } | |
26 | } | |
27 | ||
81a6ec3f | 28 | die "unsupported centos release '$release'\n" if !$version; |
c0eae401 DM |
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 | |
39834d66 | 49 | exec /sbin/mingetty --nohangup \$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 | 90 | my $filename = "/etc/init/tty.conf"; |
39834d66 SI |
91 | if ($self->ct_file_exists($filename)) { |
92 | my $data = $self->ct_file_get_contents($filename); | |
93 | $data =~ s|^(exec /sbin/mingetty)(?!.*--nohangup) (.*)$|$1 --nohangup $2|gm; | |
94 | $self->ct_file_set_contents($filename, $data); | |
95 | } else { | |
96 | $self->ct_file_set_contents($filename, $tty_conf); | |
97 | } | |
142444d5 | 98 | |
2063d380 WB |
99 | $filename = "/etc/init/start-ttys.conf"; |
100 | $self->ct_file_set_contents($filename, $start_ttys_conf) | |
101 | if ! $self->ct_file_exists($filename); | |
57569b85 | 102 | |
2063d380 WB |
103 | $filename = "/etc/init/power-status-changed.conf"; |
104 | $self->ct_file_set_contents($filename, $power_status_changed_conf) | |
105 | if ! $self->ct_file_exists($filename); | |
142444d5 DM |
106 | |
107 | # do not start udevd | |
2063d380 WB |
108 | $filename = "/etc/rc.d/rc.sysinit"; |
109 | my $data = $self->ct_file_get_contents($filename); | |
142444d5 | 110 | $data =~ s!^(/sbin/start_udev.*)$!#$1!gm; |
2063d380 | 111 | $self->ct_file_set_contents($filename, $data); |
142444d5 | 112 | } |
10d17617 | 113 | # always call so root can login, if /etc/securetty doesn't exists it's a no-op |
bcacfcb5 | 114 | $self->setup_securetty($conf); |
142444d5 DM |
115 | } |
116 | ||
142444d5 DM |
117 | sub setup_init { |
118 | my ($self, $conf) = @_; | |
119 | ||
142444d5 DM |
120 | # edit/etc/securetty |
121 | ||
dd7a436b TL |
122 | $self->fixup_old_getty(); |
123 | ||
a4f1fab1 | 124 | $self->setup_container_getty_service($conf); |
c0eae401 DM |
125 | } |
126 | ||
127 | sub set_hostname { | |
128 | my ($self, $conf) = @_; | |
129 | ||
ead433af | 130 | # Redhat wants the fqdn in /etc/sysconfig/network's HOSTNAME |
27916659 | 131 | my $hostname = $conf->{hostname} || 'localhost'; |
c0eae401 | 132 | |
2063d380 WB |
133 | my $hostname_fn = "/etc/hostname"; |
134 | my $sysconfig_network = "/etc/sysconfig/network"; | |
c0eae401 DM |
135 | |
136 | my $oldname; | |
2063d380 WB |
137 | if ($self->ct_file_exists($hostname_fn)) { |
138 | $oldname = $self->ct_file_read_firstline($hostname_fn) || 'localhost'; | |
c0eae401 | 139 | } else { |
2063d380 | 140 | my $data = $self->ct_file_get_contents($sysconfig_network); |
c0eae401 DM |
141 | if ($data =~ m/^HOSTNAME=\s*(\S+)\s*$/m) { |
142 | $oldname = $1; | |
143 | } | |
144 | } | |
145 | ||
c0eae401 DM |
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 | |
9096a91d | 151 | $self->update_etc_hosts($hostip, $oldname, $hostname, $searchdomains); |
c0eae401 | 152 | |
2063d380 WB |
153 | if ($self->ct_file_exists($hostname_fn)) { |
154 | $self->ct_file_set_contents($hostname_fn, "$hostname\n"); | |
f0f32274 WB |
155 | } |
156 | ||
157 | if ($self->ct_file_exists($sysconfig_network)) { | |
2063d380 | 158 | my $data = $self->ct_file_get_contents($sysconfig_network); |
f0f32274 | 159 | if ($data !~ s/^HOSTNAME=\h*(\S+)\h*$/HOSTNAME=$hostname/m) { |
c0eae401 DM |
160 | $data .= "HOSTNAME=$hostname\n"; |
161 | } | |
2063d380 | 162 | $self->ct_file_set_contents($sysconfig_network, $data); |
c0eae401 | 163 | } |
c0eae401 DM |
164 | } |
165 | ||
166 | sub setup_network { | |
167 | my ($self, $conf) = @_; | |
168 | ||
c0eae401 DM |
169 | my ($gw, $gw6); |
170 | ||
f08b2779 | 171 | $self->ct_make_path('/etc/sysconfig/network-scripts'); |
c0eae401 | 172 | |
f0f32274 WB |
173 | my ($has_ipv4, $has_ipv6); |
174 | ||
c0eae401 DM |
175 | foreach my $k (keys %$conf) { |
176 | next if $k !~ m/^net(\d+)$/; | |
1b4cf758 | 177 | my $d = PVE::LXC::Config->parse_lxc_network($conf->{$k}); |
fa13a37a | 178 | next if !$d->{name}; |
f0f32274 WB |
179 | $has_ipv4 = 1 if defined($d->{ip}); |
180 | $has_ipv6 = 1 if defined($d->{ip6}); | |
fa13a37a | 181 | |
2063d380 | 182 | my $filename = "/etc/sysconfig/network-scripts/ifcfg-$d->{name}"; |
685d7b1c | 183 | my $routefile = "/etc/sysconfig/network-scripts/route-$d->{name}"; |
85e4f0cd | 184 | my $route6file = "/etc/sysconfig/network-scripts/route6-$d->{name}"; |
685d7b1c | 185 | my $routes = ''; |
85e4f0cd | 186 | my $routes6 = ''; |
d5a932a5 WB |
187 | |
188 | my $header = "DEVICE=$d->{name}\nONBOOT=yes\n"; | |
189 | my $data = ''; | |
190 | my $bootproto = ''; | |
fa13a37a WB |
191 | |
192 | if ($d->{ip} && $d->{ip} ne 'manual') { | |
fa13a37a | 193 | if ($d->{ip} eq 'dhcp') { |
d5a932a5 | 194 | $bootproto = 'dhcp'; |
fa13a37a | 195 | } else { |
d5a932a5 | 196 | $bootproto = 'none'; |
c0eae401 DM |
197 | my $ipinfo = PVE::LXC::parse_ipv4_cidr($d->{ip}); |
198 | $data .= "IPADDR=$ipinfo->{address}\n"; | |
199 | $data .= "NETMASK=$ipinfo->{netmask}\n"; | |
200 | if (defined($d->{gw})) { | |
201 | $data .= "GATEWAY=$d->{gw}\n"; | |
9da070e2 WB |
202 | if (!PVE::Network::is_ip_in_cidr($d->{gw}, $d->{ip}, 4)) { |
203 | $routes .= "$d->{gw} dev $d->{name}\n"; | |
85e4f0cd | 204 | $routes .= "default via $d->{gw} dev $d->{name}\n"; |
9da070e2 | 205 | } |
c0eae401 DM |
206 | } |
207 | } | |
fa13a37a WB |
208 | } |
209 | ||
210 | if ($d->{ip6} && $d->{ip6} ne 'manual') { | |
d5a932a5 | 211 | $bootproto = 'none' if !$bootproto; |
fa13a37a | 212 | $data .= "IPV6INIT=yes\n"; |
c6b8740b WB |
213 | if ($d->{ip6} eq 'auto') { |
214 | $data .= "IPV6_AUTOCONF=yes\n"; | |
c6b8740b | 215 | } |
fa13a37a WB |
216 | if ($d->{ip6} eq 'dhcp') { |
217 | $data .= "DHCPV6C=yes\n"; | |
218 | } else { | |
da78375e | 219 | $data .= "IPV6ADDR=$d->{ip6}\n"; |
fa13a37a | 220 | if (defined($d->{gw6})) { |
d13fd23a WB |
221 | if (!PVE::Network::is_ip_in_cidr($d->{gw6}, $d->{ip6}, 6) && |
222 | !PVE::Network::is_ip_in_cidr($d->{gw6}, 'fe80::/10', 6)) { | |
85e4f0cd WB |
223 | $routes6 .= "$d->{gw6} dev $d->{name}\n"; |
224 | $routes6 .= "default via $d->{gw6} dev $d->{name}\n"; | |
225 | } else { | |
226 | $data .= "IPV6_DEFAULTGW=$d->{gw6}\n"; | |
9da070e2 | 227 | } |
fa13a37a | 228 | } |
c0eae401 | 229 | } |
685d7b1c WB |
230 | } |
231 | ||
1db21128 | 232 | next unless $data || $bootproto; |
d5a932a5 WB |
233 | $header .= "BOOTPROTO=$bootproto\n"; |
234 | $self->ct_file_set_contents($filename, $header . $data); | |
2edb50e5 | 235 | $self->ct_modify_file($routefile, $routes, delete => 1, prepend => 1); |
85e4f0cd | 236 | $self->ct_modify_file($route6file, $routes6, delete => 1, prepend => 1); |
c0eae401 | 237 | } |
f0f32274 WB |
238 | |
239 | my $sysconfig_network = "/etc/sysconfig/network"; | |
240 | if ($self->ct_file_exists($sysconfig_network)) { | |
241 | my $data = $self->ct_file_get_contents($sysconfig_network); | |
242 | if ($has_ipv4) { | |
243 | if ($data !~ s/(NETWORKING)=\S+/$1=yes/) { | |
244 | $data .= "NETWORKING=yes\n"; | |
245 | } | |
246 | } | |
247 | if ($has_ipv6) { | |
248 | if ($data !~ s/(NETWORKING_IPV6)=\S+/$1=yes/) { | |
249 | $data .= "NETWORKING_IPV6=yes\n"; | |
250 | } | |
251 | } | |
252 | $self->ct_file_set_contents($sysconfig_network, $data); | |
253 | } | |
c0eae401 DM |
254 | } |
255 | ||
256 | 1; |