ACC SHELL

Path : /usr/share/YaST2/clients/
File Upload :
Current File : //usr/share/YaST2/clients/inst_kickoff.ycp

/**
 * Module:	inst_kickoff.ycp
 *
 * Authors:	Arvin Schnell <arvin@suse.de>
 *
 * Purpose:	Do various tasks before starting with installation of rpms.
 *
 * $Id: inst_kickoff.ycp 61962 2010-05-06 11:45:24Z jsrain $
 *
 */

{
    textdomain "packager";

    import "Mode";
    import "Stage";
    import "Linuxrc";
    import "Installation";
    import "Popup";
    import "Directory";
    import "ModuleLoading";
    import "Initrd";
    import "Kernel";
    import "Arch";
    import "FileUtils";
    import "String";

void AcpiToInitrd () {
    if (! (Arch::i386 () || Arch::x86_64 () || Arch::ia64 ()))
	return;
    foreach (string m, ["processor", "thermal", "fan"], {
	Initrd::AddModule (m, "");
    });
}

// add xen paravirtualized drivers to initrd if thery are selected for installation
void XenPVToInitrd()
{
    // is any xen-kmp-* package selected?
    if (Pkg::IsSelected("xen-kmp-default")
	|| Pkg::IsSelected("xen-kmp-smp")
	|| Pkg::IsSelected("xen-kmp-pae")
	|| Pkg::IsSelected("xen-kmp-bigsmp")
	|| Pkg::IsSelected("xen-kmp-kdump"))
    {
	// add disk driver
	Initrd::AddModule ("xen-vbd", "");
	// add network driver
	Initrd::AddModule ("xen-vnif", "");

	y2milestone("Added Xen PV drivers to initrd, configured drivers: %1", Initrd::ListModules());
    }
    else
    {
	y2milestone("No xen-kmp-* package is selected for installation, skipping XEN PV driver installation");
    }
}

void HyperVPVToInitrd() {
    // is any hyper-v-kmp-* package selected?
    if (Pkg::IsSelected("hyper-v-kmp-default")
	|| Pkg::IsSelected("hyper-v-kmp-smp")
	|| Pkg::IsSelected("hyper-v-kmp-pae")
	|| Pkg::IsSelected("hyper-v-kmp-bigsmp")
	|| Pkg::IsSelected("hyper-v-kmp-kdump"))
    {
	// add modules to initrd
	Initrd::AddModule ("hv_blkvsc", "");
	Initrd::AddModule ("hv_netvsc", "");
	Initrd::AddModule ("hv_storvsc", "");
	Initrd::AddModule ("hv_vmbus", "");

	y2milestone("Added HyperV PV drivers to initrd, configured drivers: %1", Initrd::ListModules());

	// it also need to be added to MODULES_LOADED_ON_BOOT
        Kernel::AddModuleToLoad ("hv_storvsc");
        Kernel::AddModuleToLoad ("hv_netvsc");
	y2milestone ("Added hv_storvsc and hv_netvsc to modules loaded on boot");

    }
    else
    {
	y2milestone("No hyper-v-kmp-* package is selected for installation, skipping HyperV PV driver installation");
    }
}


    /**
     *  Write a fake mtab to the target system since some %post scripts might
     *  need it.
     */
    define void fake_mtab () ``{
	y2milestone("Copying /etc/mtab to the target system...");

	string tmpdir = (string) SCR::Read (.target.tmpdir);

	string mtabname = "/etc/mtab";
	string mtab = (string) WFM::Read(.local.string, mtabname);

	// remove non-existing mount points
	list<string> mtab_lines = splitstring(mtab, "\n");

	mtab_lines = filter(string mtab_line, mtab_lines,
	    {
		// parse the line, get the directory name
		string dir = regexpsub(mtab_line, "^[^ \t]+[ \t]+([^ \t]*)[ \t]+", "\\1");

		if (dir != nil)
		{
		    // check if the directory exists
		    y2debug("Checking directory %1", dir);

		    integer exit_status = (integer)WFM::Execute(.local.bash, sformat("ls -d '%1'", String::Quote(dir)));
		    if (exit_status != 0)
		    {
			y2warning("Excluding nonexisting directory %1", dir);
			return false;
		    }
		}

		return true;
	    }
	);

	// join back the lines
	mtab = mergestring(mtab_lines, "\n");
	y2milestone("Target /etc/mtab file: %1", mtab);

	SCR::Write(.target.string, tmpdir + "/mtab", mtab);
	SCR::Execute (.target.bash, "/bin/cat "
		      + "'" + String::Quote (tmpdir + "/mtab") + "'"
		      + " | /bin/sed \"s: " + Installation::destdir
		      + "/: /:\"| /bin/sed \"s: " + Installation::destdir
		      + ": /:\" "
		      + "> '" + String::Quote (Installation::destdir) + "'" + mtabname);

    }


    /**
     *  Remove some old junk.
     */
    define void remove_stuff () ``{

	// remove old junk, script is in yast2-update
	SCR::Execute (.target.bash, Directory::ybindir + "/remove_junk " +
		      "'" + String::Quote (Installation::destdir) + "'");

	// possibly remove /usr/share/info/dir
	if (!Pkg::TargetFileHasOwner ("/usr/share/info/dir"))
	{
	    SCR::Execute (.target.remove, Installation::destdir + "/usr/share/info/dir");
	}

    }


    /**
     *  Handle the backup.
     */
    define void backup_stuff () {

	if (Installation::update_backup_modified)
	{
	    Pkg::CreateBackups (true);
	    Pkg::SetBackupPath (Installation::update_backup_path);
	    SCR::Write (.target.string, Installation::destdir + "/var/lib/YaST2/backup_path",
			Installation::update_backup_path);
	}
	else
	{
	    Pkg::CreateBackups (false);
	    SCR::Execute (.target.remove, Installation::destdir + "/var/lib/YaST2/backup_path");
	}

	// Removing all old backups
	if (Installation::update_remove_old_backups)
	{
	    y2milestone ("Removing old backups *-*-*.tar.{gz,bz2} from %1", Installation::update_backup_path);
	    SCR::Execute (.target.bash, "cd '" + String::Quote (Installation::destdir) + "'; " +
			    "/bin/rm -f " + Installation::update_backup_path + "/*-*-*.tar.{gz,bz2}");
	}

	// timestamp
	string date = timestring ("%Y%m%d", time(), false);

	if (true)
	{
	    y2milestone ("Creating backup of %1", Directory::logdir);

	    string filename = "";
	    integer num = 0;

	    while (num < 42)
	    {
		filename = Installation::update_backup_path + "/YaST2-" + date + "-" +
		    sformat ("%1", num) + ".tar.gz";
		if (SCR::Read (.target.size, Installation::destdir + filename) == -1)
		    break;
		num = num + 1;
	    }

	    if (SCR::Execute (.target.bash, "cd '" + String::Quote (Installation::destdir) + "'; " +
			      "/bin/tar czf ." + filename + " " + "var/log/YaST2") != 0)
	    {
		y2error ("backup of %1 to %2 failed", Directory::logdir, filename);
		// an error popup
		Popup::Error (sformat (_("Backup of %1 failed. See %2 for details."),
				       Directory::logdir, Directory::logdir + "/y2log"));
	    }
	    else
	    {
		SCR::Execute (.target.bash, "cd '" + String::Quote (Installation::destdir) + "'; " +
		              "/bin/rm -rf var/log/YaST2/*");
	    }
	}

	if (Installation::update_backup_sysconfig)
	{
	    // backup /etc/sysconfig
	    if (SCR::Read (.target.size, Installation::destdir + "/etc/sysconfig") > 0)
	    {
		y2milestone ("backup of /etc/sysconfig");

		string filename = "";
		integer num = 0;

		while (num < 42)
		{
		    filename = Installation::update_backup_path + "/etc.sysconfig-" + date + "-" +
			sformat ("%1", num) + ".tar.gz";
		    if (SCR::Read (.target.size, Installation::destdir + filename) == -1)
			break;
		    num = num + 1;
		}

		if (SCR::Execute (.target.bash, "cd '" + String::Quote (Installation::destdir) + "'; " +
				  "/bin/tar czf ." + filename + " " + "etc/sysconfig") != 0)
		{
		    y2error ("backup of %1 to %2 failed", "/etc/sysconfig", filename);
		    // an error popup
		    Popup::Error (sformat (_("Backup of %1 failed. See %2 for details."),
					   "/etc/sysconfig", Directory::logdir + "/y2log"));
		}
	    }
	    // backup of /etc/rc.config*
	    else if (SCR::Read (.target.size, Installation::destdir + "/etc/rc.config") > 0 &&
		     SCR::Read (.target.size, Installation::destdir + "/etc/rc.config.d") > 0)
	    {
		y2milestone ("backup of /etc/rc.config.d");

		string filename = "";
		integer num = 0;

		while (num < 42)
		{
		    filename = Installation::update_backup_path + "/etc.rc.config-" + date + "-" +
			sformat ("%1", num) + ".tar.gz";
		    if (SCR::Read (.target.size, Installation::destdir + filename) == -1)
			break;
		    num = num + 1;
		}

		if (SCR::Execute (.target.bash, "cd '" + String::Quote (Installation::destdir) + "'; " +
				  "/bin/tar czf ." + filename + " " +
				  "etc/rc.config etc/rc.config.d") != 0)
		{
		    y2error ("backup of %1 to %2 failed", "/etc/rc.config", filename);
		    // an error popup
		    Popup::Error (sformat (_("Backup of %1 failed. See %2 for details."),
					   "/etc/rc.config", Directory::logdir + "/y2log"));
		}
	    }
	}

	// Backup /etc/pam.d/ unconditionally
	// bnc #393066
	if (Mode::update()) {
	    string filename = "";
	    integer num = 0;

	    while (num < 42) {
		filename = Installation::update_backup_path + "/etc.pam.d-" + date + "-" + sformat ("%1", num) + ".tar.gz";

		// avoid from filename conflicts
		if (! FileUtils::Exists (Installation::destdir + filename))
		    break;
		num = num + 1;
	    }

	    string what_to_backup = "etc/pam.d etc/security etc/securetty etc/environment";

	    // enters the Installation::destdir
	    // and creates backup of etc/pam.d directory in Installation::update_backup_path
	    string cmd = sformat (
		"cd '%1'; /bin/tar --ignore-failed-read -czf '.%2' %3",
		String::Quote (Installation::destdir),
		String::Quote (filename),
		what_to_backup
	    );

	    y2milestone ("Creating backup of %1 in %2", what_to_backup, Installation::destdir + filename);

	    if (SCR::Execute (.target.bash, cmd) != 0) {
		y2error ("backup command failed: %1", cmd);
		// an error popup
		Popup::Error (sformat (_("Backup of %1 failed. See %2 for details."),
		    "/etc/pam.d", Directory::logdir + "/y2log"));
	    }
	}
    }

    /**
     * Create /etc/mdadm.conf if it does not exist and it's needed
     * bugs: #169710 and #146304
     */
    void createmdadm () {
	string mdamd_configfile = Installation::destdir + "/etc/mdadm.conf";
	// File exists, no need to create it
	if (FileUtils::Exists(mdamd_configfile)) {
	    y2milestone("File /etc/mdadm.conf exists, skipping creation...");
	    return;
	}

	// get the current raid configuration
	map out = (map) SCR::Execute (.target.bash_output,
	    "chroot '" + String::Quote (Installation::destdir) + "' " +
	    "mdadm -Ds");
	if (out["exit"]:-1 != 0) {
	    y2error ("Error occurred while getting raid configuration: %1", out);
	    return;
	}
	// There's no current raid configuration, no reason to create that file, bug #169710
	if (out["stdout"]:"" == "") {
	    y2milestone("No raid is currently configured, skipping file creation...");
	    return;
	}
	    
	// File format defined in bug #146304
	string mdadm_content = "DEV partitions\n" +
	    out["stdout"]:"" + "\n";

	y2milestone ("/etc/mdadm.conf doesn't exist, creating it");
	if (! (boolean) SCR::Write (.target.string, mdamd_configfile, mdadm_content)) {
	    y2error ("Error occurred while creating /etc/mdadm.conf with content '%1'", mdadm_content);
	}
    }


    /**
     *  Load all network modules.  The package sysconfig requires this during
     *  update.
     */
    define void load_network_modules ()
    {
	list <map> cards = (list <map>) SCR::Read (.probe.netcard);

	foreach (map card, cards,
	{
	    list <map> drivers = card["drivers"]:[];

	    boolean one_active = false;

	    foreach (map driver, drivers,
	    {
		if (driver["active"]:false)
		    one_active = true;
	    });

	    if (!one_active)
	    {
		string name = drivers[0, "modules", 0, 0]:"";
		if (name != "")
		    ModuleLoading::Load (name, "", "Linux", "",
					 Linuxrc::manual (), true);
	    }
	});
    }

    /**
     * Calls a local command and returns if successful
     */
    define boolean LocalCommand (string command) {
	map cmd = (map) WFM::Execute (.local.bash_output, command);
	y2milestone ("Command %1 returned: %2", command, cmd);

	if (cmd["exit"]:-1 == 0) {
	    return true;
	} else {
	    if (cmd["stderr"]:"" != "") y2error ("Error: %1", cmd["stderr"]:"");
	    return false;
	}
    }

    if (!Mode::update ()) {
	// fake mtab for rpm post-scripts
	fake_mtab ();
    }

    // Feature #301903, bugzilla #244937
    if (Mode::update()) {
	// "/" means updating the running system, bugzilla #246389
	if (Installation::destdir == "/") {
	    // When upgrading system, remove devs.rpm just from rpm database
	    LocalCommand (
		"/bin/rpm -q 'devs' && /bin/rpm --nodeps --justdb -e 'devs'"
	    );
	// normal upgrade
	} else {
	    // When upgrading system, remove devs.rpm if installed
	    LocalCommand (sformat (
		"/bin/rpm --root '%1' -q 'devs' && /bin/rpm --nodeps --root '%1' -e 'devs'",
		String::Quote (Installation::destdir)
	    ));

	    // Mount (bind) the current /dev/ to the /installed_system/dev/
	    LocalCommand (sformat (
		"/bin/rm -rf '%1/dev/' && /bin/mkdir -p '%1/dev/' && /bin/mount -v --bind '/dev/' '%1/dev/'",
		String::Quote (Installation::destdir)
	    ));
	}
    }

    // installation, for instance...
    if (!Mode::update ())
    {
	// make some directories
	SCR::Execute(.target.mkdir, Installation::destdir + "/etc");
	SCR::Execute(.target.mkdir, Installation::destdir + Directory::logdir);

        if (Installation::dirinstall_installing_into_dir) {
            string template_dir= "/var/adm/fillup-templates";

	    // hack 'pre-req' cyclic dependency between bash, aaa_base, and perl
	    foreach (string filename, ["passwd", "group", "shadow"], {
		string filename_copy_to = sformat ("%1/etc/%2", Installation::destdir, filename);

		if (FileUtils::Exists (filename_copy_to)) {
		    y2milestone ("File %1 exists, not rewriting", filename_copy_to);
		} else {
		    filename = sformat ("%1/%2.aaa_base", template_dir, filename);
		    y2milestone ("Copying %1 to %2", filename, filename_copy_to);
		    SCR::Execute (.target.bash,
			sformat (
			    // BNC 441829: /etc/shadow can be symlink
			    // copying the file contents
			    // preserving the original file access permissions
			    "cp --dereference --copy-contents '%1' '%2'",
			    String::Quote (filename), String::Quote (filename_copy_to)
			)
		    );
		}
	    });

        } else {
	    y2milestone ("Copying users/groups information from the inst-sys to %1", Installation::destdir);
	    // @see bnc #381227
	    // @see bnc #440430
	    // files might have been copied already from image
	    foreach (string filename, ["/etc/passwd", "/etc/shadow", "/etc/group"], {
		string filename_copy_to = sformat ("%1/%2", Installation::destdir, filename);

		if (FileUtils::Exists (filename_copy_to)) {
		    y2milestone ("File %1 exists, not rewriting", filename_copy_to);
		} else {
		    y2milestone ("Copying %1 to %2", filename, filename_copy_to);
		    SCR::Execute (.target.bash,
			sformat (
			    // BNC 441829: /etc/shadow can be symlink
			    // copying the file contents
			    // preserving the original file access permissions
			    "cp --dereference --copy-contents '%1' '%2'",
			    String::Quote (filename), String::Quote (filename_copy_to)
			)
		    );
		}
	    });
        }

	// fake mtab
	fake_mtab ();
	AcpiToInitrd ();

	// F#302660: System installation and upgrade workflow: kernel %post
	// calling ins_bootloader write all config files for bootloader
//	if (Stage::initial ())
//    	{
// call it always, it handles installation mode inside
	   WFM::CallFunction ("inst_bootloader", WFM::Args ());
//	}
    }
    else
    {
        if (Stage::normal())
        {
            import "Kernel";
            string kernel = Kernel::ComputePackage ();
            Kernel::SetInformAboutKernelChange(Pkg::IsSelected (kernel));

            SCR::Execute (.target.mkdir, Installation::destdir + Installation::update_backup_path);
            backup_stuff ();
	    createmdadm();
        }
        else 
        {
	    // disable all repositories at the target
	    Pkg::TargetDisableSources();

            // make some directories
            SCR::Execute (.target.mkdir, Installation::destdir + Directory::logdir);
            SCR::Execute (.target.mkdir, Installation::destdir + Installation::update_backup_path);

            // backup some stuff
            backup_stuff ();

            // remove some stuff
            // do not remove when updating running system (#49608)
            remove_stuff ();

            // set update mode to yes
            SCR::Write(.target.string, Installation::destdir + "/var/lib/YaST2/update_mode", "YES");
            SCR::Execute (.target.remove, Installation::destdir + "/var/lib/YaST/update.inf");

            // check passwd and group of target
            SCR::Execute (.target.bash, "/usr/lib/YaST2/bin/update_users_groups " +
                    "'" + String::Quote (Installation::destdir) + "'");

	    // create /etc/mdadm.conf if it does not exist
	    createmdadm();

            // load all network modules
            load_network_modules ();

            // perform actions needed by various bootloaders before packages
            // get updated
            // Bootloader::PreUpdate ();
	    // -- this function call does NOTHING!            
        }
	AcpiToInitrd ();
    }

    // add Xen and HyperV PV drivers to initrd
    XenPVToInitrd();
    HyperVPVToInitrd();

    if (Stage::initial ())
    {
	// see bug 20627 for original purpose of this line,
	// bug 172149 why it was moved here
	SCR::Execute (.target.bash, "/bin/echo \"/etc/nothing\" >/proc/sys/kernel/modprobe");
    }

    return `next;
}

ACC SHELL 2018