summaryrefslogtreecommitdiffstats
path: root/lib/MGA/DrakISO/BuildRoot.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MGA/DrakISO/BuildRoot.pm')
-rwxr-xr-xlib/MGA/DrakISO/BuildRoot.pm259
1 files changed, 259 insertions, 0 deletions
diff --git a/lib/MGA/DrakISO/BuildRoot.pm b/lib/MGA/DrakISO/BuildRoot.pm
new file mode 100755
index 0000000..7112cd9
--- /dev/null
+++ b/lib/MGA/DrakISO/BuildRoot.pm
@@ -0,0 +1,259 @@
+# Copyright (C) 2005 Mandriva
+# Olivier Blin <oblin@mandriva.com>
+# Copyright (C) 2017 Mageia
+# Martin Whitaker <mageia@martin-whitaker.me.uk>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+package MGA::DrakISO::BuildRoot;
+
+use strict;
+
+use MDK::Common;
+use common;
+
+use MGA::DrakISO::Live;
+use MGA::DrakISO::Loopback;
+use MGA::DrakISO::Utils;
+
+use Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(install_live_system customise_live_system);
+
+sub install_live_system {
+ my ($live) = @_;
+
+ my $repository = $live->{settings}{repository} . '/' . $live->{settings}{arch};
+
+ my $drakx_in_chroot = $repository . '/misc/drakx-in-chroot';
+ my $remote_repository = $repository =~ m!^(ftp|http)://! && $1;
+ if ($remote_repository) {
+ my $local_drakx_in_chroot = $live->get_builddir . $live->{prefix}{build}{scripts} . '/drakx-in-chroot';
+ mkdir_p(dirname($local_drakx_in_chroot));
+ run_('curl', '--silent', '-o', $local_drakx_in_chroot, $drakx_in_chroot)
+ or die "unable to get drakx-in-chroot from remote repository\n";
+ $drakx_in_chroot = $local_drakx_in_chroot;
+ }
+
+ local %ENV = (
+ %ENV,
+ (map { "DRAKLIVE_" . uc($_->[0]) => $_->[1] } group_by2(%{$live->{settings}})),
+ %{$live->{system}{install_env}},
+ );
+ $ENV{DRAKLIVE_LANGS} = join(':', $live->get_langs);
+ run_({ targetarch => $live->{settings}{arch} },
+ 'perl', $drakx_in_chroot,
+ $repository,
+ $live->get_system_root,
+ if_($live->{system}{auto_install}, '--auto_install', $live->{settings}{config_root} . '/' . $live->{system}{auto_install}),
+ if_($live->{system}{patch_install}, '--defcfg', $live->{settings}{config_root} . '/' . $live->{system}{patch_install}),
+ if_($live->{system}{rpmsrate}, '--rpmsrate', $live->{settings}{config_root} . '/' . $live->{system}{rpmsrate}),
+ ($live->{system}{stage2_updates} ? (map { ('--stage2-update', $live->{settings}{config_root} . '/' . $_->[0], $_->[1]) } @{$live->{system}{stage2_updates}}) : ()),
+ ) or die "unable to install system chroot\n";
+}
+
+sub customise_live_system {
+ my ($live) = @_;
+
+ my $previous_umask = umask;
+ #- workaround buggy installation of directories that are not owned by any packages
+ umask 022;
+
+ mount_system_fs($live);
+
+ #- copy resolv.conf for name resolution to work when adding media
+ cp_f("/etc/resolv.conf", $live->get_system_root . "/etc/");
+
+ #- remove previous draklive leftovers if needed
+ run_({ root => $live->get_system_root }, 'urpmi.removemedia', '-a');
+
+ foreach (@{$live->{system}{additional_media}}) {
+ run_({ root => $live->get_system_root }, 'urpmi.addmedia', if_($_->{distrib}, '--distrib'), $_->{name}, $_->{path})
+ or die "unable to add media from $_->{path}\n";
+ @{$_->{packages} || []} or next;
+ run_({ root => $live->get_system_root, targetarch => $live->{settings}{arch} },
+ 'urpmi', '--auto', '--no-verify-rpm', if_(!$_->{distrib}, '--searchmedia', $_->{name}), @{$_->{packages}})
+ or die "unable to install packages from $_->{path}\n";
+ }
+
+ #- additional rpms may have dependencies in additional media
+ if (@{$live->{system}{rpms} || []}) {
+ my $rpm_tmp_dir = '/tmp/draklive_rpms';
+ mkdir_p($live->get_system_root . $rpm_tmp_dir);
+ cp_f((map { $live->{settings}{config_root} . '/' . $_ } @{$live->{system}{rpms}}), $live->get_system_root . $rpm_tmp_dir);
+ run_({ root => $live->get_system_root, targetarch => $live->{settings}{arch} },
+ 'urpmi', '--auto', '--no-verify-rpm',
+ map { $rpm_tmp_dir . '/' . basename($_) } @{$live->{system}{rpms}})
+ or die "unable to install additional system rpms\n";
+ rm_rf($live->get_system_root . $rpm_tmp_dir);
+ }
+
+ #- remove urpmi media added by drakx-in-chroot and additional media, they're unusable
+ run_({ root => $live->get_system_root }, 'urpmi.removemedia', '-a');
+
+ my $erase = join(' ', @{$live->{system}{erase_rpms} || []});
+ run_({ root => $live->get_system_root, targetarch => $live->{settings}{arch} },
+ 'sh', '-c', "rpm -qa $erase | xargs rpm -e ") if $erase;
+
+ run_({ root => $live->get_system_root }, 'systemctl', 'disable', $_ . '.service') foreach @{$live->{system}{disable_services}};
+ run_({ root => $live->get_system_root }, 'systemctl', 'disable', $_ . '.timer') foreach @{$live->{system}{disable_timers}};
+
+ #- make sure harddrake is run:
+ #- if previous HW config file is empty, we assumes DrakX has just completed the installation
+ #- (do it in chroot, or else Storable from the build box may write an incompatible config file)
+ run_({ root => $live->get_system_root },
+ 'perl', '-MStorable', '-e', qq(Storable::store({ UNKNOWN => {} }, '/etc/sysconfig/harddrake2/previous_hw')));
+
+ #- remove some build-machine specific configuration
+ clean_system_conf_file($live, $_)
+ foreach qw(/etc/mtab /etc/iftab /etc/shorewall/interfaces /etc/mdadm.conf),
+ if_(!$live->{system}{skip_fstab}, '/etc/fstab');
+ unlink($_) foreach map { glob($live->get_system_root . $_) } @{$live->{system}{remove_files} || []};
+
+ if ($live->{system}{modules_conf}) {
+ local $::prefix = $live->get_system_root;
+ local *modules::write_preload_conf = sub {}; #- FIXME, make this an option
+ my $modules_conf = modules::any_conf->vnew;
+ put_in_hash($modules_conf, $live->{system}{modules_conf});
+ $modules_conf->write;
+ }
+
+ my $mount_options = $live->{media}->get_media_setting('mount_options') || "defaults";
+ output_with_perm($live->get_system_root . '/etc/fstab', 0644,
+ $live->{mount}{overlay}
+ ? "none / $live->{mount}{overlay} $mount_options 0 0\n"
+ : $live->{media}->get_media_setting('source') . " / " . $live->{media}->get_media_setting('fs') . " $mount_options 1 1\n"
+ ) unless $live->{system}{skip_fstab};
+
+ #- interactive mode can lead to race in initscripts
+ #- (don't use addVarsInSh from MDK::Common, it breaks shell escapes)
+ substInFile { s/^PROMPT=.*/PROMPT=no/ } $live->get_system_root . '/etc/sysconfig/init';
+
+ configure_draklive_resize($live);
+
+ if ($live->{system}{preselect_kdm_user}) {
+ #- preselect specified user in kdm
+ my $kdm_cfg = $live->get_system_root . '/etc/kde/kdm/kdmrc';
+ update_gnomekderc($kdm_cfg, 'X-:0-Greeter' => (PreselectUser => 'Default', DefaultUser => $live->{system}{preselect_kdm_user})) if -f $kdm_cfg;
+ }
+
+ #- apply patches and install files after the configuration is cleaned
+ #- to allow special configuration files (especially modprobe.preload)
+ foreach (@{$live->{system}{patches}}) {
+ my $patch = $live->{settings}{config_root} . '/' . $_;
+ my @args = ('-p0', '-d', $live->get_system_root, '-i', $patch);
+ run_program::run('patch', '>', '/dev/null', '--dry-run', '-f', '-R', @args) || run_('patch', @args)
+ or die "unable to apply patch " . $patch . "\n";
+ }
+
+ copy_files_to($live, $live->{system}{files}, $live->get_system_root);
+ my @no_install_files = map { $_->[1] } grep { $_->[2] && $_->[2]{no_install} } @{$live->{system}{files}};
+ output_p($live->get_system_root . '/etc/draklive-install.d/remove.d/draklive', map { "$_\n" } @no_install_files);
+
+ eval { rm_rf($live->get_builddir . $live->{prefix}{build}{files}) };
+ mkdir_p($live->get_builddir . $live->{prefix}{build}{files});
+ if ($live->{media}{files}) {
+ copy_files_to($live, $live->{media}{files}, $live->get_builddir . $live->{prefix}{build}{files});
+ }
+ remove_files_from($live->{media}{remove_files}, $live->get_builddir . $live->{prefix}{build}{files});
+
+ run_({ targetarch => $live->{settings}{arch} },
+ "chroot", $live->get_system_root, "bash", "-c", $live->{system}{postInstall}) if $live->{system}{postInstall};
+
+ clean_system_conf_file($live, "/etc/resolv.conf");
+ write_dist_lists($live);
+
+ umount_external_fs($live);
+
+ umask $previous_umask;
+}
+
+sub configure_draklive_resize {
+ my ($live) = @_;
+
+ my $resizable_loopback = find { $_->{min_size} } @{$live->{mount}{dirs} || []};
+ if ($resizable_loopback) {
+ my $media_loopbacks = $live->get_media_prefix('loopbacks');
+ my $ext = $loop_types{$resizable_loopback->{type}}{extension};
+ output($live->get_system_root . '/etc/sysconfig/draklive-resize', <<EOF);
+DRAKLIVE_RESIZE=yes
+LOOPBACK=$live->{prefix}{live}{mnt}$live->{prefix}{media}{mnt}${media_loopbacks}$resizable_loopback->{path}$ext
+TYPE=$resizable_loopback->{fs}
+MIN_SIZE=$resizable_loopback->{min_size}
+MOUNT=$live->{prefix}{live}{mnt}$resizable_loopback->{mountpoint}_resized
+OLD_MOUNT=$live->{prefix}{live}{mnt}$resizable_loopback->{mountpoint}
+UNION=/
+EOF
+ }
+}
+
+sub copy_files_to {
+ my ($live, $files, $root) = @_;
+ foreach (@$files) {
+ my ($source, $dest, $o_opts) = @$_;
+ $dest = $root . '/' . $dest;
+ mkdir_p($dest =~ m|/$| ? $dest : dirname($dest));
+ my @sources = MGA::DrakISO::Utils::glob__($live->{settings}{config_root} . '/' . $source);
+ print STDERR "copying @sources to $dest\n";
+ cp_af(@sources, $dest);
+ my $o_perm = $o_opts && $o_opts->{mode};
+ chmod $o_perm, $dest if $o_perm;
+ }
+}
+
+sub remove_files_from {
+ my ($files, $root) = @_;
+ run_('find', $root, '(', join_lists('-o', map { [ '-name', $_ ] } @$files), ')', '-exec', 'rm', '-r', '{}', ';')
+ if $files && @$files;
+}
+
+sub join_lists {
+ my ($separator, $head, @lists) = @_;
+ @{$head || []}, map { $separator, @$_ } @lists;
+}
+
+sub clean_system_conf_file {
+ my ($live, $file) = @_;
+ substInFile { undef $_ if /^[^#]/ } $live->get_system_root . $file;
+}
+
+sub write_dist_lists {
+ my ($live) = @_;
+
+ my $lists_dir = $live->get_builddir . $live->{prefix}{build}{dist};
+ mkdir_p($lists_dir);
+
+ run_("chroot " . $live->get_system_root . " rpm -qa | sort > " .
+ $lists_dir . '/' . $live->get_name . '.lst');
+
+ run_("chroot " . $live->get_system_root . " rpm -qa --qf '%{name}\n' | sort > " .
+ $lists_dir . '/' . $live->get_name . '.lst.names');
+
+ run_("chroot " . $live->get_system_root .
+ qq( sh -c "rpm -qa --qf '[%{NAME} %{FILESIZES} %{FILESTATES}\n]' | awk '{if(\\\$3==0) {s[\\\$1]+=\\\$2}} END{for (p in s){print s[p],p}}' | sort -n" > ) .
+ $lists_dir . '/' . $live->get_name . '.lst.full');
+
+ run_("chroot " . $live->get_system_root .
+ qq( sh -c "urpmi_rpm-find-leaves | xargs rpm -q --qf '[%{NAME} %{FILESIZES} %{FILESTATES}\n]' | awk '{if(\\\$3==0) {s[\\\$1]+=\\\$2}} END{for (p in s){print s[p],p}}' | sort -n" > ) .
+ $lists_dir . '/' . $live->get_name . '.lst.leaves');
+
+ require lang;
+ my @live_langs = $live->get_langs;
+ my @langs = grep { member($_, @live_langs) || member(lang::locale_to_main_locale($_), @live_langs) } lang::list_langs();
+ my $langs_file = $lists_dir . '/' . $live->get_name . '.langs';
+ output_p($langs_file, map { lang::l2name($_) . " (" . $_ . ")\n" } sort(@langs));
+}
+
+1;