home *** CD-ROM | disk | FTP | other *** search
- /**
- * Module: installation.ycp
- *
- * Authors: Mathias Kettner (kettner@suse.de)
- *
- * Purpose: Setup the UI and define macros for the
- * installation dialog, general framework, ...
- * Describing and calling all submodules, depending on
- * the installation should be started or continued.
- *
- * user_settings: add: continue_mode
- * used: language
- * add: targets
- * add: architecture
- * add: boot_mode
- * add: has_floppy
- * add: mouse_id
- * add: mouse
- * used: automode
- * used: instmode
- * used: keyboard
- *
- */
- {
- string default_language = "en";
- string default_architecture = "i386";
-
- /*
- * test command line arguments for test mode and continue mode
- */
-
- integer arg_n = size(Args()) - 1;
- boolean test_mode = false;
- boolean continue_mode = false;
-
- while (arg_n >= 0) {
- if (Args(arg_n) == .test) {
- test_mode = true;
- }
-
- if (Args(arg_n) == .continue) {
- continue_mode = true;
- }
-
- arg_n = arg_n - 1;
- }
-
-
- /*
- * Define macros for use in the submodules.
- */
-
- /*
- * Define a macro that looks up a localized string in a language map
- * of the form $[ "default" : "Defaultstring", "de" : "German....", ...]
- */
-
- define translate(map lmap, string lang) ``{
- string|void t = lookup(lmap, lang, nil);
- if (t == nil && size(lang) > 2) t = lookup(lmap, substring(lang, 0, 2), nil);
- if (t == nil) t = lookup(lmap, "default", nil);
- return t;
- };
-
-
- /*
- * Fallback in case the first parameter is no language map but a string
- */
-
- define translate(string s, string lang) ``{
- return s;
- };
-
-
- integer current_stage = -1;
-
- /*
- * Set the wizard installation stage, i.e. the indicator of how
- * far the installation has progressed yet.
- * Sets the wizard header image accordingly.
- */
-
- define SetWizardStage( integer stage, boolean force ) ``{
-
- if ( stage == current_stage && ! force ) // cache
- {
- y2log( .debug, "installation", 666, sformat("Stage %1 cached - doing nothing", stage ) );
- return;
- }
-
- y2log( .debug, "installation", 666, sformat("Setting stage to %1", stage ) );
-
- // Set the header image according to the stage
- UI( `SetWizardImage( ReadByteblock( sformat( "/lib/YaST2/images/stage%1.png", stage ) ) ) );
-
- // Cache the current stage
- current_stage = stage;
- };
-
- // ==================================================================================
-
- /*
- * Set the X mouse as specified.
- * Uses the 'mset' command (originally from SaX).
- *
- * used by inst_startup and inst_mouse
- */
-
- define SetXMouse( map mouse_params ) ``{
- string emul3 = "off";
-
- if ( lookup ( mouse_params, "emul3", false ) )
- emul3 = "on";
-
- // mset <device> <mousetype> <baudrate> <samplerate> <resolution> <buttons> <emul3> <timeout> <chordmiddle>
- // [ClearDTR] [ClearRTS] [ReOpen]
- // Example: mset /dev/psaux PS/2 1200 60 0 3 off 50 off
-
-
- string mset_command = sformat ( "/lib/YaST2/bin/mset %1 %2 1200 60 0 3 %3 50 off",
- lookup ( mouse_params, "device", "/dev/mouse" ),
- lookup ( mouse_params, "xf86", "PS/2" ),
- emul3 );
-
- if ( test_mode )
- y2log( .milestone, "inst_mouse", 1,
- "Test mode - NOT setting X mouse - would have called:\n" + mset_command );
- else {
- integer result = Shell( mset_command, $["DISPLAY" : ":0.0"] );
- }
- };
-
- // ==================================================================================
-
-
- /*
- * for PPC: convert pdisk output to fdisk output format
- */
-
- define pdisk2target (list pdisk_data) ``{
- list partitions = [];
-
- foreach (`pentry, pdisk_data, ``{
- // make partition entry map, start with dummy fsid entry
- map part = $["fsid":0, "type":`pdisk];
-
- if (lookup (pentry, "type") == nil) continue;
-
- string fstype = lookup (pentry, "type");
-
- if (lookup (pentry, "name") != nil)
- fstype = fstype + " (" + lookup (pentry, "name") + ")";
-
- // fstype
- part = add (part, "fstype", fstype);
- // nr
- part = add (part, "nr", lookup (pentry, "nr"));
-
- part = add (part, "region", [(lookup (pentry, "base") / 64), (lookup (pentry, "length") / 64)]);
-
- partitions = add (partitions, part);
-
- }); // foreach
-
- return partitions;
-
- }; // pdisk2target
-
-
- // ------------------------------------------------------
- // check partitions for given disk (as path, i.e. '.sda')
- // returns list as specified in README.target_partition
- //
-
- define check4partitions (path diskpath, string architecture) ``{
-
- list partitions = SCR(`Read(.disk + diskpath + .partitions));
-
- // fdisk may fail on ppc, check with pdisk in this case
-
- if ((partitions == []) && (architecture == "ppc")) {
- partitions = pdisk2target (SCR(`Read(.pdisk + diskpath)));
- }
-
- if (test_mode) y2log (.milestone, "check4partitions", 1, "partitions " + partitions);
-
- return partitions;
- };
-
- // ==================================================================================
-
- /*
- * Define a macro that transforms information about all partitions ( from
- * user_settings( "targets" ) ) into a list(map) with information about partitions
- * which are available for installation, e.g.:
- *
- * [$["free":1625676, "name":"/boot", "used":0], $["free":2210406, "name":"/", "used":0]]
- *
- * Please note: in 6.4 there isn't any information about used space, so "used" at begin
- * of installation is initialized with zero; size "free" in KBytes
- *
- */
-
- define get_partition_info( map targets, boolean remove_slash ) ``{
-
- list(map) target_partitions = [];
- integer spare_percentage = 22; // percentage of free spare space on every partition
- integer min_spare = 2048; // minimum free space ( 2 MB )
-
- foreach( `disk, `diskinfo, targets, ``{
-
- list part_info = lookup( diskinfo, "partitions" );
-
- foreach( `part, part_info, ``{
- integer free_size = 0;
- integer spare_size = 0;
-
- if ( lookup( part, "mount", nil ) != nil && substring( lookup( part, "mount"), 0, 1 ) == "/" )
- {
- if ( lookup( part, "create", nil ) == true || lookup( part, "delete", nil ) == false ||
- ( lookup( part, "create", nil) == nil && lookup( part, "delete", nil ) == nil ) )
- {
- _debug( "get_partition_info: adding partition: ", part );
-
- // get free space ("region", second value ) * cyl_size in KBytes
- free_size = select( lookup( part, "region" ), 1 ) * (lookup( diskinfo,"cyl_size")/1024);
-
- spare_size = (free_size*spare_percentage)/100;
-
- if ( spare_size < min_spare )
- {
- spare_size = min_spare;
- }
- free_size = free_size - spare_size;
-
- y2log( .milestone, "installation", 1, sformat( "available partition: mount: %1, free: %2 KB",
- lookup( part, "mount" ), free_size) );
- if ( !remove_slash)
- {
- target_partitions = add ( target_partitions, $["name":lookup( part, "mount" ), "used":0, "free":free_size,
- "region":lookup( part, "region" ), "used_fs":lookup( part, "used_fs" ) ] );
- }
- else
- {
- string part_name = "";
- string mount_name = lookup( part, "mount");
-
- if ( mount_name != "/" )
- {
- part_name = substring( mount_name, 1, size(mount_name) );
- }
- else
- {
- part_name = mount_name;
- }
-
- target_partitions = add ( target_partitions, $["name":part_name, "used":0, "free":free_size,
- "region":lookup( part, "region" ), "used_fs":lookup( part, "used_fs" ) ] );
-
- }
-
- }
- }
- } );
- } );
-
- _debug( "get_partition_info: ", target_partitions );
-
- return ( target_partitions );
- };
-
-
- UI(``{
- /**
- * Create a typical installation wizard dialog.
- */
- OpenDialog( `opt(`defaultsize),
- `VBox(
- `ReplacePoint( `id(`image ), `Image( `suseheader, "SuSE") ),
- `HBox(
- `HWeight( 30, `ReplacePoint( `id(`helpSpace), `RichText(`id(`help), ""))),
- `HWeight( 70, `VBox(
- `Left(`Heading(`id(`title), _("YaST2\nInitializing ..."))),
- `HVCenter(`ReplacePoint(`id(`contents), `Empty())),
- `HBox(
- // back pushbutton: the user input is ignored and the last dialog is called
- `PushButton(`id(`back), _("&Back")),
- `HStretch(),
- `ReplacePoint( `id(`rep_next),
- // next pushbutton: the user input is checked and the next dialog is called
- `PushButton(`id(`next), _("&Next"))
- )
- )
- )
- )
- )
- )
- );
-
-
- /*
- * Define how the general framework for the installation wizard should
- * look like. This Macro creates and show a dialog.
- */
-
- define SetWizardContents(string title, term contents, string helptext,
- boolean has_back, boolean has_next) ``{
- ChangeWidget(`id(`back), `Enabled, has_back);
- ChangeWidget(`id(`next), `Enabled, has_next);
- ChangeWidget(`id(`help), `Value, helptext);
- ChangeWidget(`id(`title), `Value, title);
- ReplaceWidget(`id(`contents), contents);
- SetFocus( `id(`next) );
- };
-
-
- /*
- * Change the image at the top of the window.
- */
- define SetWizardImage(byteblock|void imagedata) ``{
- if (imagedata == nil)
- {
- y2log(.warning, "installation", 1, "SetWizardImage(): Invalid image - using fallback" );
- ReplaceWidget( `id(`image), `Image(`suseheader, "SuSE") );
- }
- else
- ReplaceWidget( `id(`image), `Image(imagedata, "SuSE") );
- };
-
- /*
- * Replace the wizard help subwindow with a custom widget.
- * Call this BEFORE SetWizardContents() to avoid geometry
- * management problems!
- *
- * Remember to restore the help subwindow with
- * RestoreWizardHelp() before any other module is called!
- */
- define ReplaceWizardHelp(term contents) ``{
- ReplaceWidget(`id(`helpSpace), contents);
- };
-
-
- /*
- * Restore the wizard help subwindow after ReplaceWizardHelp().
- */
- define RestoreWizardHelp(string helpText) ``{
- ReplaceWidget(`id(`helpSpace), `RichText(`id(`help), helpText ) );
- };
-
-
- /*
- * Replace the wizard 'next' button with a custom widget.
- */
- define ReplaceWizardNextButton(term contents) ``{
- ReplaceWidget(`id(`rep_next), contents);
- };
-
-
- /*
- * Restore the wizard 'next' button after ReplaceWizardNextButton().
- */
- define RestoreWizardNextButton() ``{
- ReplaceWidget(`id(`rep_next),
- // next pushbutton: the user input is checked and the next dialog is called
- `PushButton(`id(`next), _("&Next") )
- );
- };
-
- /*
- * Small dialog that has a next, cancel and back button that
- * appears, if one of the submodules does not work. This is
- * useful during development.
- */
- // DEBUG
- define ModuleError(string text) ``{
- OpenDialog(`opt(`decorated),
- `VBox(`Label(text),
- `HBox(`PushButton(`id(`back), "&Back"),
- `PushButton(`id(`cancel), "&Cancel"),
- `PushButton(`id(`again), "&Again"),
- `PushButton(`id(`next), "&Next"))));
- any r = UserInput();
- CloseDialog();
- return r;
- };
-
- /*
- * Displays a message to the user in a small dialog with an OK
- * button.
- */
-
- define DisplayMessage(string message) ``{
- // ok pushbutton: confirm the dialog
- OpenDialog(`opt(`decorated),
- `VBox(`Label(message),
- `PushButton(`opt(`default), _("&OK"))));
- UserInput();
- CloseDialog();
- };
-
- /**
- * Displays a message with timeout to the user in a small dialog
- * with an OK
- * button.
- */
-
- define DisplayTimedMessage(string message, integer seconds) ``{
- // ok pushbutton: confirm the dialog
- OpenDialog(`opt(`decorated),
- `VBox(`Label(message),
- `HCenter(`Label(`id(`remaining_time), ""+seconds)),
- `HBox(`PushButton(`id(`timed_stop), _("&Stop")),
- `PushButton(`id(`timed_ok), `opt(`default), _("&OK")))));
- sleep (1000);
- any which_input = `empty;
- while (seconds > 0) {
- which_input = PollInput();
- if (which_input == `timed_ok)
- break;
- if (which_input == `timed_stop) {
- while (which_input == `timed_stop)
- which_input = UserInput();
- break;
- }
- sleep (1000);
- seconds = seconds - 1;
- ChangeWidget (`id(`remaining_time), `Value, ""+seconds);
- }
- CloseDialog();
- };
-
- /*
- * Are your sure?
- */
-
- define YesOrNo(any message, string yes_button_message, string no_button_message) ``{
- OpenDialog(`opt(`decorated),
- `VBox(`Label(message),
- `HBox(
- `PushButton(`id(`yes), `opt(`default), yes_button_message),
- `HStretch(),
- // no pushbutton: the dialog is not confirmed
- `PushButton( no_button_message )
- )
- )
- );
- any ret = UserInput();
- CloseDialog();
- return (ret == `yes);
- };
-
-
- // Return a pretty description of a byte count, with two fraction digits
- // and using KB, MB or GB as unit as appropriate.
- define size_text (integer bytes) ``{
- float whole = tofloat (bytes) / 1024.0;
- // KiloByte abbreviated
- string unit = _("KB");
- if (whole > 1024.0)
- {
- whole = whole / 1024.0;
- // MegaByte abbreviated
- unit = _("MB");
- if (whole > 1024.0)
- {
- whole = whole / 1024.0;
- // GigaByte abbreviated
- unit = _("GB");
- }
- }
- return tostring (whole, 2) + " " + unit;
- };
-
- /*
- * Small dialog that has a cancel and continue button that
- * appears just befor the video mode is tested.
- */
- define ContinueCancel(string message,
- string continue_button_message,
- string cancel_button_message ) ``{
- OpenDialog(`opt(`decorated),
- `VBox(`Label(message),
- `HBox(
- `PushButton(`id(`continue), `opt(`default),continue_button_message),
- `PushButton(`id(`cancel), cancel_button_message)
- )
- )
- );
- any r = UserInput();
- CloseDialog();
- return ( r == `continue );
- };
- });
-
- string mountpoint = "/var/adm/mount";
- map user_settings = $["mountpoint":mountpoint];
-
- /*
- * The first argument to this module decides, if the installation
- * should be _started_ or _continued_. If the first argument
- * is given and is .continue, we have a different list of modules
- */
- list modules = [];
- integer m = 0; // current module
-
-
- if (test_mode) {
- user_settings = add(user_settings, "test_mode", true);
- y2log(.warning, "installation", 1, "***** Test mode enabled *****");
- }
-
- if (continue_mode) {
- modules =
- [
- [ `inst_rpmcopy (false, false), 7 ],
- [ `inst_config_x11 (true, true), 7 ],
- [ `inst_suseconfig (false, false), 8 ],
- [ `inst_ask_config (false, true), 8 ]
- ];
-
- // Read the final settings of the first part of the installation.
- user_settings = Read("/var/lib/YaST2/settings.ycp");
- // Add marker for the second pass.
- user_settings = add(user_settings, "continue_mode", true);
- UI(`SetLanguage(lookup (user_settings, "language", default_language)));
- // UI(`SetKeyboard(lookup (user_settings, "keyboard", "english-us")));
- }
- else {
- /*
- * Try to load user_settings from disk.
- * If none are found, we simply use an empty map.
- */
- Shell("mount /dev/fd0 /floppy -t msdos");
- any r = ReadY2("settings.ycp");
- if (is(r, map)) {
- user_settings = r;
- _debug("Read user settings: ", user_settings);
- }
- Shell("umount /floppy");
-
- modules =
- [
- // module back next stage
- [ `inst_language (false, true), 1 ],
- [ `inst_mouse (true, true), 1 ],
- [ `inst_environment (true, true), 1 ],
- [ `inst_mode (true, true), 2 ],
- [ `inst_target_selection (true, true), 2 ],
- [ `inst_target_part (true, true), 2 ],
- [ `inst_custom_part (true, true), 2 ],
- [ `inst_sw_select (true, true), 3 ],
- [ `inst_lilo_info (true, true), 4 ],
- [ `inst_user (true, true), 5 ],
- [ `inst_root (true, true), 5 ],
- [ `inst_doit (true, true), 6 ],
- [ `inst_prepdisk (false, false), 6 ],
- [ `inst_rpmcopy (false, false), 6 ],
- [ `inst_finish (false, false), 6 ]
-
- ];
-
-
- /*
- * Show warning, if existent.
- */
-
- string warnfile = "/var/adm/mount/suse/setup/descr/common.war";
- string|void warning = ReadString(warnfile);
- if (warning != nil) {
- UI(`DisplayMessage(warning));
- }
-
- // pass targets to user_settings
-
- if ( ! test_mode ) {
- SetWizardStage (1, false);
- CallFunction (`inst_startup ());
- // inst_startup might return `cancel if no disks were found
- // we allow this for now (diskless client installation ?!)
- // if (xxx == `cancel) { return `cancel; // no disks found !! }
- }
-
- if (lookup(user_settings, "automode") == .doit) m = 10;
- }
-
-
- // All settings the user does are saved into a map. The submodules
- // are called as functions and thus have access to this variable.
- // They return `next, `back, `cancel, `again or `auto.
- // A submodule that can't be loaded (syntax error) returns nil.
-
- any former_result = nil;
-
- while ((m >= 0) && (m < size(modules)))
- {
- list module_info = select( modules, m);
- term argterm = select( module_info, 0);
- integer stage = select( module_info, 1);
-
- // Tell modules if we were going backwards.
- argterm = add(argterm, former_result == `back);
-
- // Regenerate the text of the buttons in order to make language change active
- UI(`ChangeWidget(`id(`back), `Label, _("&Back")));
- UI(`ChangeWidget(`id(`next), `Label, _("&Next")));
-
- SetWizardStage(stage, false);
- symbol|void result = CallFunction(argterm);
-
- // If the module return nil, something basic went wrong.
- // We show a stub dialog instead.
-
- if (result == nil) {
- any r = nil;
- r = UI(`ModuleError(("The module " + symbolof(argterm)) + " does not work."));
- if (r == `next) m = m + 1;
- else if (r == `back) m = m - 1;
- else if (r != `again) return nil;
- else continue;
- }
-
- if (result == `next) m = m + 1;
- else if (result == `back) m = m - 1;
- else if (result == `cancel) return `cancel;
- else if (result == `again) continue; // Show same dialog again
- else if (result == `auto)
- {
- if (former_result != nil) {
- if (former_result == `next) m = m + 1;
- else if (former_result == `back) m = m - 1;
- }
- continue;
- }
- former_result = result;
- }
- UI(`CloseDialog());
- y2log( .milestone, "installation", 1, "all done : "+m);
- if (m <= -1) return `back;
- else return `next;
- }
-