ACC SHELL

Path : /usr/share/YaST2/modules/
File Upload :
Current File : //usr/share/YaST2/modules/AutoinstStorage.ycp

/**
 * File:	modules/AutoinstStorage.ycp
 * Module:	Auto-Installation
 * Summary:	Storage
 * Authors:	Anas Nashif <nashif@suse.de>
 *
 * $Id: AutoinstStorage.ycp 62054 2010-05-21 09:04:27Z ug $
 */
{
    module "AutoinstStorage";
    textdomain "autoinst";

    import "Storage";
    import "RootPart";
    import "Partitions";
    import "FileSystems";
    import "Summary";
    import "Storage";
    import "Partitions";  
    import "Popup";
    import "Report";
    import "Mode";
    import "Installation";

    // All shared data are in yast2.rpm to break cyclic dependencies
    import "AutoinstData";

    // Read existing fstab and format partitions, but dont create anything
    // Use same mountpoints etc.
    global boolean read_fstab = false;
    global boolean ZeroNewPartitions = true;

    // Fstab options
    global map fstab = $[];

    // Partition plan as parsed from control file
    global list<map> AutoPartPlan = [];

    // Prepared target map from parsed data
    global map<string, map> AutoTargetMap = $[];

    /* default value of settings modified */
    global boolean modified = false;

    global map<string,list> raid2device = $[];

    // some architectures need a boot partition. Do we have one?
    global boolean planHasBoot = false;

    /**
     * Function sets internal variable, which indicates, that any
     * settings were modified, to "true"
     */
    global define void SetModified ()
    {
        y2milestone("SetModified");
        modified = true;
    }

    /**
     * Functions which returns if the settings were modified
     * @return boolean  settings were modified
     */
    global define boolean GetModified ()
    {
        return modified;
    }

    /**
     * Wrapper function for the LibStorage call that can't be used directly
     * in YCP
     * @return integer
     *
     */
    global define integer humanStringToByte( string s, boolean b ) {
        if( size(s) == 0 )
            s = "0b";
        if( findfirstof( s, "bB" ) == nil )
            s = s + "b";
        return Storage::ClassicStringToByte(s);
    }

    include "autoinstall/autopart.ycp";
    include "autoinstall/autoinst_dialogs.ycp";

    global define string find_first_disk(string after) {
        map <string, map> initial_target_map = Storage::GetTargetMap();
        y2milestone("Target map: %1", initial_target_map );

        string mbr_disk = "";
        if( after == "" ) {
            foreach (string device, map disk, initial_target_map, ``{
                if (disk["type"]:`jo == `CT_DMRAID ||
                    disk["type"]:`jo == `CT_MDPART ||
		    disk["type"]:`jo == `CT_DMMULTIPATH)
                {
                    mbr_disk = device;
                }
            });
        }

        if( after == "" && mbr_disk == "" ) {
            foreach (string device, map disk, initial_target_map, ``{
                if (disk["bios_id"]:"" == "0x80")
                {
                    mbr_disk = device;
                }
            });
        }

        /* device guessing code enhanced */
        if( mbr_disk == "" ) {
            foreach (string device, map disk, initial_target_map, ``{
                if( disk["type"]:`x == `CT_DISK ) {
                    if( device == after )
                        continue;
                    mbr_disk = device;
                    break;
                }
            });
        }

        y2milestone("device detection: %1", mbr_disk);
        return mbr_disk;
    }

    /**
     * Pre-process partition plan and prepare for creating partitions.
     * @return void
     */
    define map<string, map>  set_devices(list<map> storage_config ) {
    y2milestone("entering set_devices with %1",storage_config);	
        boolean first_set = false;
        boolean failed = false;
        map<string, map> auto_targetmap =  listmap (map drive, storage_config, ``{
            string device = "";
            y2milestone("Working on drive: %1", drive);

            // FIXME: Check if physical drives > 1
            if (drive["device"]:"" == "ask"  )
            {
                string dev = DiskSelectionDialog();
                if (dev != nil)
                {
                    first_set = true;
                    device = dev;
                }	

                return  $[device: drive ];
            }

            if (!first_set 
                && ( drive["device"]:"" == ""  
                     || drive["device"]:"" == "ask")
                )
            {
                device = Storage::GetPartDisk();
                y2milestone("device: %1", device );
                first_set = true;
                return $[device: drive ];
            }
            else if (drive["device"]:"" != "")
            {	
                string dev = drive["device"]:"";
                if (dev == "") {
                    dev = "error";
                    y2error("Missing device name in partitioning plan");
                    failed = true;
                }

                return $[dev: drive ];
            }
            
        });

        if (failed)
            return nil;
        
        auto_targetmap =  mapmap (string device, map d, auto_targetmap, ``{
            // Convert from Old Style
            if (haskey(d, "use"))
            {
               y2milestone("converting from \"use\" to new style: %1", device);
               if (d["use"]:"" == "free") {
                   d["prefer_remove"] = false;
               } else if (d["use"]:"" == "all" ) {
                   d["prefer_remove"] = true;
               } else if (d["use"]:"" == "linux" ) {
                   d["keep_partition_num"] = GetNoneLinuxPartitions(device);
                   d["prefer_remove"] = true;
               } else {
                    list<string> uselist = filter(string s,
                                splitstring(d["use"]:"", ","), ``(s!=""));
                    y2milestone("uselist: %1", uselist);
                    list<integer> keeplist = [];
                    list<integer> all = GetAllPartitions(device);
                    y2milestone("all list: %1", all);
                    foreach(integer i , all, ``{
                            if (!contains(uselist, sformat("%1", i)))
                                keeplist=add(keeplist,i);
                        });
                    y2milestone("keeplist: %1", keeplist);
                    d["keep_partition_num"] = keeplist;
                    
                    if (size(keeplist) > 0 )
                        d["prefer_remove"] = true;
               }
            } else {
                d["use"] = "all";
            }
            // see if <usepart> is used and add the partitions to <keep_partition_num>
            foreach(map p, d["partitions"]:[], ``{
                    if (p["usepart"]:-1 != -1 ){
                        d["keep_partition_num"] = add(d["keep_partition_num"]:[], p["usepart"]:-1);
                    }
                    });
            d["keep_partition_num"] = toset(d["keep_partition_num"]:[]);

            return($[device:d]);
            });

        y2milestone("processed autoyast partition plan: %1", auto_targetmap );
        return auto_targetmap;
    }

    global define list GetRaidDevices (string dev, map<string,map> tm) {
        list<map> ret = [];
        foreach( string k, map d, tm, ``{
            if( d["type"]:`CT_UNKNOWN == `CT_DISK ) {
                list tmp = filter( map p, d["partitions"]:[],
                                    ``( p["raid_name"]:"" == dev ) );
                ret = (list<map>)union( ret, tmp );
            }
        });
        list dlist = maplist( map p, ret, ``{ return p["device"]:""; } );
        y2milestone("GetRaidDevices dlist = %1 and ret = %2", dlist, ret);
        return dlist;
    }

    global define void SearchRaids (map<string,map> tm) {
        //raid2device = $[];
        foreach( string k, map d, tm, ``{
            if( d["type"]:`CT_UNKNOWN == `CT_DISK ) {
                list<map> tmp = filter( map p, d["partitions"]:[],
                                    ``( p["raid_name"]:"" != "" ) );
                list<string> devMd = maplist( map p, tmp, ``{ return p["raid_name"]:""; } );
                foreach( string dev, devMd, ``{
                    if( ! haskey( raid2device, dev ) ) {
                        raid2device[dev] = GetRaidDevices(dev,tm);
                    } else {
                        foreach( string k, (list<string>)GetRaidDevices(dev,tm), ``{
                             raid2device[dev] = add(raid2device[dev]:[],k);
                        });
                    }
                });
            }
        });
        y2milestone("SearchRaids raid2device = %1", raid2device);
    }

    /**
     * if mountby is used, we will search for the matching
     * partition here.
     * @return list
     */
    global define list<map> mountBy(list<map> settings) {
        map <string, map> tm = Storage::GetTargetMap();
        y2milestone("Storage::GetTargetMap returns %1",tm);
        settings = maplist( map d, settings, ``{
            string device = d["device"]:"";
            d["partitions"] = maplist( map p, d["partitions"]:[], ``{
                string mountby = "";
                boolean mountByIsList = false;
                if( p["mount"]:"" == "swap" || p["filesystem"]:`none == `swap ) {
                     p["mount"] = "swap";
                     p["filesystem"] = `swap;
                }
                if( haskey(p, "mountby") ) {
                    if( p["mountby"]:`none == `label ) {
                        mountby = "label";
                    } else if( p["mountby"]:`none == `uuid ) {
                        mountby = "uuid";
                    } else if( p["mountby"]:`none == `path ) {
                        mountby = "udev_path";
                    } else if( p["mountby"]:`none == `id ) {
                        mountByIsList = true;
                        mountby = "udev_id";
                    } else if( p["mountby"]:`none != `device ) {
                        y2milestone("unknown mountby parameter '%1' will be ignored",p["mountby"]:`none);
                    }
                }
                /* reuse partition by "mountby" */
                if( mountby != "" && p["create"]:true == false ) {
                    string label = p[mountby]:"";
                    y2milestone("mountby found for %1=%2 in part=%3",mountby,label,p);
                    map target = tm[device]:$[];
                    if( device == "" ) {
                        y2milestone("searching for the device by %1",mountby);
                        foreach( string deviceName, map tmp_target, tm, ``{
                            foreach( map targetPart, tmp_target["partitions"]:[], ``{
                                if( mountByIsList ? (contains(targetPart[mountby]:[], label)):(targetPart[mountby]:"" == label) ) {
                                    target = tmp_target;
                                    device = deviceName;
                                    y2milestone("device=%1 found",device);
                                    break;
                                }
                            });
                        });
                    }
                    foreach( map targetPart, target["partitions"]:[], ``{
                        if( mountByIsList ? (contains(targetPart[mountby]:[], label)):(targetPart[mountby]:"" == label) ) {
                            y2milestone("%1 found in targetmap",mountby);
                            d["device"] = device; //FIXME: for some reason this does not work
                            p["partition_nr"] = targetPart["nr"]:0;
                            p["usepart"] = targetPart["nr"]:0;
                        }
                    });
                }
                return p;
            });
            return d;
        });
        y2milestone("after mountBy settings=%1",settings);
        return settings;
    }

    /* makes something like: 
            <device>/dev/disk/by-id/edd-int13_dev80</device>
       possible (Bug #82867)
    */
    global define list<map> udev2dev(list<map> settings) {
        map <string, map> tm = Storage::GetTargetMap();
        string last_dev = "";
        settings = maplist( map d, settings, ``{
            string device = d["device"]:"";
            string udev_string = "";
            if( device == "" ) {
                d["device"] = find_first_disk(last_dev);
                y2milestone("empty device in profile set to %1", d["device"]:"");
            }

            // translation of by-id, by-path, ... device names.
            // was handled in autoyast until openSUSE 11.3
            map<string,any> deviceTranslation = $[];
            if( Storage::GetContVolInfo( d["device"]:"", deviceTranslation ) )
                d["device"] = deviceTranslation["cdevice"]:"";

            /* old code for device mapping (by-id, by-path, ...)
            else if( issubstring( device, "by-id" ) )
                udev_string = "udev_id";
            else if( issubstring( device, "by-path" ) )
                udev_string = "udev_path";
            if( udev_string != "" ) {
                integer index = findlastof( device, "/" );
                string wanted_udev = substring( device, index+1 );
                foreach( string deviceName, map tmp_target, tm, ``{
                    y2milestone("searching for %1 on %2", wanted_udev, deviceName );
                    list<string> liste = [];
                    if( udev_string == "udev_id" )
                        liste = tmp_target[udev_string]:[];
                    else
                        liste = [ tmp_target[udev_string]:"" ];
                    foreach( string found_udev, liste, ``{
                        if( found_udev == wanted_udev ) {
                            d["device"] = deviceName;
                            y2milestone("found mapping of %1 to %2",found_udev, deviceName);
                            break;
                        }
                    });
                });
            }
            */


            last_dev = d["device"]:"";
            return d;
        });
        return settings;
    }

    global define list<map> checkSizes(list<map> settings) {
        y2milestone("entering checkSizes with %1",settings);
        map <string, map> tm = Storage::GetTargetMap();
        y2milestone("targetmap = %1",tm);

        settings = maplist( map d, settings, ``{
            if( d["type"]:`x == `CT_DISK ) {
                integer sizeByCyl = 0;
                integer usedSize = 0;
                integer max = 0;
                integer cyl_size = 0;
                foreach( string device, map v, tm, ``{
                    if( device == d["device"]:"" ) {
                        sizeByCyl = v["cyl_count"]:0 * v["cyl_size"]:0;
                        cyl_size = v["cyl_size"]:0;
                        y2milestone("device found in tm. sizeByCyl=%1",sizeByCyl);
                    }
                });
                if( sizeByCyl == 0 ) {
                    y2milestone("not found");
                    return d;
                }
                foreach(map pe, d["partitions"]:[], ``{
                    usedSize = usedSize + pe["size"]:0;
                    if( pe["size"]:0 > max )
                        max = pe["size"]:0;
                });
                if( usedSize > sizeByCyl ) {
                    y2milestone("usedSize too big: %1",usedSize);
                    d["partitions"] = maplist( map pe, d["partitions"]:[], ``{
                        integer s = pe["size"]:0;
                        if( s == max ) {
                            y2milestone("shrinking %1",pe);
                            s = s - ((usedSize - sizeByCyl)/cyl_size+1+size(d["partitions"]:[]))*cyl_size; // 1 cyl buffer per partition
                            if( s < 1 ) {
                                Report::Error( sformat( _("The partition plan configured in your XML profile does not fit on the hard disk. %1MB missing"), (usedSize-sizeByCyl)/(1024*1024) ));
                                break;
                            } else {
                                usedSize = usedSize - s;
                                y2milestone("shrinking to %1",s);
                                pe["size"] = s;
                            }
                        }
                        return pe;
                    });
                }
            }
            return d;
        });
        y2milestone("after checkSizes %1",settings);
        return settings;
    }

    /*
       the resize option in the storage lib requires the new size in the
       "region" format. That format is hardly configureable by humans, so I
       do the translation here
    */
    global define list<map> region4resize( list<map> settings ) {
        // the storage lib requires the region to be set
        // we transform the size to the region here
        map <string, map> tm = Storage::GetTargetMap();
        settings = maplist( map d, settings, ``{
            if( d["type"]:`x == `CT_DISK ) {
                map realDisk = tm[ d["device"]:"" ]:$[];
                d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
                    if( pe["resize"]:false ) {
                        integer currentCyl = realDisk["partitions",pe["partition_nr"]:1-1,"region",1]:0;
                        pe["region"] = realDisk["partitions",pe["partition_nr"]:1-1,"region"]:[];
                        if( issubstring( pe["size"]:"", "%") ) {
                            string percentage = deletechars( pe["size"]:"", "%" );
                            integer newCyl = currentCyl * tointeger(percentage) / 100;
                            pe["region",1] = newCyl;
                        } else {
                            integer new_size = humanStringToByte( pe["size"]:"0", true );
                            integer newCyl = new_size/realDisk["cyl_size"]:1;
                            pe["region",1] = newCyl;
                        }
                        y2milestone("resize partition nr %1 of %2 to region: %3", pe["partition_nr"]:1, d["device"]:"", pe["region"]:[]);
                    }
                    return pe;
                });
            }
            return d;
        });
        y2milestone("after region4resize = %1",settings);
        return settings;
    }

    /*
        the percentage must be calculated to an actual size.
        This is done here
    */
    global define list<map> percent2size( list<map> settings ) {
        map <string, map> tm = Storage::GetTargetMap();
        settings = maplist( map d, settings, ``{
            if( d["type"]:`x == `CT_DISK ) {
                map v = tm[ d["device"]:"" ]:$[];
                d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
                    if( issubstring( pe["size"]:"", "%") ) {
                        string percentage = deletechars( pe["size"]:"", "%" );
                        integer device_size = v["cyl_count"]:0 * v["cyl_size"]:0;
                        pe["size"] = sformat("%1", device_size * tointeger(percentage) / 100);
                        y2milestone("percentage %1 of %2 = %3",percentage,d["device"]:"",pe["size"]:"");
                    }
                    return pe;
                });
            } else if( d["type"]:`x == `CT_LVM ) {
                d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
                    if( issubstring( pe["size"]:"", "%") ) {
                        pe["size"] = deletechars( pe["size"]:"", "%" ); // a size smalle than 101 will be treated as % later
                    }
                    return pe;
                });
            }
            return d;
        });
        y2milestone("after percent2size = %1",settings);
        return settings;
    }

    /*
        if partition type is primary but not set in the profile, set it now
    */
    global define list<map> setPartitionType(list<map> settings) {
        map <string, map> tm = Storage::GetTargetMap();
        settings = maplist( map d, settings, ``{
            if( d["type"]:`x == `CT_DISK ) {
                integer mp = tm[ d["device"]:"xxx","max_primary" ]:0;
                if( mp > 0 ) {
                    d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
                        if( haskey(pe, "partition_nr") && !haskey(pe,"partition_type") && pe["partition_nr"]:-1 <= mp )
                            pe["partition_type"] = "primary";
                        return pe;
                    });
                }
            }
            return d;
        });
        y2milestone("after setPartitionType = %1",settings);
        return settings;
    }


    /**
     * Get all the configuration from a map.
     * When called by inst_auto<module name> (preparing autoinstallation data)
     * the list may be empty.
     * @param settings a list	[...]
     * @return	boolean success
     */
    global define boolean Import(list<map> settings)
    {
        y2milestone("entering Import with %1", settings);
        if (Mode::autoinst()) {
            settings = maplist( map d, settings, ``{
                d["partitions"] = sort( map x, map y, d["partitions"]:[], ``( x["partition_nr"]:99 < y["partition_nr"]:99 ));
                return d;
            });
            settings = udev2dev(settings);
            settings = mountBy(settings);
            settings = region4resize(settings);
            settings = percent2size(settings);
            settings = setPartitionType(settings);
            settings = maplist( map d, settings, ``{
                d["partitions"] = maplist(map pe, d["partitions"]:[], ``{
                    if( haskey( pe, "size" ) ) {
                        if( pe["size"]:"" == "auto" && pe["mount"]:"" == "swap" )
                            pe["size"] = sformat( "%1", 1024*1024*Partitions::SwapSizeMb(0) );
                        else if( pe["size"]:"" == "auto" && pe["mount"]:"" == "/boot" )
                            pe["size"] = sformat( "%1", Partitions::MinimalNeededBootsize() );
                        if( pe["size"]:"" != "max" && pe["size"]:"" != "auto" )
                            pe["size"] = sformat("%1",humanStringToByte(pe["size"]:"", false));
                    }
                    return pe;
                });
                return d;
            });
            AutoPartPlan = preprocess_partition_config(settings);
            AutoPartPlan = checkSizes(AutoPartPlan);
        } else {
            settings = maplist( map d, settings, ``{
                if( ! haskey(d,"device") ) {
                    // this is just to satisfy the UI
                    d = add( d, "device", "auto" );
                    y2debug("device 'auto' added");
                }
                return d;
            });
            AutoPartPlan = settings;
        }
        y2milestone("AutoPartPlan: %1", AutoPartPlan );

        return true;
    }

    /**
     * Import Fstab data
     * @param settings Settings Map
     * @return	boolean true on success
     */
    global define boolean ImportAdvanced(map settings)
    {
        y2milestone("entering ImportAdvanced with %1", settings);
        fstab = settings["fstab"]:$[];
        read_fstab = fstab["use_existing_fstab"]:false;

        //AutoinstLVM::ZeroNewPartitions = settings["zero_new_partitions"]:true;
        return true;
    }

    /**
     * return Summary of configuration
     * @return  string configuration summary dialog
     */
    global define string Summary()
    {
        string summary = "";
        summary = Summary::AddHeader(summary, _("Drives"));
        integer num = size(AutoPartPlan);
        summary = Summary::AddLine( summary, sformat(_("Total of %1 drive", "Total of %1 drives", num), num));
        summary = Summary::OpenList(summary);
        foreach(map drive, AutoPartPlan, ``{
            summary = Summary::AddListItem(summary, drive["device"]:_("No specific device configured") );
        });
        summary = Summary::CloseList(summary);
        return summary;
    }

    // Moved here from RootPart module (used just by this module)
    global define boolean SetFormatPartitions (list<map> fstabpart)
    {
	// All storage devices
        map <string, map> target_map = Storage::GetTargetMap ();

	// all activated
	list <map> tmp = filter (map e, RootPart::GetActivated(), {
	    return (e[`type]:"" == "mount" || e[`type]:"" == "swap");
	});

	foreach (map e, tmp, {
	    string mntpt = (e[`type]:"" == "swap")?("swap"):(e[`mntpt]:"");
	    string part  = e[`device]:"";

	    map p = $[];
	    foreach (map pp, fstabpart, {
		// mountpoint matches
		if (pp["mount"]:"" == mntpt) {
		    p = pp;
		    break;
		}
	    });
	    string mount_options = "";
	    foreach (map entry, (list <map>) Storage::ReadFstab (Installation::destdir), {
		if( entry["file"]:"" == mntpt ) {
			mount_options = entry["mntops"]:"";
			break;
		}
	    });
	    target_map = Storage::SetPartitionData (target_map, part, "mount", mntpt );
	    target_map = Storage::SetPartitionData (target_map, part, "format", p["format"]:false );
	    target_map = Storage::SetPartitionData (target_map, part, "delete", false);
	    target_map = Storage::SetPartitionData (target_map, part, "create", false);
	    if( size(mount_options) > 0 && !haskey(p, "fstopt" ) )
		    target_map = Storage::SetPartitionData (target_map, part, "fstopt", mount_options);
	    if( haskey(p, "fstopt" ) )
		    target_map = Storage::SetPartitionData (target_map, part, "fstopt", p["fstopt"]:"");
            if( haskey( p, "mountby" ) )
                target_map = Storage::SetPartitionData (target_map, part, "mountby", p["mountby"]:`device);
	});

        Storage::SetTargetMap (target_map);
        return true;
    }

    /**
     * Handle /etc/fstab usage
     * @return boolean
     */
    define boolean handle_fstab()
    {
        y2milestone("entering handle_fstab");

        if (!RootPart::didSearchForRootPartitions)
        {
            UI::OpenDialog (`opt(`decorated ),
                            `Label(_("Evaluating root partition. One moment please...")));
            RootPart::FindRootPartitions ();
            UI::CloseDialog ();
        }

        if (RootPart::numberOfValidRootPartitions == 0)
        {
            // a popup
            Popup::Message(_("No Linux root partition found."));
            return false;
        }

        // We must only change RootPart::selectedRootPartition if booting
        // is inevitable.
        string rp = fstab["root_partition"]:"";
        list<map> fstab_partitions = fstab["partitions"]:[];

        if (RootPart::numberOfValidRootPartitions == 1)
        {
            RootPart::SetSelectedToValid ();
        }
        else if ( rp == ""){
            Popup::Message(_("Multiple root partitions found, but you did not configure
which root partition should be used.  Automatic installation not possible.
"));
            return false;
        }
        else if ( haskey(RootPart::rootPartitions, rp) 
                && RootPart::numberOfValidRootPartitions > 1)
        {
            RootPart::selectedRootPartition = rp;
        }

        RootPart::MountPartitions(RootPart::selectedRootPartition);
        SetFormatPartitions (fstab_partitions);
        RootPart::UnmountPartitions (true);
        return true;
    }


    /**
     * Create partition plan
     * @return boolean
     */
    global define boolean Write() {
        y2milestone("entering Write");
        Storage::SetRecursiveRemoval( true );

        if (read_fstab)
            return (handle_fstab());

        map <string, map> initial_target_map = Storage::GetTargetMap();
        y2milestone("Target map: %1", initial_target_map );

        Storage::SetPartDisk( find_first_disk("") );

        AutoTargetMap =  set_devices(AutoPartPlan);
        if (AutoTargetMap == nil || AutoTargetMap == $[])
            return false;

        y2milestone("AutoTargetMap: %1",  AutoTargetMap);
        
        // return list of available devices
        list<string> disk_devices = maplist( string k, map e,
                                             filter( string l, map f, Storage::GetTargetMap(),
                                                     ``(Storage::IsRealDisk( f ))), ``(k));

        y2milestone("disk_devices: %1", disk_devices );

        boolean result = false;

        foreach (string device, map data, AutoTargetMap, ``{
                if ( Storage::IsRealDisk( data) &&
                     data["initialize"]:false == true) {
                        initial_target_map[device,"delete"] = true;
                        Storage::SetTargetMap(initial_target_map);
                }
        });
        y2milestone("Target map after initialzing disk: %1", Storage::GetTargetMap());

        foreach (string device, map data, AutoTargetMap, ``{
            if( size(filter( map e, data["partitions"]:[],
                  ``(e["mount"]:""==Partitions::BootMount() || 
                    (e["partition_id"]:0 == Partitions::FsidBoot() && Partitions::FsidBoot() != 131 ) ))) > 0 ) {
                planHasBoot = true;
                break;
            }
        });
        y2milestone("plan has boot: %1", planHasBoot);

        foreach (string device, map data, AutoTargetMap,
                 ``{
            if( !haskey( Storage::GetTargetMap(), device ) && data["type"]:`CT_DISK == `CT_DISK ) {
                Report::Error( sformat( _("device '%1' not found by storage backend"), device ) );
                y2milestone("device %1 not found in TargetMap", device);
            }

            if ( Storage::IsRealDisk( data) )
            {
                ZeroNewPartitions = data["zero_new_partitions"]:true; // that's not really nice. Just an undocumented fallback which should never be used
                y2milestone("Creating partition plans for %1", device);
                
                map sol = find_matching_disk([device], Storage::GetTargetMap(), data );	  
                if (size(sol) > 0 )
                    result = true;
                    
                y2milestone("solutions: %1", sol);
                map <string, map> tm = Storage::GetTargetMap();
                tm[device] =    process_partition_data(device, sol);

        SearchRaids(tm);
                Storage::SetTargetMap(tm);
        }
        });

        return result;
    }


    /**
     * Build the id for a partition entry in the man table.
     * @parm disk_dev_name name of the devie e.g.: /dev/hda
     * @parm nr number of the partition e.g.: 1
     * @return string e.g.: 01./dev/hda
     */
    define string  build_id(  string disk_dev_name , any nr )
    {
        return (sformat( "%1:%2", disk_dev_name, nr));
    }


    /**
     * Partitioning Overview
     * @return list Overview
     */
    global define list Overview()
    {
        y2milestone("entering Overview");

        map allfs = FileSystems::GetAllFileSystems(true, true);
        list drives_table = [];

        string id = "";
        foreach(map d, AutoPartPlan,
                ``{
            id = d["device"]:"";
            term a = `item(`id(id), d["device"]:"", "", "", "", "", "" );

            drives_table = add (drives_table, a);

            list<map> partitions = d["partitions"]:[];
            integer start_id = 1;

            if ( size (partitions) > 0 )
            {
                foreach(map p, partitions, ``{
                    id = build_id(d["device"]:"" , start_id );

                    term b = `item(`id(id));
                    b = add (b, "");

                    b=add(b, p["mount"]:"" );
                    b=add(b, p["size"]:"");

                    if (!haskey(p, "filesystem_id"))
                    {
                        b=add(b, Partitions::FsIdToString(p["partition_id"]:131));
                    }
                    else
                    {
                        b=add(b, Partitions::FsIdToString(p["filesystem_id"]:131));
                    }

                    map fs = allfs[p["filesystem"]:`nothing]:$[];
                    string fs_name = fs[`name]:"";

                    b=add(b, fs_name);

                    if ( size( p["region"]:[] ) > 0 )
                    {
                        b=add(b, sformat("%1 - %2", p["region",0]:0, p["region",1]:0));
                    }
                    else
                    {
                        b=add(b, "");
                    }

                    drives_table = add(drives_table, b);
                    start_id = start_id + 1;
                });
            }

        });

        integer entries = size(drives_table);
        list reversed_table = [];
        integer counter = entries;

        term tmp = `item(`id(`empty));

        while (counter != 0)
        {
            reversed_table=add(reversed_table, drives_table[counter -1]:tmp);
            counter = counter - 1;

        }
        y2debug("table: %1", drives_table );
        return drives_table;


    }



    // EOF
}

ACC SHELL 2018