]>
Commit | Line | Data |
---|---|---|
7af97ad5 | 1 | package PVE::LXC::Setup; |
1c7f4f65 DM |
2 | |
3 | use strict; | |
4 | use warnings; | |
f08b2779 | 5 | use POSIX; |
a8e58e9c | 6 | use PVE::Tools; |
1c7f4f65 | 7 | |
7af97ad5 DM |
8 | use PVE::LXC::Setup::Debian; |
9 | use PVE::LXC::Setup::Ubuntu; | |
10 | use PVE::LXC::Setup::Redhat; | |
11 | use PVE::LXC::Setup::ArchLinux; | |
1c7f4f65 DM |
12 | |
13 | my $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 | 20 | my $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 | 39 | sub 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 |
60 | sub 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 |
102 | sub 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 | 111 | sub 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 | ||
120 | sub 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 |
129 | sub 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 |
138 | sub 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 |
147 | sub 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 |
156 | sub 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 |
165 | sub 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 | ||
177 | sub 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 | ||
186 | 1; |