package install::steps; use diagnostics; use strict; use vars qw(@filesToSaveForUpgrade @filesNewerToUseAfterUpgrade); #-###################################################################################### #- misc imports #-###################################################################################### use common; use install::any 'addToBeDone'; use partition_table; use detect_devices; use fs::any; use fs::type; use fs::partitioning; use modules; use run_program; use lang; use keyboard; use fsedit; use do_pkgs; use install::pkgs; use any; use log; our @ISA = qw(do_pkgs); =head1 SYNOPSYS Generic installation module containing steps definition. Handle the base installer steps. This generic installation module containing steps definition. All steps should always be defined here as some methods may be used on automatic mode. There is no interactivity available. Typically are defined base operation for configuring each step according to $o. It is inherited by other steps_* modules (who also inherit from the proper interactive::* module). =head1 Functions =over =cut @filesToSaveForUpgrade = qw( /etc/ld.so.conf /etc/fstab /etc/hosts /etc/conf.modules /etc/modules.conf ); @filesNewerToUseAfterUpgrade = qw( /etc/profile ); #-###################################################################################### #- OO Stuff #-###################################################################################### sub new($$) { my ($type, $o) = @_; bless $o, ref($type) || $type; return $o; } sub charsetChanged { my ($_o) = @_; } #-###################################################################################### #- In/Out Steps Functions #-###################################################################################### =back =head2 In/Out Steps Functions =over =item enteringStep($_o, $step) Log that a new step has begun. =cut sub enteringStep { my ($_o, $step) = @_; log::l("starting step `$step'"); } =item leavingStep($_o, $step) Log that a new step has finished. Refresh the logs in /mnt/root/drakx with the latest installer logs from /tmp. Then =cut sub leavingStep { my ($o, $step) = @_; log::l("step `$step' finished"); if (-d "$::prefix/root/drakx") { eval { cp_af("/tmp/ddebug.log", "$::prefix/root/drakx") }; output(install::any::auto_inst_file(), install::any::g_auto_install(1)); } foreach my $s (@{$o->{orderedSteps}}) { #- the reachability property must be recomputed each time to take #- into account failed step. next if $o->{steps}{$s}{done} && !$o->{steps}{$s}{redoable}; my $reachable = 1; if (my $needs = $o->{steps}{$s}{needs}) { my @l = ref($needs) ? @$needs : $needs; $reachable = min(map { $o->{steps}{$_}{done} || 0 } @l); } $o->{steps}{$s}{reachable} = 1 if $reachable; } $o->{steps}{$step}{reachable} = $o->{steps}{$step}{redoable}; while (my $f = shift @{$o->{steps}{$step}{toBeDone} || []}) { eval { &$f() }; if (my $err = $@) { $o->ask_warn(N("Error"), [ N("An error occurred, but I do not know how to handle it nicely. Continue at your own risk."), formatError($err) || $err ]); } } } =item errorInStep($_o, $err) Handle a failing step. The base class just exists. =cut sub errorInStep { my ($_o, $err) = @_; print "error :(\n"; print "$err\n\n"; c::_exit(1); } sub kill_action {} #-###################################################################################### #- Steps Functions #-###################################################################################### #------------------------------------------------------------------------------ =back =head2 Steps Functions Those functions define the base steps. They can be overloaded in either: =over 4 =item * L for auto install =item * L for interactive text or graphic install =item * L for specialized graphical GUIs =back =over =item selectLanguage($o) This step enables to select the language =cut sub selectLanguage { my ($o) = @_; $o->{locale}{langs} ||= { $o->{locale}{lang} => 1 }; if (!exists $o->{locale}{country}) { lang::lang_changed($o->{locale}); } add2hash_($o->{locale}, { utf8 => lang::utf8_should_be_needed($o->{locale}) }); lang::set($o->{locale}, !$o->isa('interactive::gtk')); log::l("selectLanguage: pack_langs: ", lang::pack_langs($o->{locale}{langs}), " utf8-flag: ", to_bool($o->{locale}{utf8})); #- for auto_install compatibility with old $o->{keyboard} containing directly $o->{keyboard}{KEYBOARD} $o->{keyboard} = { KEYBOARD => $o->{keyboard} } if $o->{keyboard} && !ref($o->{keyboard}); if (!$o->{keyboard} || $o->{keyboard}{unsafe}) { $o->{keyboard} = keyboard::default($o->{locale}); $o->{keyboard}{unsafe} = 1; keyboard::setup_install($o->{keyboard}); } $o->charsetChanged; addToBeDone { if ($o->{isUpgrade}) { #- preserve existing locale settings (mga#24671) $o->{locale} = lang::read(); $o->{locale}{langs}{$o->{locale}{lang}} = 1; } else { lang::write_langs($o->{locale}{langs}); } } 'formatPartitions'; addToBeDone { lang::write_and_install($o->{locale}, $o->do_pkgs); } 'installPackages'; } #------------------------------------------------------------------------------ =item selectKeyboard($o) This step enables to select the keyboard to use during the installation and in the installed system after boot. =cut sub selectKeyboard { my ($o) = @_; keyboard::setup_install($o->{keyboard}); addToBeDone { #- the bkmap keymaps in installer are deficient, we need to load the real one before keyboard::write which will generate /etc/sysconfig/console/default.kmap run_program::rooted($::prefix, 'loadkeys', keyboard::keyboard2kmap($o->{keyboard})) or log::l("loadkeys failed"); keyboard::write($o->{keyboard}); } 'installPackages' if !$o->{isUpgrade} || !$o->{keyboard}{unsafe}; } #------------------------------------------------------------------------------ =item acceptLicense() This step enforces accepting the license before continuing =cut sub acceptLicense {} #------------------------------------------------------------------------------ sub setupSCSI { my ($o) = @_; install::any::configure_pcmcia($o); modules::load(modules::category2modules('disk/cdrom')); modules::load_category($o->{modules_conf}, 'bus/firewire'); modules::load_category($o->{modules_conf}, 'disk/scsi'); #- load disk/scsi before disk/ide since libata is now the default #- (to prevent modules::load_category from loading ide-generic too early) modules::load_category($o->{modules_conf}, 'disk/ide|hardware_raid|sata|firewire'); install::any::getHds($o); } #------------------------------------------------------------------------------ sub selectInstallClass { my ($o) = @_; if ($o->{partitioning}{use_existing_root} || $o->{isUpgrade}) { # either one root is defined (and all is ok), or we take the first one we find my $p = fs::get::root_($o->{fstab}) || (first(install::any::find_root_parts($o->{fstab}, $::prefix)) || die)->{part}; $o->{migrate_device_names} = install::any::use_root_part($o->{all_hds}, $p); $o->{previous_release} = $p if $o->{isUpgrade}; } } #------------------------------------------------------------------------------ sub doPartitionDisksBefore { my ($o) = @_; log::l("fdisk before:\n" . any::fdisk()); eval { eval { fs::mount::umount("$::prefix/sys/kernel/debug/usb") }; eval { fs::mount::umount("$::prefix/sys") }; eval { fs::mount::umount("$::prefix/proc") }; eval { fs::mount::umount_all($o->{fstab}) }; eval { sleep 1; fs::mount::umount_all($o->{fstab}) } if $@; #- HACK } if $o->{fstab} && !$::testing; } #------------------------------------------------------------------------------ sub doPartitionDisksAfter { my ($o) = @_; fs::any::write_hds($o->{all_hds}, $o->{fstab}, !$o->{isUpgrade}, sub { $o->rebootNeeded }, $o); log::l("fdisk after\n" . any::fdisk()); if ($::local_install) { #- We skipped the setupSCSI step, so $o->{fstab} will be empty. We need to #- add a fake entry, to satisfy the following check for a root partition. my $fstab = [ fs::read_fstab('', '/proc/mounts') ]; my $part = fs::get::mntpoint2part($::prefix, $fstab) || $fstab->[0]; $part->{mntpoint} = '/'; $part->{isMounted} = 1; $o->{fstab} = [ $part ]; } fs::any::check_hds_boot_and_root($o->{all_hds}, $o->{fstab}, $o->{isUpgrade}, $o->{match_all_hardware}); if ($o->{partitioning}{use_existing_root}) { #- ensure those partitions are mounted so that they are not proposed in choosePartitionsToFormat fs::mount::part($_) foreach sort { $a->{mntpoint} cmp $b->{mntpoint} } grep { $_->{mntpoint} && maybeFormatted($_) } @{$o->{fstab}}; } } #------------------------------------------------------------------------------ sub doPartitionDisks { my ($o) = @_; if ($o->{partitioning}{auto_allocate}) { catch_cdie { fsedit::auto_allocate($o->{all_hds}, $o->{partitions}) } sub { 1 }; } } #------------------------------------------------------------------------------ sub rebootNeeded($) { my ($_o) = @_; log::l("Rebooting..."); c::_exit(0); } sub choosePartitionsToFormat { my ($o) = @_; fs::partitioning::guess_partitions_to_format($o->{fstab}); } sub formatMountPartitions { my ($o) = @_; fs::format::formatMount_all($o->{all_hds}, $o->{fstab}, undef); } #------------------------------------------------------------------------------ sub setPackages { my ($o) = @_; install::any::setPackages($o); } sub ask_deselect_media__copy_on_disk { my (undef, $_hdlists, $_copy_rpms_on_disk) = @_; 0; } sub ask_change_cd { my (undef, $phys_m) = @_; log::l("change to medium $phys_m refused (it can't be done automatically)"); 0; } sub selectSupplMedia { '' } sub choosePackages { my ($o, $o_compssListLevel) = @_; #- clear the mirror cache before upgrading: eval { rm_rf("$::prefix/var/cache/urpmi/mirrors.cache") }; #- now for upgrade, package that must be upgraded are #- selected first, after is used the same scheme as install. #- make sure we kept some space left for available else the system may #- not be able to start my $available = install::any::getAvailableSpace($o); my $availableCorrected = install::pkgs::invCorrectSize($available / sqr(1024)) * sqr(1024); log::l(sprintf "available size %s (corrected %s)", formatXiB($available), formatXiB($availableCorrected)); #- !! destroying user selection of packages (they may have done individual selection before) exists $o->{compssListLevel} || defined $o_compssListLevel and install::pkgs::setSelectedFromCompssList($o->{packages}, $o->{rpmsrate_flags_chosen}, $o_compssListLevel || $o->{compssListLevel}, $availableCorrected); $availableCorrected; } =item live_patch_URPM() This function is used when upgrading a Red Hat or a Conectiva installation. It live patches URPM::Package::compare_pkg() and URPM::Package::compare() so that Mageia packages are always preferred over existing packages that came from a different vendor. =cut sub live_patch_URPM() { sub prefering_mga { my ($lpkg, $rpkg_ver, $c) = @_; my $lpkg_ver = $lpkg->version . '-' . $lpkg->release; log::l($lpkg->name . ' ' . ': prefering ' . ($c == 1 ? "$lpkg_ver over $rpkg_ver" : "$rpkg_ver over $lpkg_ver")); } my $old_compare_pkg = \&URPM::Package::compare_pkg; undef *URPM::Package::compare_pkg; *URPM::Package::compare_pkg = sub { my ($lpkg, $rpkg) = @_; my $c = ($lpkg->release =~ /mga/ ? 1 : 0) - ($rpkg->release =~ /mga/ ? 1 : 0); if ($c) { prefering_mga($lpkg, $rpkg->version . '-' . $rpkg->release, $c); $c; } else { &$old_compare_pkg; } }; my $old_compare = \&URPM::Package::compare; undef *URPM::Package::compare; *URPM::Package::compare = sub { my ($lpkg, $rpkg_ver) = @_; my $c = ($lpkg->release =~ /mga/ ? 1 : 0) - ($rpkg_ver =~ /mga/ ? 1 : 0); if ($c) { prefering_mga($lpkg, $rpkg_ver, $c); return $c; } &$old_compare; }; } sub upgrading_redhat() { #- remove weird config files that bother Xconfig::* too much unlink "$::prefix/etc/X11/XF86Config"; unlink "$::prefix/etc/X11/XF86Config-4"; } =item beforeInstallPackages($o) It's called just before installing packages. If we're upgrading a Red Hat installtion, it'll live patch URPM first. =cut sub beforeInstallPackages { my ($o) = @_; read_bootloader_config($o); if ($o->{isUpgrade}) { $o->{modules_conf}->merge_into(modules::any_conf->read); #- save these files in case of upgrade failure. foreach (@filesToSaveForUpgrade) { unlink "$::prefix/$_.mdkgisave"; if (-e "$::prefix/$_") { eval { cp_af("$::prefix/$_", "$::prefix/$_.mdkgisave") }; } } foreach (@filesNewerToUseAfterUpgrade) { unlink "$::prefix/$_.rpmnew"; } log::l("converting filesystem for usrmove"); if (!run_program::run('/usr/lib/dracut/modules.d/30convertfs/convertfs.sh', $::prefix)) { mkdir_p("$::prefix/root/drakx") if ! -d "$::prefix/root/drakx"; # logs are only copied to $::prefix/root/drakx at the end of each step, so do it manually now eval { cp_af("/tmp/ddebug.log", "$::prefix/root/drakx") }; die "Unable to convert filesystem prior to upgrade. Check ddebug.log for details"; } } #- mainly for upgrading redhat packages, but it can help other my @should_not_be_dirs = qw(/usr/share/locale/zh_TW/LC_TIME /usr/include/GL); my @should_be_dirs = qw(/etc/X11/xkb); my @to_remove = ( (grep { !-l $_ && -d $_ } map { "$::prefix$_" } @should_not_be_dirs), (grep { -l $_ || !-d $_ && -e $_ } map { "$::prefix$_" } @should_be_dirs), ); rm_rf(@to_remove); live_patch_URPM() if $o->{isUpgrade} !~ /mageia/; if ($o->{isUpgrade} eq 'redhat') { upgrading_redhat(); } if ($o->{isUpgrade} =~ /redhat|conectiva/) { #- to ensure supermount is removed (???) fs::mount_options::set_all_default($o->{all_hds}, %$o, lang::fs_options($o->{locale})); } #- some packages need such files for proper installation. install::any::write_fstab($o); #- resolv.conf will be modified at boot time #- the following will ensure we have a working DNS during install if (-e "/etc/resolv.conf" && ! -e "$::prefix/etc/resolv.conf") { cp_af("/etc/resolv.conf", "$::prefix/etc"); } foreach ('/run', '/tmp/.X11-unix') { if (-e $_) { mkdir "$::prefix/$_"; run_program::run('mount', '--bind', $_, "$::prefix/$_"); } } log::l("setting excludedocs to $o->{excludedocs}"); substInFile { s/%_excludedocs.*//; $_ .= "%_excludedocs yes\n" if eof && $o->{excludedocs} } "$::prefix/etc/rpm/macros"; #- add oem theme if the files exists. mkdir_p("$::prefix/usr/share"); install::media::getAndSaveFile_($o->{stage2_phys_medium}, "install/oem-theme.rpm", "$::prefix/usr/share/oem-theme.rpm"); system("sh", "-c", $o->{preInstallNonRooted}) if $o->{preInstallNonRooted}; } =item pkg_install($o, @l) Select the requested packages (@l) then install them using installPackages() if they're not already installed. Returns number of packages installed, 0 if none were selected. =cut sub pkg_install { my ($o, @l) = @_; log::l("selecting packages " . join(" ", @l)); install::pkgs::select_by_package_names($o->{packages}, \@l); my @toInstall = install::pkgs::packagesToInstall($o->{packages}); if (@toInstall) { log::l("installing packages"); $o->installPackages; } else { log::l("all packages selected are already installed, nothing to do"); delete $o->{packages}{rpmdb}; #- make sure rpmdb is closed 0; } } =item installCallback() The default package installation callback. It does nothing. It's overidden in text & graphicall installations in order to display a nice progress bar. =cut sub installCallback { # my (undef, $msg, @para) = @_; # log::l("$msg: " . join(',', @para)); } =item installPackages($o, $o_interactive) Install the selected packages. =cut sub installPackages { my ($o, $o_interactive) = @_; my $p = fs::get::root_($o->{fstab}); if (isLUKS($p)) { install::pkgs::selectPackage($o->{packages}, install::pkgs::packageByName($o->{packages}, 'plymouth')); } my $packages = $o->{packages}; install::pkgs::remove_marked_ask_remove($packages, \&installCallback); #- small transaction will be built based on this selection and depslist. my @toInstall = install::pkgs::packagesToInstall($packages); my $exit_code; my $time = time(); { local $ENV{DURING_INSTALL} = 1; local $ENV{LOCAL_INSTALL} = 1 if $::local_install; local $ENV{TMPDIR} = '/tmp'; local $ENV{TMP} = '/tmp'; local $ENV{HOME}; local $packages->{options}{auto} = !$o_interactive; $exit_code = install::pkgs::install($o->{isUpgrade}, \@toInstall, $packages, \&installCallback); } any::writeandclean_ldsoconf($::prefix); log::l("Install took: ", formatTimeRaw(time() - $time)); run_program::rooted_or_die($::prefix, 'ldconfig') if !$o->{justdb}; $exit_code and die "Installation failed"; install::media::log_sizes(); scalar(@toInstall); #- return number of packages installed. } sub afterInstallPackages($) { my ($o) = @_; read_bootloader_config($o) if $o->{isUpgrade} && is_empty_hash_ref($o->{bootloader}); die N("Some important packages did not get installed properly. Either your cdrom drive or your cdrom is defective. Check the cdrom on an installed computer using \"rpm -qpl media/main/*.rpm\" ") if any { m|read failed: Input/output error| } cat_("$::prefix/root/drakx/install.log"); if (!$o->{justdb}) { -x "$::prefix/usr/bin/dumpkeys" or $::testing or die "Some important packages did not get installed properly. Please switch to console 2 (using ctrl-alt-f2) and look at the log file /tmp/ddebug.log Consoles 1,3,4,7 may also contain interesting information"; } #- why not? cuz weather is nice today :-) [pixel] common::sync(); common::sync(); #- generate /etc/lvmtab needed for rc.sysinit run_program::rooted($::prefix, 'lvm2', 'vgscan') if -e '/etc/lvmtab'; require harddrake::autoconf; #- configure PCMCIA services if needed. harddrake::autoconf::pcmcia($o->{pcmcia}); #- configure CPU frequency modules harddrake::autoconf::cpufreq(); harddrake::autoconf::floppy(); # prevent slow boot on first boot: my $cfg_file = "$::prefix/etc/sysconfig/harddrake2/kernel"; if (-f $cfg_file) { my %kernel_config = getVarsFromSh($cfg_file); $kernel_config{IS_LAPTOP} = bool2text(detect_devices::isLaptop()); setVarsInSh($cfg_file, \%kernel_config); } #- for mandrake_firstime touch "$::prefix/var/lock/TMP_1ST"; fs::any::set_cdrom_symlink($o->{all_hds}{raw_hds}); any::config_mtools($::prefix); #- make sure wins is disabled in /etc/nsswitch.conf #- else if eth0 is not existing, glibc segfaults. substInFile { s/\s*wins// if /^\s*hosts\s*:/ } "$::prefix/etc/nsswitch.conf"; if ($o->{mouse}{device} =~ /ttyS/) { log::l("disabling gpm for serial mice (does not get along nicely with X)"); run_program::rooted($::prefix, "chkconfig", "--del", "gpm"); } if ($o->{pcmcia}) { substInFile { s/.*(TaskBarShowAPMStatus).*/$1=1/ } "$::prefix/usr/lib/X11/icewm/preferences"; eval { cp_af("$::prefix/usr/share/applnk/System/kapm.kdelnk", "$::prefix/etc/skel/Desktop/Autostart/kapm.kdelnk") }; } if ($o->{brltty}) { output("$::prefix/etc/brltty.conf", <{brltty}{driver} braille-device $o->{brltty}{device} text-table $o->{brltty}{table} EOF } install::any::disable_user_view() if $o->{security} > 1 || $o->{authentication}{NIS}; run_program::rooted($::prefix, "kdeDesktopCleanup"); #- move some file after an upgrade that may be seriously annoying. #- and rename saved files to .mdkgiorig. if ($o->{isUpgrade}) { my $pkg = install::pkgs::packageByName($o->{packages}, 'rpm'); $pkg && ($pkg->flag_selected || $pkg->flag_installed) && $pkg->compare(">= 4.0") and install::pkgs::cleanOldRpmDb(); log::l("moving previous desktop files that have been updated to Trash of each user"); install::any::kdemove_desktop_file($::prefix); foreach (@filesToSaveForUpgrade) { renamef("$::prefix/$_.mdkgisave", "$::prefix/$_.mdkgiorig") if -e "$::prefix$_.mdkgisave"; } foreach (@filesNewerToUseAfterUpgrade) { if (-e "$::prefix/$_.rpmnew" && -e "$::prefix/$_") { renamef("$::prefix/$_", "$::prefix/$_.mdkgiorig"); renamef("$::prefix/$_.rpmnew", "$::prefix/$_"); } } } renamef(install::pkgs::removed_pkgs_to_upgrade_file(), install::pkgs::removed_pkgs_to_upgrade_file() . '.done'); unlink(glob("$::prefix/root/drakx/*.upgrading")); if ($o->{upgrade_by_removing_pkgs_matching}) { if (cat_("$::prefix/etc/inittab.rpmsave") =~ /^id:5:initdefault:\s*$/m) { $o->{X}{xdm} = 1; require Xconfig::various; Xconfig::various::runlevel(5); } } any::fix_broken_alternatives($o->{isUpgrade} eq 'redhat'); #- update theme directly from a package (simplest). if (-s "$::prefix/usr/share/oem-theme.rpm") { run_program::rooted($::prefix, "rpm", "-U", "/usr/share/oem-theme.rpm"); unlink "/usr/share/oem-theme.rpm"; } #- call update-menus at the end of package installation push @{$o->{waitpids}}, run_program::raw({ root => $::prefix, detach => 1 }, "update-menus", "-n"); $o->install_hardware_packages; if ($o->{updatemodules}) { $o->updatemodules($ENV{THIRDPARTY_DEVICE}, $ENV{THIRDPARTY_DIR}); } } =item install_urpmi($o) If needed, write the urpmi configuration according to the media that were used to install the OS. =cut sub install_urpmi { my ($o) = @_; my $pkg = install::pkgs::packageByName($o->{packages}, 'urpmi'); if ($pkg && ($pkg->flag_selected || $pkg->flag_installed) #- this is a workaround. if many urpmi packages are found in the #- provides of all media, packages_providing() might return the wrong #- one. This probably needs to be fixed in URPM || run_program::rooted_get_stdout($::prefix, '/bin/rpm', '-q', 'urpmi') =~ /urpmi/ ) { install::media::install_urpmi($o->{method}, $o->{packages}); install::pkgs::saveCompssUsers($o->{packages}, $o->{compssUsers}); } else { log::l("skipping install_urpmi, urpmi not installed"); } } sub install_hardware_packages { my ($o) = @_; if ($o->{match_all_hardware}) { my @l = pkgs::detect_hardware_packages($o->do_pkgs, $o->{match_all_hardware}); $o->do_pkgs->install(@l) if @l; } } sub updatemodules { my ($_o, $dev, $rel_dir) = @_; return if $::testing; $dev = devices::make($dev) or log::l("updatemodules: bad device $dev"), return; my $mount_dir = '/updatemodules'; find { eval { fs::mount::mount($dev, $mount_dir, $_, 0); 1 }; } 'ext2', 'vfat' or log::l("updatemodules: can't mount $dev"), return; my $dir = "$mount_dir$rel_dir"; foreach my $kernel_version (all("$::prefix/lib/modules")) { log::l("examining updated modules for kernel $kernel_version"); -d "$dir/$kernel_version" or next; log::l("found updatable modules"); run_program::run("cd $dir/$kernel_version ; find -type f | cpio -pdu $::prefix/lib/modules/$kernel_version"); run_program::rooted($::prefix, 'depmod', '-a', '-F', "/boot/System.map-$kernel_version", $kernel_version); } my $category; foreach (cat_("$dir/to_load")) { chomp; if (/^#/) { ($category) = $1 if /\[list_modules: (.*?)\]/; } elsif ($category) { log::l("adding $_ to $category\n"); my $r = \%list_modules::l; $r = $r->{$_} foreach split('/', $category); push @$r, $_; $category = ''; } } fs::mount::umount($mount_dir); } #------------------------------------------------------------------------------ sub selectMouse($) { my ($_o) = @_; } #------------------------------------------------------------------------------ sub configureNetwork { my ($o) = @_; require network::network; network::network::configure_network($o->{net}, $o, $o->{modules_conf}); configure_firewall($o) if !$o->{isUpgrade} && !$o->{justdb}; #- only a http proxy can be used by stage1 #- the method is http even for ftp connections through a http proxy #- use this http proxy for both http and ftp connections if ($o->{method} eq "http" && $ENV{PROXY}) { my $proxy = "http://$ENV{PROXY}" . ($ENV{PROXYPORT} && ":$ENV{PROXYPORT}"); add2hash($o->{miscellaneous} ||= {}, { http_proxy => $proxy, ftp_proxy => $proxy, }); network::network::proxy_configure($o->{miscellaneous}); } } sub configure_firewall { my ($o) = @_; #- set up a firewall if ports have been specified or if the security level is high enough $o->{firewall_ports} ||= '' if $o->{security} >= 1 && !exists $o->{firewall_ports}; if (defined $o->{firewall_ports}) { require network::drakfirewall; $o->{firewall_ports} ||= ''; #- don't open any port by default network::drakfirewall::set_ports($o->do_pkgs, 0, $o->{firewall_ports}, 'log_net_drop'); network::drakfirewall::set_ifw($o->do_pkgs, 1, [ 'psd' ], ''); } } #------------------------------------------------------------------------------ sub installUpdates {} sub summaryBefore {} sub summary { my ($o) = @_; configureTimezone($o); } sub summaryAfter { my ($_o) = @_; } #------------------------------------------------------------------------------ sub configureTimezone { my ($o) = @_; if ($o->{timezone}{ntp}) { # We prefer chrony, but we'll deal with ntpd for the sake of upgrades my $pkg = install::pkgs::packageByName($o->{packages}, 'chrony'); unless ($pkg && $pkg->flag_installed) { $pkg = install::pkgs::packageByName($o->{packages}, 'ntpsec'); $o->pkg_install('chrony') unless $pkg && $pkg->flag_installed; } } require timezone; timezone::write($o->{timezone}); } #------------------------------------------------------------------------------ sub configureServices { my ($o) = @_; if ($o->{services}) { require services; services::doit($o, $o->{services}); } } #------------------------------------------------------------------------------ sub setRootPassword_addUser { my ($o) = @_; setRootPassword($o); addUser($o); } sub setRootPassword { my ($o) = @_; $o->{superuser} ||= {}; require authentication; authentication::set_root_passwd($o->{superuser}, $o->{authentication}); install::any::set_authentication($o); } sub addUser { my ($o) = @_; my $users = $o->{users} ||= []; if ($::prefix) { #- getpwnam, getgrnam, getgrid works symlinkf("$::prefix/etc/passwd", '/etc/passwd'); symlinkf("$::prefix/etc/group", '/etc/group'); } any::add_users($users, $o->{authentication}); if ($o->{rpmsrate_flags_chosen}{CAT_X}) { my $autologin = any::get_autologin(); $autologin->{user} = $o->{autologin}; $autologin->{desktop} = $o->{desktop} if $o->{desktop}; $autologin->{dm} = $o->{dm} if $o->{dm}; any::set_autologin($o->do_pkgs, $autologin, $o->{step}{auto}); } install::any::disable_user_view() if @$users == (); } #------------------------------------------------------------------------------ sub read_bootloader_config { my ($o) = @_; require bootloader; eval { add2hash($o->{bootloader} ||= {}, bootloader::read($o->{all_hds})) }; $@ && $o->{isUpgrade} and log::l("read_bootloader_config failed: $@"); $o->{bootloader}{bootUnsafe} = 0 if $o->{bootloader}{boot}; #- when upgrading, do not ask where to install the bootloader (mbr vs boot partition) } sub setupBootloaderBefore { my ($o) = @_; my $bool = $o->{meta_class} ne 'server'; any::setupBootloaderBefore($o->do_pkgs, $o->{bootloader}, $o->{all_hds}, $o->{fstab}, $o->{keyboard}, $o->{allowFB}, $o->{vga}, $bool, $bool); } sub setupBootloader { my ($o) = @_; any::install_bootloader_pkgs($o->do_pkgs, $o->{bootloader}); require bootloader; bootloader::install($o->{bootloader}, $o->{all_hds}); } #------------------------------------------------------------------------------ sub configureXBefore { my ($o) = @_; #- keep this here if the package has to be updated. $o->pkg_install("task-x11"); } sub configureX { my ($o) = @_; configureXBefore($o); require Xconfig::default; $o->{raw_X} = Xconfig::default::configure($o->do_pkgs, $o->{keyboard}, $o->{mouse}); require Xconfig::main; Xconfig::main::configure_everything_auto_install($o->{raw_X}, $o->do_pkgs, $o->{X}, install::any::X_options_from_o($o)); configureXAfter($o); } sub configureXAfter { my ($_o) = @_; } #------------------------------------------------------------------------------ sub miscellaneousBefore { my ($o) = @_; require security::level; require security::various; $o->{security} ||= security::level::get(); $o->{security_user} ||= security::various::config_security_user($::prefix); log::l("security level is $o->{security}"); } sub miscellaneous { my ($_o) = @_; #- keep some given parameters #-TODO } sub miscellaneousAfter { my ($o) = @_; $ENV{SECURE_LEVEL} = $o->{security}; #- deprecated with chkconfig 1.3.4-2mdk, uses /etc/sysconfig/msec addToBeDone { addVarsInSh("$::prefix/etc/sysconfig/system", { META_CLASS => $o->{meta_class} }); eval { install::any::set_security($o) } if !$o->{isUpgrade}; } 'installPackages'; } #------------------------------------------------------------------------------ =item exitInstall($o) Cleanly exit the installer: =over 4 =item * running any post script for auto install ("postInstallNonRooted" and "postInstall") =item * saving the install report in /root.drakx/report.bug.xz =item * umounting the installer media =back =cut sub exitInstall { my ($o) = @_; install::any::deploy_server_notify($o) if exists $o->{deploy_server}; #- mainly for auto_install's #- do not use run_program::xxx because it does not leave stdin/stdout unchanged system("bash", "-c", $o->{postInstallNonRooted}) if $o->{postInstallNonRooted}; system("chroot", $::prefix, "bash", "-c", $o->{postInstall}) if $o->{postInstall}; eval { my $report = '/root/drakx/report.bug'; unlink "$::prefix$report", "$::prefix$report.gz"; output "$::prefix$report", install::any::report_bug(); run_program::rooted($::prefix, 'xz', $report); }; output("$::prefix/root/drakx/package_list.pl", install::any::selected_leaves_pl($o)); eval { install::any::getAndSaveAutoInstallFloppies($o, 1) }; eval { output "$::prefix/root/drakx/README", sprintf("This directory contains several installation-related files, mostly log files (very useful if you ever report a bug!). Beware that some %s tools rely on the contents of some of these files... so remove any file from here at your own risk! ", "Mageia") }; #- wait for remaining processes. foreach (@{$o->{waitpids}}) { waitpid $_, 0; log::l("pid $_ returned $?"); } install::media::umount_media($o->{packages}); install::media::openCdromTray($o->{stage2_phys_medium}{device}) if !detect_devices::is_xbox() && $o->{method} eq 'cdrom'; install::media::log_sizes(); } #------------------------------------------------------------------------------ =back =head2 Network Functions =over 4 =item hasNetwork($o) Whether the network is configured for internet. =cut sub hasNetwork { my ($o) = @_; $o->{net}{type} && $o->{net}{network}{NETWORKING} ne 'no' and return 1; log::l("no network seems to be configured for internet ($o->{net}{type},$o->{net}{network}{NETWORKING})"); 0; } =item network_is_cheap($o) Whether the network is fast enough to use (aka not ISDN and the like) =cut sub network_is_cheap { my ($o) = @_; member($o->{net}{type}, qw(adsl lan cable)); } =item start_network_interface($o) Start the network on the specified interface. =cut sub start_network_interface { my ($o) = @_; require network::tools; network::tools::start_net_interface($o->{net}, 0); } =item stop_network_interface($o) Stop the network on the specified interface. =cut sub stop_network_interface { my ($o) = @_; require network::tools; network::tools::stop_net_interface($o->{net}, 0); } =item upNetwork($o, $b_pppAvoided) Start the network if configured and fast enough (or if PPP is authorized). =cut #------------------------------------------------------------------------------ sub upNetwork { my ($o, $b_pppAvoided) = @_; install::any::is_network_install($o) || $::local_install and return 1; $o->{modules_conf}->write; if (! -e "/etc/resolv.conf") { #- symlink resolv.conf in install root too so that updates and suppl media can be added symlink "$::prefix/etc/resolv.conf", "/etc/resolv.conf"; } if (hasNetwork($o)) { if (network_is_cheap($o)) { log::l("starting network ($o->{net}{type})"); start_network_interface($o); return 1; } elsif (!$b_pppAvoided) { log::l("starting network (PPP: $o->{net}{type})"); eval { modules::load(qw(serial bsd_comp ppp_deflate)) }; run_program::rooted($::prefix, "/etc/rc.d/init.d/syslog", "start"); start_network_interface($o); return 1; } else { log::l(qq(not starting network (b/c ppp avoided and type is "$o->{net}{type})")); } } $::testing; } #------------------------------------------------------------------------------ =item downNetwork($o) Stop the network if it's no a network installation. =cut sub downNetwork { my ($o, $costlyOnly) = @_; install::any::is_network_install($o) || $::local_install and return 1; $o->{modules_conf}->write; if (hasNetwork($o)) { if (!$costlyOnly) { stop_network_interface($o); return 1; } elsif (!network_is_cheap($o)) { stop_network_interface($o); run_program::rooted($::prefix, "/etc/rc.d/init.d/syslog", "stop"); eval { modules::unload(qw(ppp_deflate bsd_comp serial)) }; return 1; } } $::testing; } #------------------------------------------------------------------------------ =back =head2 Misc Functions =over =item cleanIfFailedUpgrade($o) Clean a failed install, saving the important files. =cut sub cleanIfFailedUpgrade($) { my ($o) = @_; #- if an upgrade has failed, there should be .mdkgisave files around. if ($o->{isUpgrade}) { foreach (@filesToSaveForUpgrade) { if (-e "$::prefix/$_" && -e "$::prefix/$_.mdkgisave") { rename "$::prefix/$_", "$::prefix/$_.mdkginew"; #- keep new files around in case ! rename "$::prefix/$_.mdkgisave", "$::prefix/$_"; } } } } =back =cut 1;