home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / boot / i386 / root / usr / share / YaST2 / modules / AutoinstStorage.ycp < prev    next >
Text File  |  2006-11-29  |  29KB  |  786 lines

  1. /**
  2.  * File:    modules/AutoinstStorage.ycp
  3.  * Module:    Auto-Installation
  4.  * Summary:    Storage
  5.  * Authors:    Anas Nashif <nashif@suse.de>
  6.  *
  7.  * $Id: AutoinstStorage.ycp 33388 2006-10-13 10:05:55Z ug $
  8.  */
  9. {
  10.     module "AutoinstStorage";
  11.     textdomain "autoinst";
  12.  
  13.     import "Storage";
  14.     import "RootPart";
  15.     import "Partitions";
  16.     import "FileSystems";
  17.     import "Summary";
  18.     import "Storage";
  19.     import "Partitions";  
  20.     import "Popup";
  21.  
  22.     include "partitioning/partition_defines.ycp";
  23.  
  24.     // Read existing fstab and format partitions, but dont create anything
  25.     // Use same mountpoints etc.
  26.     global boolean read_fstab = false;
  27.  
  28.     // Fstab options
  29.     global map fstab = $[];
  30.  
  31.     // Show warning for /boot on raid
  32.     global boolean BootRaidWarning = true;
  33.  
  34.     // Show warning for /boot on lvm
  35.     global boolean BootLVMWarning = true;
  36.  
  37.     // Show warning for /boot cyl <1024
  38.     global boolean BootCylWarning = true;
  39.  
  40.     // Partition plan as parsed from control file
  41.     global list<map> AutoPartPlan = [];
  42.  
  43.     // Prepared target map from parsed data
  44.     global map<string, map> AutoTargetMap = $[];
  45.  
  46.     /* default value of settings modified */
  47.     global boolean modified = false;
  48.  
  49.     global map<string,list> raid2device = $[];
  50.  
  51.     /**
  52.      * Function sets internal variable, which indicates, that any
  53.      * settings were modified, to "true"
  54.      */
  55.     global define void SetModified ()
  56.     {
  57.         y2milestone("SetModified");
  58.         modified = true;
  59.     }
  60.  
  61.     /**
  62.      * Functions which returns if the settings were modified
  63.      * @return boolean  settings were modified
  64.      */
  65.     global define boolean GetModified ()
  66.     {
  67.         return modified;
  68.     }
  69.  
  70.  
  71.     include "autoinstall/autopart.ycp";
  72.     include "autoinstall/autoinst_dialogs.ycp";
  73.  
  74.     global define string find_first_disk() {
  75.         map <string, map> initial_target_map = Storage::GetTargetMap();
  76.         y2milestone("Target map: %1", initial_target_map );
  77.  
  78.         string mbr_disk = "";
  79.         foreach (string device, map disk, initial_target_map, ``{
  80.             if (disk["bios_id"]:"" == "0x80")
  81.             {
  82.                 y2milestone ("disk with bios_id 0x80: %1", device);
  83.                 mbr_disk = device;
  84.             }
  85.         });
  86.  
  87.         /* device guessing code enhanced */
  88.         if( mbr_disk == "" ) {
  89.             foreach (string device, map disk, initial_target_map, ``{
  90.                 if( disk["type"]:`x == `CT_DISK ) {
  91.                     y2milestone ("first real disk is: %1", device);
  92.                     mbr_disk = device;
  93.                     break;
  94.                 }
  95.             });
  96.         }
  97.  
  98.         y2milestone("mbr disk: %1", mbr_disk);
  99.         return mbr_disk;
  100.     }
  101.  
  102.     /**
  103.      * Pre-process partition plan and prepare for creating partitions.
  104.      * @return void
  105.      */
  106.     define map<string, map>  set_devices(list<map> storage_config ) {
  107.     y2milestone("entering set_devices with %1",storage_config);    
  108.         boolean first_set = false;
  109.         boolean failed = false;
  110.         map<string, map> auto_targetmap =  listmap (map drive, storage_config, ``{
  111.             string device = "";
  112.             y2milestone("Working on drive: %1", drive);
  113.  
  114.             // FIXME: Check if physical drives > 1
  115.             if (drive["device"]:"" == "ask"  )
  116.             {
  117.                 string dev = DiskSelectionDialog();
  118.                 if (dev != nil)
  119.                 {
  120.                     first_set = true;
  121.                     device = dev;
  122.                 }    
  123.  
  124.                 return  $[device: drive ];
  125.             }
  126.  
  127.             if (!first_set 
  128.                 && ( drive["device"]:"" == ""  
  129.                      || drive["device"]:"" == "ask")
  130.                 )
  131.             {
  132.                 device = Storage::GetPartDisk();
  133.                 y2milestone("device: %1", device );
  134.                 first_set = true;
  135.                 return $[device: drive ];
  136.             }
  137.             else if (drive["device"]:"" != "")
  138.             {    
  139.                 string dev = drive["device"]:"";
  140.                 if (dev == "") {
  141.                     dev = "error";
  142.                     y2error("Missing device name in partitioning plan");
  143.                     failed = true;
  144.                 }
  145.  
  146.                 return $[dev: drive ];
  147.             }
  148.             
  149.         });
  150.  
  151.         if (failed)
  152.             return nil;
  153.         
  154.         auto_targetmap =  mapmap (string device, map d, auto_targetmap, ``{
  155.             // Convert from Old Style
  156.             if (haskey(d, "use"))
  157.             {
  158.                y2milestone("converting from \"use\" to new style: %1", device);
  159.                if (d["use"]:"" == "free") {
  160.                    d["prefer_remove"] = false;
  161.                } else if (d["use"]:"" == "all" ) {
  162.                    d["prefer_remove"] = true;
  163.                } else if (d["use"]:"" == "linux" ) {
  164.                    d["keep_partition_num"] = GetNoneLinuxPartitions(device);
  165.                    d["prefer_remove"] = true;
  166.                } else {
  167.                     list<string> uselist = filter(string s,
  168.                                 splitstring(d["use"]:"", ","), ``(s!=""));
  169.                     y2milestone("uselist: %1", uselist);
  170.                     list<integer> keeplist = [];
  171.                     list<integer> all = GetAllPartitions(device);
  172.                     y2milestone("all list: %1", all);
  173.                     foreach(integer i , all, ``{
  174.                             if (!contains(uselist, sformat("%1", i)))
  175.                                 keeplist=add(keeplist,i);
  176.                         });
  177.                     y2milestone("keeplist: %1", keeplist);
  178.                     d["keep_partition_num"] = keeplist;
  179.                     
  180.                     if (size(keeplist) > 0 )
  181.                         d["prefer_remove"] = true;
  182.                }
  183.             }
  184.             // see if <usepart> is used and add the partitions to <keep_partition_num>
  185.             foreach(map p, d["partitions"]:[], ``{
  186.                     if (p["usepart"]:-1 != -1 ){
  187.                         d["keep_partition_num"] = add(d["keep_partition_num"]:[], p["usepart"]:-1);
  188.                     }
  189.                     });
  190.             d["keep_partition_num"] = toset(d["keep_partition_num"]:[]);
  191.  
  192.             return($[device:d]);
  193.             });
  194.  
  195.         y2milestone("processed autoyast partition plan: %1", auto_targetmap );
  196.         return auto_targetmap;
  197.     }
  198.  
  199.     global define list GetRaidDevices (string dev, map<string,map> tm) {
  200.         list<map> ret = [];
  201.         foreach( string k, map d, tm, ``{
  202.             if( d["type"]:`CT_UNKNOWN == `CT_DISK ) {
  203.                 list tmp = filter( map p, d["partitions"]:[],
  204.                                     ``( p["raid_name"]:"" == dev ) );
  205.                 ret = (list<map>)union( ret, tmp );
  206.             }
  207.         });
  208.         list dlist = maplist( map p, ret, ``{ return p["device"]:""; } );
  209.         y2milestone("GetRaidDevices dlist = %1 and ret = %2", dlist, ret);
  210.         return dlist;
  211.     }
  212.  
  213.     global define void SearchRaids (map<string,map> tm) {
  214.         //raid2device = $[];
  215.         foreach( string k, map d, tm, ``{
  216.             if( d["type"]:`CT_UNKNOWN == `CT_DISK ) {
  217.                 list<map> tmp = filter( map p, d["partitions"]:[],
  218.                                     ``( p["raid_name"]:"" != "" ) );
  219.                 list<string> devMd = maplist( map p, tmp, ``{ return p["raid_name"]:""; } );
  220.                 foreach( string dev, devMd, ``{
  221.                     if( ! haskey( raid2device, dev ) ) {
  222.                         raid2device[dev] = GetRaidDevices(dev,tm);
  223.                     } else {
  224.                         foreach( string k, (list<string>)GetRaidDevices(dev,tm), ``{
  225.                              raid2device[dev] = add(raid2device[dev]:[],k);
  226.                         });
  227.                     }
  228.                 });
  229.             }
  230.         });
  231.         y2milestone("SearchRaids raid2device = %1", raid2device);
  232.     }
  233.  
  234.     /**
  235.      * Dump the settings to a map, for autoinstallation use.
  236.      * @return list
  237.      */
  238.     global define list<map> Export()
  239.     {
  240.         y2milestone("entering Export");
  241.         list<map> clean_drives = maplist(map d,  AutoPartPlan, ``{
  242.             list p = maplist(map part, d["partitions"]:[] , ``{
  243.                 if (haskey(part, "fsid"))
  244.                 {
  245.                     part = remove(part, "fsid");
  246.                 }
  247.                 if (haskey(part, "used_fs")) {
  248.                     part = remove(part, "used_fs");
  249.                 }
  250.                 return part;
  251.             });
  252.             d["partitions"] = p;
  253.  
  254.             // this is to delete the dummy "auto" filled in by UI
  255.             if( haskey(d,"device") && d["device"]:"" == "auto" ) {
  256.                 d = remove(d, "device");
  257.                 y2debug("device 'auto' dropped");
  258.                 
  259.             }
  260.             return d;
  261.         });
  262.  
  263.         return clean_drives;
  264.     }
  265.  
  266.     /**
  267.      * if mountby is used, we will search for the matching
  268.      * partition here.
  269.      * @return list
  270.      */
  271.     global define list<map> mountBy(list<map> settings) {
  272.         map <string, map> tm = Storage::GetTargetMap();
  273.         y2milestone("Storage::GetTargetMap returns %1",tm);
  274.         settings = maplist( map d, settings, ``{
  275.             string device = d["device"]:"";
  276.             d["partitions"] = maplist( map p, d["partitions"]:[], ``{
  277.                 string mountby = "";
  278.                 boolean mountByIsList = false;
  279.                 if( haskey(p, "mountby") ) {
  280.                     if( p["mountby"]:`none == `label ) {
  281.                         mountby = "label";
  282.                     } else if( p["mountby"]:`none == `uuid ) {
  283.                         mountby = "uuid";
  284.                     } else if( p["mountby"]:`none == `path ) {
  285.                         mountby = "udev_path";
  286.                     } else if( p["mountby"]:`none == `id ) {
  287.                         mountByIsList = true;
  288.                         mountby = "udev_id";
  289.                     } else {
  290.                         y2milestone("unknown mountby parameter '%1' will be ignored",p["mountby"]:`none);
  291.                     }
  292.                 }
  293.                 /* reuse partition by "mountby" */
  294.                 if( mountby != "" && p["create"]:true == false ) {
  295.                     string label = p[mountby]:"";
  296.                     y2milestone("mountby found for %1=%2 in part=%3",mountby,label,p);
  297.                     map target = tm[device]:$[];
  298.                     if( device == "" ) {
  299.                         y2milestone("searching for the device by %1",mountby);
  300.                         foreach( string deviceName, map tmp_target, tm, ``{
  301.                             foreach( map targetPart, tmp_target["partitions"]:[], ``{
  302.                                 if( mountByIsList ? (contains(targetPart[mountby]:[], label)):(targetPart[mountby]:"" == label) ) {
  303.                                     target = tmp_target;
  304.                                     device = deviceName;
  305.                                     y2milestone("device=%1 found",device);
  306.                                     break;
  307.                                 }
  308.                             });
  309.                         });
  310.                     }
  311.                     foreach( map targetPart, target["partitions"]:[], ``{
  312.                         if( mountByIsList ? (contains(targetPart[mountby]:[], label)):(targetPart[mountby]:"" == label) ) {
  313.                             y2milestone("%1 found in targetmap",mountby);
  314.                             d["device"] = device; //FIXME: for some reason this does not work
  315.                             p["partition_nr"] = targetPart["nr"]:0;
  316.                             p["usepart"] = targetPart["nr"]:0;
  317.                         }
  318.                     });
  319.                 }
  320.                 return p;
  321.             });
  322.             return d;
  323.         });
  324.         y2milestone("after mountBy settings=%1",settings);
  325.         return settings;
  326.     }
  327.  
  328.     /* makes something like: 
  329.             <device>/dev/disk/by-id/edd-int13_dev80</device>
  330.        possible (Bug #82867)
  331.     */
  332.     global define list<map> udev2dev(list<map> settings) {
  333.         map <string, map> tm = Storage::GetTargetMap();
  334.         settings = maplist( map d, settings, ``{
  335.             string device = d["device"]:"";
  336.             string udev_string = "";
  337.             if( device == "" ) {
  338.                 d["device"] = find_first_disk();
  339.                 y2milestone("empty device in profile set to %1", d["device"]:"");
  340.             } else if( issubstring( device, "by-id" ) )
  341.                 udev_string = "udev_id";
  342.             else if( issubstring( device, "by-path" ) )
  343.                 udev_string = "udev_path";
  344.             if( udev_string != "" ) {
  345.                 integer index = findlastof( device, "/" );
  346.                 string wanted_udev = substring( device, index+1 );
  347.                 foreach( string deviceName, map tmp_target, tm, ``{
  348.                     y2milestone("searching for %1 on %2", wanted_udev, deviceName );
  349.                     list<string> liste = [];
  350.                     if( udev_string == "udev_id" )
  351.                         liste = tmp_target[udev_string]:[];
  352.                     else
  353.                         liste = [ tmp_target[udev_string]:"" ];
  354.                     foreach( string found_udev, liste, ``{
  355.                         if( found_udev == wanted_udev ) {
  356.                             d["device"] = deviceName;
  357.                             y2milestone("found mapping of %1 to %2",found_udev, deviceName);
  358.                             break;
  359.                         }
  360.                     });
  361.                 });
  362.             }
  363.             return d;
  364.         });
  365.         return settings;
  366.     }
  367.  
  368.     global define list<map> checkSizes(list<map> settings) {
  369.         y2milestone("entering checkSizes with %1",settings);
  370.         map <string, map> tm = Storage::GetTargetMap();
  371.         y2milestone("targetmap = %1",tm);
  372.  
  373.         settings = maplist( map d, settings, ``{
  374.             if( d["type"]:`x == `CT_DISK ) {
  375.                 integer sizeByCyl = 0;
  376.                 integer usedSize = 0;
  377.                 integer max = 0;
  378.                 integer cyl_size = 0;
  379.                 foreach( string device, map v, tm, ``{
  380.                     if( device == d["device"]:"" ) {
  381.                         sizeByCyl = v["cyl_count"]:0 * v["cyl_size"]:0;
  382.                         cyl_size = v["cyl_size"]:0;
  383.                         y2milestone("device found in tm. sizeByCyl=%1",sizeByCyl);
  384.                     }
  385.                 });
  386.                 if( sizeByCyl == 0 ) {
  387.                     y2milestone("not found");
  388.                     return d;
  389.                 }
  390.                 foreach(map pe, d["partitions"]:[], ``{
  391.                     usedSize = usedSize + pe["size"]:0;
  392.                     if( pe["size"]:0 > max )
  393.                         max = pe["size"]:0;
  394.                 });
  395.                 if( usedSize > sizeByCyl ) {
  396.                     y2milestone("usedSize too big: %1",usedSize);
  397.                     d["partitions"] = maplist( map pe, d["partitions"]:[], ``{
  398.                         integer s = pe["size"]:0;
  399.                         if( s == max ) {
  400.                             y2milestone("shrinking %1",pe);
  401.                             s = s - ((usedSize - sizeByCyl)/cyl_size+2)*cyl_size; // FIXME: why 2? 1 should be enough
  402.                             usedSize = usedSize - s;
  403.                             y2milestone("shrinking to %1",s);
  404.                             pe["size"] = s;
  405.                         }
  406.                         return pe;
  407.                     });
  408.                 }
  409.             }
  410.             return d;
  411.         });
  412.         y2milestone("after checkSizes %1",settings);
  413.         return settings;
  414.     }
  415.  
  416.     /*
  417.        the resize option in the storage lib requires the new size in the
  418.        "region" format. That format is hardly configureable by humans, so I
  419.        do the translation here
  420.     */
  421.     global define list<map> region4resize( list<map> settings ) {
  422.         // the storage lib requires the region to be set
  423.         // we transform the size to the region here
  424.         map <string, map> tm = Storage::GetTargetMap();
  425.         settings = maplist( map d, settings, ``{
  426.             if( d["type"]:`x == `CT_DISK ) {
  427.                 map realDisk = tm[ d["device"]:"" ]:$[];
  428.                 d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
  429.                     if( pe["resize"]:false ) {
  430.                         integer currentCyl = realDisk["partitions",pe["partition_nr"]:1-1,"region",1]:0;
  431.                         pe["region"] = realDisk["partitions",pe["partition_nr"]:1-1,"region"]:[];
  432.                         if( issubstring( pe["size"]:"", "%") ) {
  433.                             string percentage = deletechars( pe["size"]:"", "%" );
  434.                             integer newCyl = currentCyl * tointeger(percentage) / 100;
  435.                             pe["region",1] = newCyl;
  436.                         } else {
  437.                             integer new_size = kmgt_str_to_byte( pe["size"]:"0" );
  438.                             integer newCyl = new_size/realDisk["cyl_size"]:1;
  439.                             pe["region",1] = newCyl;
  440.                         }
  441.                         y2milestone("resize partition nr %1 of %2 to region: %3", pe["partition_nr"]:1, d["device"]:"", pe["region"]:[]);
  442.                     }
  443.                     return pe;
  444.                 });
  445.             }
  446.             return d;
  447.         });
  448.         y2milestone("after region4resize = %1",settings);
  449.         return settings;
  450.     }
  451.  
  452.     /*
  453.         the percentage must be calculated to an actual size.
  454.         This is done here
  455.     */
  456.     global define list<map> percent2size( list<map> settings ) {
  457.         map <string, map> tm = Storage::GetTargetMap();
  458.         settings = maplist( map d, settings, ``{
  459.             if( d["type"]:`x == `CT_DISK ) {
  460.                 map v = tm[ d["device"]:"" ]:$[];
  461.                 d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
  462.                     if( issubstring( pe["size"]:"", "%") ) {
  463.                         string percentage = deletechars( pe["size"]:"", "%" );
  464.                         integer device_size = v["cyl_count"]:0 * v["cyl_size"]:0;
  465.                         pe["size"] = sformat("%1", device_size * tointeger(percentage) / 100);
  466.                         y2milestone("percentage %1 of %2 = %3",percentage,d["device"]:"",pe["size"]:"");
  467.                     }
  468.                     return pe;
  469.                 });
  470.             } else if( d["type"]:`x == `CT_LVM || d["type"]:`x == `CT_EVMS ) {
  471.                 d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
  472.                     if( issubstring( pe["size"]:"", "%") ) {
  473.                         pe["size"] = deletechars( pe["size"]:"", "%" ); // a size smalle than 101 will be treated as % later
  474.                     }
  475.                     return pe;
  476.                 });
  477.             }
  478.             return d;
  479.         });
  480.         y2milestone("after percent2size = %1",settings);
  481.         return settings;
  482.     }
  483.  
  484.     /*
  485.         if partition type is primary but not set in the profile, set it now
  486.     */
  487.     global define list<map> setPartitionType(list<map> settings) {
  488.         map <string, map> tm = Storage::GetTargetMap();
  489.         settings = maplist( map d, settings, ``{
  490.             if( d["type"]:`x == `CT_DISK ) {
  491.                 integer mp = tm[ d["device"]:"xxx","max_primary" ]:0;
  492.                 if( mp > 0 ) {
  493.                     d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
  494.                         if( haskey(pe, "partition_nr") && !haskey(pe,"partition_type") && pe["partition_nr"]:-1 <= mp )
  495.                             pe["partition_type"] = "primary";
  496.                         return pe;
  497.                     });
  498.                 }
  499.             }
  500.             return d;
  501.         });
  502.         y2milestone("after setPartitionType = %1",settings);
  503.         return settings;
  504.     }
  505.  
  506.     /**
  507.      * Get all the configuration from a map.
  508.      * When called by inst_auto<module name> (preparing autoinstallation data)
  509.      * the list may be empty.
  510.      * @param settings a list    [...]
  511.      * @return    boolean success
  512.      */
  513.     global define boolean Import(list<map> settings)
  514.     {
  515.         y2milestone("entering Import with %1", settings);
  516.         if (Mode::autoinst()) {
  517.             settings = maplist( map d, settings, ``{
  518.                 d["partitions"] = sort( map x, map y, d["partitions"]:[], ``( x["partition_nr"]:99 < y["partition_nr"]:99 ));
  519.                 return d;
  520.             });
  521.             settings = udev2dev(settings);
  522.             settings = mountBy(settings);
  523.             settings = region4resize(settings);
  524.             settings = percent2size(settings);
  525.             settings = setPartitionType(settings);
  526.             AutoPartPlan = preprocess_partition_config(settings);
  527.             AutoPartPlan = checkSizes(AutoPartPlan);
  528.         } else {
  529.             settings = maplist( map d, settings, ``{
  530.                 if( ! haskey(d,"device") ) {
  531.                     // this is just to satisfy the UI
  532.                     d = add( d, "device", "auto" );
  533.                     y2debug("device 'auto' added");
  534.                 }
  535.                 return d;
  536.             });
  537.             AutoPartPlan = settings;
  538.         }
  539.         y2milestone("AutoPartPlan: %1", AutoPartPlan );
  540.  
  541.         return true;
  542.     }
  543.  
  544.     /**
  545.      * Import Fstab data
  546.      * @param settings Settings Map
  547.      * @return    boolean true on success
  548.      */
  549.     global define boolean ImportAdvanced(map settings)
  550.     {
  551.         y2milestone("entering ImportAdvanced with %1", settings);
  552.         fstab = settings["fstab"]:$[];
  553.         read_fstab = fstab["use_existing_fstab"]:false;
  554.  
  555.         //AutoinstLVM::ZeroNewPartitions = settings["zero_new_partitions"]:true;
  556.         return true;
  557.     }
  558.  
  559.     /**
  560.      * return Summary of configuration
  561.      * @return  string configuration summary dialog
  562.      */
  563.     global define string Summary()
  564.     {
  565.         string summary = "";
  566.         summary = Summary::AddHeader(summary, _("Drives"));
  567.         integer num = size(AutoPartPlan);
  568.         summary = Summary::AddLine( summary, sformat(_("Total of %1 drive", "Total of %1 drives", num), num));
  569.         summary = Summary::OpenList(summary);
  570.         foreach(map drive, AutoPartPlan, ``{
  571.             summary = Summary::AddListItem(summary, drive["device"]:_("No specific device configured") );
  572.         });
  573.         summary = Summary::CloseList(summary);
  574.         return summary;
  575.     }
  576.  
  577.     /**
  578.      * Handle /etc/fstab usage
  579.      * @return boolean
  580.      */
  581.     define boolean handle_fstab()
  582.     {
  583.         y2milestone("entering handle_fstab");
  584.  
  585.         if (!RootPart::didSearchForRootPartitions)
  586.         {
  587.             UI::OpenDialog (`opt(`decorated ),
  588.                             `Label(_("Evaluating root partition. One moment please...")));
  589.             RootPart::FindRootPartitions ();
  590.             UI::CloseDialog ();
  591.         }
  592.  
  593.         if (RootPart::numberOfValidRootPartitions == 0)
  594.         {
  595.             // a popup
  596.             Popup::Message(_("No Linux root partition found."));
  597.             return false;
  598.         }
  599.  
  600.         // We must only change RootPart::selectedRootPartition if booting
  601.         // is inevitable.
  602.         string rp = fstab["root_partition"]:"";
  603.         list<map> fstab_partitions = fstab["partitions"]:[];
  604.  
  605.         if (RootPart::numberOfValidRootPartitions == 1)
  606.         {
  607.             RootPart::SetSelectedToValid ();
  608.         }
  609.         else if ( rp == ""){
  610.             Popup::Message(_("Multiple root partitions found, but you did not configure
  611. which root partition should be used.  Automatic installation not possible.
  612. "));
  613.             return false;
  614.         }
  615.         else if ( haskey(RootPart::rootPartitions, rp) 
  616.                 && RootPart::numberOfValidRootPartitions > 1)
  617.         {
  618.             RootPart::selectedRootPartition = rp;
  619.         }
  620.  
  621.         RootPart::MountPartitions(RootPart::selectedRootPartition);
  622.         RootPart::SetFormatPartitions (fstab_partitions);
  623.         RootPart::UnmountPartitions (true);
  624.         return true;
  625.     }
  626.  
  627.  
  628.     /**
  629.      * Create partition plan
  630.      * @return boolean
  631.      */
  632.     global define boolean Write() {
  633.         y2milestone("entering Write");
  634.         Storage::SetRecursiveRemoval( true );
  635.  
  636.         if (read_fstab)
  637.             return (handle_fstab());
  638.  
  639.         map <string, map> initial_target_map = Storage::GetTargetMap();
  640.         y2milestone("Target map: %1", initial_target_map );
  641.  
  642.         Storage::SetPartDisk( find_first_disk() );
  643.  
  644.         AutoTargetMap =  set_devices(AutoPartPlan);
  645.         if (AutoTargetMap == nil || AutoTargetMap == $[])
  646.             return false;
  647.  
  648.         y2milestone("AutoTargetMap: %1",  AutoTargetMap);
  649.         
  650.         // return list of available devices
  651.         list<string> disk_devices = maplist( string k, map e,
  652.                                              filter( string l, map f, Storage::GetTargetMap(),
  653.                                                      ``(Storage::IsRealDisk( f ))), ``(k));
  654.  
  655.         y2milestone("disk_devices: %1", disk_devices );
  656.  
  657.         boolean result = false;
  658.  
  659.         foreach (string device, map data, AutoTargetMap, ``{
  660.                 if ( Storage::IsRealDisk( data) &&
  661.                      data["initialize"]:false == true) {
  662.                         initial_target_map[device,"delete"] = true;
  663.                         Storage::SetTargetMap(initial_target_map);
  664.                 }
  665.         });
  666.         y2milestone("Target map after initialzing disk: %1", Storage::GetTargetMap());
  667.  
  668.         foreach (string device, map data, AutoTargetMap,
  669.                  ``{
  670.             if ( Storage::IsRealDisk( data) )
  671.             {
  672.                 y2milestone("Creating partition plans for %1", device);
  673.                 
  674.                 map sol = find_matching_disk([device], Storage::GetTargetMap(), data );      
  675.                 if (size(sol) > 0 )
  676.                     result = true;
  677.                     
  678.                 y2milestone("solutions: %1", sol);
  679.                 map <string, map> tm = Storage::GetTargetMap();
  680.                 tm[device] =    process_partition_data(device, sol);
  681.  
  682.         SearchRaids(tm);
  683.                 Storage::SetTargetMap(tm);
  684.         }
  685.         });
  686.  
  687.         return result;
  688.     }
  689.  
  690.  
  691.     /**
  692.      * Build the id for a partition entry in the man table.
  693.      * @parm disk_dev_name name of the devie e.g.: /dev/hda
  694.      * @parm nr number of the partition e.g.: 1
  695.      * @return string e.g.: 01./dev/hda
  696.      */
  697.     define string  build_id(  string disk_dev_name , any nr )
  698.     {
  699.         return (sformat( "%1:%2", disk_dev_name, nr));
  700.     }
  701.  
  702.  
  703.     /**
  704.      * Partitioning Overview
  705.      * @return list Overview
  706.      */
  707.     global define list Overview()
  708.     {
  709.         y2milestone("entering Overview");
  710.  
  711.         map allfs = FileSystems::GetAllFileSystems(true, true);
  712.         list drives_table = [];
  713.  
  714.         string id = "";
  715.         foreach(map d, AutoPartPlan,
  716.                 ``{
  717.             id = d["device"]:"";
  718.             term a = `item(`id(id), d["device"]:"", "", "", "", "", "" );
  719.  
  720.             drives_table = add (drives_table, a);
  721.  
  722.             list<map> partitions = d["partitions"]:[];
  723.             integer start_id = 1;
  724.  
  725.             if ( size (partitions) > 0 )
  726.             {
  727.                 foreach(map p, partitions, ``{
  728.                     id = build_id(d["device"]:"" , start_id );
  729.  
  730.                     term b = `item(`id(id));
  731.                     b = add (b, "");
  732.  
  733.                     b=add(b, p["mount"]:"" );
  734.                     b=add(b, p["size"]:"");
  735.  
  736.                     if (!haskey(p, "filesystem_id"))
  737.                     {
  738.                         b=add(b, Partitions::FsIdToString(p["partition_id"]:131));
  739.                     }
  740.                     else
  741.                     {
  742.                         b=add(b, Partitions::FsIdToString(p["filesystem_id"]:131));
  743.                     }
  744.  
  745.                     map fs = allfs[p["filesystem"]:`nothing]:$[];
  746.                     string fs_name = fs[`name]:"";
  747.  
  748.                     b=add(b, fs_name);
  749.  
  750.                     if ( size( p["region"]:[] ) > 0 )
  751.                     {
  752.                         b=add(b, sformat("%1 - %2", p["region",0]:0, p["region",1]:0));
  753.                     }
  754.                     else
  755.                     {
  756.                         b=add(b, "");
  757.                     }
  758.  
  759.                     drives_table = add(drives_table, b);
  760.                     start_id = start_id + 1;
  761.                 });
  762.             }
  763.  
  764.         });
  765.  
  766.         integer entries = size(drives_table);
  767.         list reversed_table = [];
  768.         integer counter = entries;
  769.  
  770.         term tmp = `item(`id(`empty));
  771.  
  772.         while (counter != 0)
  773.         {
  774.             reversed_table=add(reversed_table, drives_table[counter -1]:tmp);
  775.             counter = counter - 1;
  776.  
  777.         }
  778.         y2debug("table: %1", drives_table );
  779.         return drives_table;
  780.  
  781.  
  782.     }
  783.  
  784.     // EOF
  785. }
  786.