]> git.proxmox.com Git - pve-container.git/blame - src/PVE/LXC/Setup.pm
Setup: fix bad /dev bindmount
[pve-container.git] / src / PVE / LXC / Setup.pm
CommitLineData
7af97ad5 1package PVE::LXC::Setup;
1c7f4f65
DM
2
3use strict;
4use warnings;
f08b2779 5use POSIX;
a8e58e9c 6use PVE::Tools;
1c7f4f65 7
7af97ad5
DM
8use PVE::LXC::Setup::Debian;
9use PVE::LXC::Setup::Ubuntu;
10use PVE::LXC::Setup::Redhat;
11use PVE::LXC::Setup::ArchLinux;
1c7f4f65
DM
12
13my $plugins = {
7af97ad5
DM
14 debian => 'PVE::LXC::Setup::Debian',
15 ubuntu => 'PVE::LXC::Setup::Ubuntu',
16 redhat => 'PVE::LXC::Setup::Redhat',
17 archlinux => 'PVE::LXC::Setup::ArchLinux',
1c7f4f65
DM
18};
19
bdd4194c 20my $autodetect_type = sub {
5b4657d0 21 my ($rootdir) = @_;
a8e58e9c
DM
22
23 my $lsb_fn = "$rootdir/etc/lsb-release";
24 if (-f $lsb_fn) {
25 my $data = PVE::Tools::file_get_contents($lsb_fn);
26 if ($data =~ m/^DISTRIB_ID=Ubuntu$/im) {
27 return 'ubuntu';
28 }
29 } elsif (-f "$rootdir/etc/debian_version") {
bdd4194c 30 return "debian";
c0eae401
DM
31 } elsif (-f "$rootdir/etc/redhat-release") {
32 return "redhat";
c1d32b55
WB
33 } elsif (-f "$rootdir/etc/arch-release") {
34 return "archlinux";
bdd4194c
DM
35 }
36 die "unable to detect OS disribution\n";
37};
38
1c7f4f65 39sub new {
5b4657d0 40 my ($class, $conf, $rootdir, $type) = @_;
1c7f4f65 41
5b4657d0
DM
42 die "no root directory\n" if !$rootdir || $rootdir eq '/';
43
5b3614f8 44 my $self = bless { conf => $conf, rootdir => $rootdir};
1c7f4f65 45
bdd4194c
DM
46 if (!defined($type)) {
47 # try to autodetect type
5b4657d0 48 $type = &$autodetect_type($rootdir);
bdd4194c
DM
49 }
50
633a7bd8 51 my $plugin_class = $plugins->{$type} ||
1c7f4f65
DM
52 "no such OS type '$type'\n";
53
5b4657d0 54 $self->{plugin} = $plugin_class->new($conf, $rootdir);
f08b2779 55 $self->{in_chroot} = 0;
633a7bd8 56
1c7f4f65
DM
57 return $self;
58}
59
f08b2779
WB
60sub protected_call {
61 my ($self, $sub) = @_;
62
63 # avoid recursion:
64 return $sub->() if $self->{in_chroot};
65
66 my $rootdir = $self->{rootdir};
67 if (!-d "$rootdir/dev" && !mkdir("$rootdir/dev")) {
68 die "failed to create temporary /dev directory: $!\n";
69 }
70
71 my $child = fork();
72 die "fork failed: $!\n" if !defined($child);
73
8ba6ef14
WB
74 # can't bind to /proc/$pid/root/dev, it'll bind to the host's /dev
75 my $mountdev = ($rootdir !~ m@^/proc@);
76
f08b2779
WB
77 if (!$child) {
78 # avoid recursive forks
79 $self->{in_chroot} = 1;
80 $self->{plugin}->{in_chroot} = 1;
81 eval {
8ba6ef14 82 PVE::Tools::run_command(['mount', '--bind', '/dev', "$rootdir/dev"]) if $mountdev;
f08b2779
WB
83 chroot($rootdir) or die "failed to change root to: $rootdir: $!\n";
84 chdir('/') or die "failed to change to root directory\n";
85 $sub->();
86 };
87 if (my $err = $@) {
88 print STDERR "$err\n";
89 POSIX::_exit(1);
90 }
91 POSIX::_exit(0);
92 }
93 while (waitpid($child, 0) != $child) {}
8ba6ef14
WB
94 my $status = $? == 0;
95 if ($mountdev) {
96 eval { PVE::Tools::run_command(['umount', "$rootdir/dev"]); };
97 warn $@ if $@;
98 }
99 return $status;
f08b2779
WB
100}
101
142444d5
DM
102sub template_fixup {
103 my ($self) = @_;
104
f08b2779
WB
105 my $code = sub {
106 $self->{plugin}->template_fixup($self->{conf});
107 };
108 $self->protected_call($code);
142444d5
DM
109}
110
1c7f4f65 111sub setup_network {
55fa4e09 112 my ($self) = @_;
1c7f4f65 113
f08b2779
WB
114 my $code = sub {
115 $self->{plugin}->setup_network($self->{conf});
116 };
117 $self->protected_call($code);
1c7f4f65
DM
118}
119
120sub set_hostname {
121 my ($self) = @_;
122
f08b2779
WB
123 my $code = sub {
124 $self->{plugin}->set_hostname($self->{conf});
125 };
126 $self->protected_call($code);
1c7f4f65
DM
127}
128
c325b32f
DM
129sub set_dns {
130 my ($self) = @_;
131
f08b2779
WB
132 my $code = sub {
133 $self->{plugin}->set_dns($self->{conf});
134 };
135 $self->protected_call($code);
c325b32f
DM
136}
137
d66768a2
DM
138sub setup_init {
139 my ($self) = @_;
140
f08b2779
WB
141 my $code = sub {
142 $self->{plugin}->setup_init($self->{conf});
143 };
144 $self->protected_call($code);
d66768a2
DM
145}
146
168d6b07
DM
147sub set_user_password {
148 my ($self, $user, $pw) = @_;
149
f08b2779
WB
150 my $code = sub {
151 $self->{plugin}->set_user_password($self->{conf}, $user, $pw);
152 };
153 $self->protected_call($code);
1c7f4f65
DM
154}
155
7ee31468
DM
156sub rewrite_ssh_host_keys {
157 my ($self) = @_;
158
f08b2779
WB
159 my $code = sub {
160 $self->{plugin}->rewrite_ssh_host_keys($self->{conf});
161 };
162 $self->protected_call($code);
7ee31468
DM
163}
164
d66768a2
DM
165sub pre_start_hook {
166 my ($self) = @_;
167
f08b2779
WB
168 my $code = sub {
169 # Create /fastboot to skip run fsck
170 $self->{plugin}->ct_file_set_contents('/fastboot', '');
2988dbbc 171
f08b2779
WB
172 $self->{plugin}->pre_start_hook($self->{conf});
173 };
174 $self->protected_call($code);
d66768a2
DM
175}
176
177sub post_create_hook {
168d6b07 178 my ($self, $root_password) = @_;
1c7f4f65 179
f08b2779
WB
180 my $code = sub {
181 $self->{plugin}->post_create_hook($self->{conf}, $root_password);
182 };
183 $self->protected_call($code);
1c7f4f65
DM
184}
185
1861;