/[soft]/draklive-install/trunk/draklive-install
ViewVC logotype

Contents of /draklive-install/trunk/draklive-install

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4023 - (show annotations) (download)
Wed Apr 11 22:33:04 2012 UTC (6 years, 3 months ago) by blino
File size: 14583 byte(s)
fix breakage due to prepare_minimal_root() changes (from tmb)
1 #!/usr/bin/perl
2
3 # Must be done as early as possible to avoid issues when displaying translated
4 # strings
5 BEGIN {
6 push @::textdomains, 'draklive-install';
7 }
8
9 use lib qw(/usr/lib/libDrakX);
10 use standalone;
11 use interactive;
12 use fs;
13 use fs::any;
14 use fs::type;
15 use fs::partitioning;
16 use fs::partitioning_wizard;
17 use partition_table;
18 use MDK::Common;
19 use common;
20 use feature qw(state);
21
22 ($::real_windowwidth, $::real_windowheight) = (600, 400);
23
24 {
25 use diskdrake::interactive;
26 package diskdrake::interactive;
27 my $old = \&hd_possible_actions_base;
28 undef *hd_possible_actions_base;
29 *hd_possible_actions_base = sub {
30 #- for the partition wizard to show the auto-allocate option
31 local $::isInstall = 1;
32 &$old;
33 };
34 undef *Done;
35 #- skip the fstab/reboot checks
36 *Done = \&diskdrake_interactive_Done;
37 #- don't ask whether to Move/Hide old files
38 undef *need_migration;
39 *need_migration = sub { 'hide' };
40 }
41
42 install_live();
43
44 sub install_live() {
45 my $in = 'interactive'->vnew('su');
46 $in->{pop_wait_messages} = 0;
47
48 $::isWizard = 1;
49 $::Wizard_no_previous = 1;
50 $::Wizard_pix_up = "draklive-install";
51 any::set_wm_hints_if_needed($in);
52
53 my $all_hds = {};
54 my $fstab = [];
55 $::prefix = '/mnt/install';
56
57 my $system_file = '/etc/sysconfig/draklive-install';
58 my %settings = getVarsFromSh($system_file);
59
60 my $copy_source = $settings{SOURCE} || '/';
61 my $live_media = '/live/media';
62
63 display_start_message();
64 init_hds($in, $all_hds, $fstab, $live_media);
65 ask_partitions_loop($in, $all_hds, $fstab, $copy_source);
66 remove_unused_packages($in, $copy_source);
67 prepare_root($in, $all_hds);
68 copy_root($in, $copy_source);
69 complete_install($in, $all_hds);
70 setup_bootloader($in, $all_hds, $fstab);
71 finish_installation($fstab);
72 display_end_message($in);
73 $in->exit(0);
74 }
75
76 sub umount_all {
77 my ($fstab) = @_;
78 #- make sure nothing is mounted in the new root
79 foreach (sort { $b cmp $a } grep { /^$::prefix/ } map { (split)[1] } cat_('/proc/mounts')) {
80 system('umount', $_);
81 }
82 #- make sure selected devices aren't mounted, and swap isn't used
83 foreach (grep { isSwap($_) } @$fstab) {
84 eval { fs::mount::swapoff($_->{device}) };
85 }
86 foreach (map { $_->{mntpoint} && !isSwap($_) ? "/dev/$_->{device}" : () } @$fstab) {
87 system('umount', $_);
88 }
89 }
90
91 sub on_reboot_needed {
92 my ($in) = @_;
93 fs::partitioning_wizard::warn_reboot_needed($in);
94 $in->exit(0);
95 }
96
97 sub display_start_message() {
98 require any;
99 my $has_running_wm = to_bool(any::running_window_manager());
100 local $::isStandalone = $has_running_wm; # center me if run in xsetup.d script
101 my $w = ugtk2->new(N("Mageia Live"));
102 ugtk2::gtkadd($w->{window},
103 ugtk2::gtkcreate_img("MageiaLive-install"),
104 ugtk2::gtknew('Label', height => 5),
105 N("This wizard will help you to install the live distribution."),
106 ugtk2::create_okcancel($w));
107 $w->{ok}->grab_focus;
108 $w->main;
109 }
110
111 sub umount_first_pass() {
112 local $::prefix = undef;
113 my $all_hds = fsedit::get_hds();
114 fs::get_raw_hds('', $all_hds);
115 fs::get_info_from_fstab($all_hds);
116 my $fstab = [ fs::get::fstab($all_hds) ];
117 fs::merge_info_from_mtab($fstab);
118
119 #- inlined from fs::mount::umount_all to go on when one umount fail
120 #- (maybe the sort function could be shared)
121 log::l("unmounting all filesystems");
122 foreach (sort { $b->{mntpoint} cmp $a->{mntpoint} }
123 grep { $_->{mntpoint} && !$_->{real_mntpoint} } @$fstab) {
124 eval { fs::mount::umount_part($_) };
125 log::l("error unmounting $_->{mntpoint}: $@") if $@;
126 }
127 }
128
129 sub init_hds {
130 my ($in, $all_hds, $fstab, $live_media) = @_;
131 my $wait = $in->wait_message('', N("Please wait"));
132 umount_first_pass();
133 eval { fs::any::get_hds($all_hds, $fstab, [], {}, 'skip_mtab', $in) };
134
135 #- fs::any::get_hds does not return mounts that are not in fstab
136 my @mounted = fs::read_fstab('', '/proc/mounts');
137 my $live_part = find { $_->{mntpoint} eq $live_media } @mounted;
138 my $live_device = $live_part && $live_part->{device};
139 #- remove live device from the detected hds, so that bootloader is not installed on it:
140 #- bootloader installation uses first device from detect_devices::get, which tries to list devices
141 #- by booting order, and our live system is likely to be here in first position
142 #- it can be either a partition (USB) or the full disk (Hybrid on USB)
143 @{$all_hds->{hds}} = grep {
144 $_->{device} ne $live_device &&
145 !member($live_device, map { $_->{device} } partition_table::get_normal_parts_and_holes($_));
146 } @{$all_hds->{hds}} if $live_device;
147
148 my $err = $@;
149 umount_all($fstab);
150 if ($err) {
151 undef $wait;
152 $in->ask_warn(N("Error"), [ formatError($err) ]);
153 $in->exit(1);
154 }
155 }
156
157 sub ask_partitions_loop {
158 my ($in, $all_hds, $fstab, $copy_source) = @_;
159
160 while (1) {
161 eval { ask_partitions($in, $all_hds, $fstab, $copy_source) };
162 my $err = $@ or last;
163 $in->exit(1) if $err =~ /wizcancel/ ||
164 !$in->ask_warn(N("Error"), [ N("An error occurred"), formatError($err) ]);
165 }
166 }
167
168 sub ask_partitions {
169 my ($in, $all_hds, $fstab, $copy_source) = @_;
170 fs::partitioning_wizard::main($in, $all_hds, $fstab, [], undef, {}, 'skip_mtab');
171
172 mkdir_p($::prefix) or die "unable to create $::prefix";
173
174 fs::any::write_hds($all_hds, $fstab, undef, sub { on_reboot_needed($in) }, {});
175 fs::any::check_hds_boot_and_root($all_hds, $fstab);
176 fs::partitioning::choose_partitions_to_format($in, $fstab);
177
178 my $total = get_total_size($in, $copy_source);
179 my $available = fs::any::getAvailableSpace($fstab, 'skip_mounted');
180 die N("Not enough space available (%s available while %s are needed)",
181 formatXiB($available), formatXiB($total)) . "\n"
182 if $total > $available;
183
184 umount_all($fstab);
185 fs::partitioning::format_mount_partitions($in, $all_hds, $fstab);
186 }
187
188 sub remove_unused_packages {
189 my ($in, $o_prefix) = @_;
190 require pkgs;
191 #in remove_unused_packages, we want to get the locale from the currently
192 #running system, but we want to remove unused packages from the
193 #system based in $o_prefix, that's why we use an extra arg instead of
194 #directly using $::prefix
195 local $::prefix;
196 pkgs::remove_unused_packages($in, $in->do_pkgs, $o_prefix);
197 }
198
199 sub prepare_root {
200 my ($in, $all_hds) = @_;
201 #- create required directories and devices (early to have a consistent root before calling other programs)
202 my $_wait = $in->wait_message('', N("Please wait"));
203 fs::any::prepare_minimal_root();
204 }
205
206 sub build_copy_command {
207 my ($source, $dest) = @_;
208 join(' ',
209 'tar', 'c', '--one-file-system', '-C', $source, '.',
210 '|',
211 'tar', 'xvv', '-C', $dest,
212 );
213 }
214
215 sub get_total_size {
216 my ($in, $source) = @_;
217 state %total;
218 return $total{$source} if $total{$source};
219 my $_wait = $in->wait_message('', N("Computing total size"));
220 $total{$source} = first(split(/\s+/, `du -sbx $source 2>/dev/null`));
221 }
222
223 sub sync_logs() {
224 cp_af('/var/log', $::prefix . '/var');
225 }
226
227 sub copy_root {
228 my ($in, $copy_source) = @_;
229 my $total = get_total_size($in, $copy_source);
230
231 my ($wait, $update_progress) = copying_message_with_progress_bar($in, N("Copying in progress"));
232 open(my $OUTPUT, '-|', build_copy_command($copy_source, $::prefix));
233 {
234 local $_;
235 my $current = my $previous = 0;
236 while (<$OUTPUT>) {
237 (undef, undef, my $size) = split;
238 $current += $size;
239 if ($current <= $total && $current/$total > $previous/$total + 0.001) {
240 $update_progress->('', $current, $total);
241 $previous = $current;
242 }
243 }
244 }
245 if (!close($OUTPUT)) {
246 undef $wait;
247 undef $update_progress;
248 $in->ask_warn(N("Error"), N("Unable to copy files to new root"));
249 $in->exit(1);
250 }
251 sync_logs();
252 }
253
254 sub clean_harddrake_hds {
255 my ($prefix) = @_;
256 #- remove harddisks from harddrake's config file, so that hardddisks
257 #- are automatically rediscovered at first boot
258 require Storable;
259 my $harddrake_file = $prefix . "/etc/sysconfig/harddrake2/previous_hw";
260 my $harddrake_conf = eval { Storable::retrieve($harddrake_file) };
261 if ($harddrake_conf) {
262 delete $harddrake_conf->{HARDDISK};
263 Storable::store($harddrake_conf, $harddrake_file);
264 }
265 }
266
267
268 sub complete_install {
269 my ($in, $all_hds) = @_;
270 my $_wait = $in->wait_message('', N("Please wait"));
271
272 my $real_rpm_dir = "/tmp/rpm/real";
273 cp_f(glob($real_rpm_dir . "/*"), $::prefix . "/var/lib/rpm") if -d $real_rpm_dir;
274
275 #- FIXME: maybe factorize with draklive, using draklive --clean-chroot ?
276 #- remove unwanted files and packages
277 my $live_user = chomp_(cat_('/etc/draklive-install.d/user'));
278 my $live_user_desktop = $live_user && chomp_(run_program::rooted_get_stdout($::prefix, "su - $live_user -c 'xdg-user-dir DESKTOP'"));
279 unlink(map { $::prefix . $_ } '/.autofsck',
280 chomp_(cat_(glob('/etc/draklive-install.d/remove.d/*'))),
281 if_($live_user_desktop,
282 $live_user_desktop . '/draklive-copy-wizard.desktop',
283 $live_user_desktop . '/draklive-install.desktop'),
284 );
285 {
286 #- do not allow update-menus to create home directory with invalid perms
287 local $ENV{HOME} = '/root';
288 system('chroot', $::prefix, 'rpm', '-e', 'draklive-install');
289 }
290
291 foreach (glob('/etc/draklive-install.d/run.d/*')) {
292 run_program::rooted($::prefix, $_);
293 }
294
295 #- copy sysconfig files for first boot
296 cp_f(glob('/etc/draklive-install.d/sysconfig/*'), $::prefix . '/etc/sysconfig');
297
298 #- unselect live user in kdm
299 my $kdm_cfg = common::read_alternative('kdm4-config');
300 update_gnomekderc($::prefix . $kdm_cfg,
301 'X-:0-Greeter' => (PreselectUser => 'None', DefaultUser => '')) if -f $kdm_cfg;
302 my $autologin = any::get_autologin();
303 delete $autologin->{user};
304 any::set_autologin($in->do_pkgs, $autologin);
305
306 #- allow to install doc in disk install
307 substInFile { undef $_ if /^\%_excludedocs/ } $::prefix . '/etc/rpm/macros';
308
309 fs::write_fstab($all_hds, $::prefix);
310
311 clean_harddrake_hds($::prefix);
312
313 # enable back some disabled services
314 require services;
315 services::start_service_on_boot($_) foreach chomp_(cat_('/etc/draklive-install.d/services'));
316
317 sync_logs();
318 }
319
320 sub setup_bootloader {
321 my ($in, $all_hds, $fstab) = @_;
322 use bootloader;
323 my $bootloader = {};
324 any::setupBootloaderBeforeStandalone($in->do_pkgs, $bootloader, $all_hds, $fstab);
325 local $::Wizard_no_previous = 0;
326 any::setupBootloaderUntilInstalled($in, $bootloader, $all_hds, $fstab, $ENV{SECURE_LEVEL});
327 sync_logs();
328 }
329
330 sub clean_live_system_hds() {
331 #- clean fstab and harddrake config in the live system
332 #- since partitions UUIDs of the installed system have been modified
333 #- (useful for persistent live systems)
334 local $::prefix = undef;
335 clean_harddrake_hds($::prefix);
336 my $all_hds = fs::get::empty_all_hds(); #- skip real harddisks
337 fs::get_raw_hds('', $all_hds);
338 fs::get_info_from_fstab($all_hds);
339 fs::write_fstab($all_hds, $::prefix);
340 }
341
342 sub finish_installation {
343 my ($fstab) = @_;
344 sync_logs();
345 #- cleanly umount here, it will avoid fs journals to be corrupted after a hackish reboot
346 umount_all($fstab);
347 clean_live_system_hds();
348 }
349
350 sub display_end_message {
351 my ($in) = @_;
352 $::Wizard_finished = 1;
353 $in->ask_okcancel(N("Congratulations"), N("Please halt your computer, remove your live system, and restart your computer."));
354 }
355
356 ###
357 ### duplicate code
358 ###
359
360 #- from disdrake::interactive
361 {
362 package diskdrake::interactive;
363 sub diskdrake_interactive_Done {
364 my ($in, $all_hds) = @_;
365 eval { raid::verify($all_hds->{raids}) };
366 if (my $err = $@) {
367 $::expert or die;
368 $in->ask_okcancel('', [ formatError($err), N("Continue anyway?") ]) or return;
369 }
370 foreach (@{$all_hds->{hds}}) {
371 if (!write_partitions($in, $_, 'skip_check_rebootNeeded')) {
372 return if !$::isStandalone;
373 $in->ask_yesorno(N("Quit without saving"), N("Quit without writing the partition table?"), 1) or return;
374 }
375 }
376 #- skip that fstab/reboot steps
377 if (!$::isInstall && 0) {
378 my $new = fs::fstab_to_string($all_hds);
379 if ($new ne $all_hds->{current_fstab} && $in->ask_yesorno('', N("Do you want to save /etc/fstab modifications"), 1)) {
380 $all_hds->{current_fstab} = $new;
381 fs::write_fstab($all_hds);
382 }
383 update_bootloader_for_renumbered_partitions($in, $all_hds);
384
385 if (any { $_->{rebootNeeded} } @{$all_hds->{hds}}) {
386 $in->ask_warn('', N("You need to reboot for the partition table modifications to take place"));
387 tell_wm_and_reboot();
388 }
389 }
390 if (my $part = find { $_->{mntpoint} && !maybeFormatted($_) } fs::get::fstab($all_hds)) {
391 $in->ask_okcancel('', N("You should format partition %s.
392 Otherwise no entry for mount point %s will be written in fstab.
393 Quit anyway?", $part->{device}, $part->{mntpoint})) or return if $::isStandalone && 0; #- no, please
394 }
395 1;
396 }
397 }
398
399 # forked from interactive::wait_message
400 sub copying_message {
401 my ($o, $title, $message, $b_temp) = @_;
402
403 my $w = $o->wait_messageW($title, N("Copying in progress"), ugtk2::gtknew('VBox', padding => 5, children_tight => [
404 ugtk2::gtkcreate_img("MageiaLive-advert"),
405 $message,
406 ]));
407 push @tempory::objects, $w if $b_temp;
408 my $b = before_leaving { $o->wait_message_endW($w) };
409
410 #- enable access through set
411 MDK::Common::Func::add_f4before_leaving(sub { $o->wait_message_nextW($_[1], $w) }, $b, 'set');
412 $b;
413 }
414
415 # forked from interactive::gtk::wait_message_with_progress_bar
416 sub copying_message_with_progress_bar {
417 my ($in, $o_title) = @_;
418
419 my $progress = Gtk2::ProgressBar->new;
420 my $w = copying_message($in, $o_title, $progress);
421 my $displayed;
422 $progress->signal_connect(expose_event => sub { $displayed = 1; 0 });
423 $w, sub {
424 my ($msg, $current, $total) = @_;
425 if ($msg) {
426 $w->set($msg);
427 }
428
429 if ($total) {
430 $progress or internal_error('You must first give some text to display');
431 $progress->set_fraction($current / $total);
432 $progress->show;
433 $displayed = 0;
434 mygtk2::flush() while !$displayed;
435 } else {
436 $progress->hide if !$total;
437 }
438 };
439 }

Properties

Name Value
svn:executable *

  ViewVC Help
Powered by ViewVC 1.1.26