home *** CD-ROM | disk | FTP | other *** search
- /**
- * File: modules/AutoinstStorage.ycp
- * Module: Auto-Installation
- * Summary: Storage
- * Authors: Anas Nashif <nashif@suse.de>
- *
- * $Id: AutoinstStorage.ycp 33388 2006-10-13 10:05:55Z ug $
- */
- {
- module "AutoinstStorage";
- textdomain "autoinst";
-
- import "Storage";
- import "RootPart";
- import "Partitions";
- import "FileSystems";
- import "Summary";
- import "Storage";
- import "Partitions";
- import "Popup";
-
- include "partitioning/partition_defines.ycp";
-
- // Read existing fstab and format partitions, but dont create anything
- // Use same mountpoints etc.
- global boolean read_fstab = false;
-
- // Fstab options
- global map fstab = $[];
-
- // Show warning for /boot on raid
- global boolean BootRaidWarning = true;
-
- // Show warning for /boot on lvm
- global boolean BootLVMWarning = true;
-
- // Show warning for /boot cyl <1024
- global boolean BootCylWarning = true;
-
- // 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 = $[];
-
- /**
- * 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;
- }
-
-
- include "autoinstall/autopart.ycp";
- include "autoinstall/autoinst_dialogs.ycp";
-
- global define string find_first_disk() {
- map <string, map> initial_target_map = Storage::GetTargetMap();
- y2milestone("Target map: %1", initial_target_map );
-
- string mbr_disk = "";
- foreach (string device, map disk, initial_target_map, ``{
- if (disk["bios_id"]:"" == "0x80")
- {
- y2milestone ("disk with bios_id 0x80: %1", device);
- mbr_disk = device;
- }
- });
-
- /* device guessing code enhanced */
- if( mbr_disk == "" ) {
- foreach (string device, map disk, initial_target_map, ``{
- if( disk["type"]:`x == `CT_DISK ) {
- y2milestone ("first real disk is: %1", device);
- mbr_disk = device;
- break;
- }
- });
- }
-
- y2milestone("mbr disk: %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;
- }
- }
- // 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);
- }
-
- /**
- * Dump the settings to a map, for autoinstallation use.
- * @return list
- */
- global define list<map> Export()
- {
- y2milestone("entering Export");
- list<map> clean_drives = maplist(map d, AutoPartPlan, ``{
- list p = maplist(map part, d["partitions"]:[] , ``{
- if (haskey(part, "fsid"))
- {
- part = remove(part, "fsid");
- }
- if (haskey(part, "used_fs")) {
- part = remove(part, "used_fs");
- }
- return part;
- });
- d["partitions"] = p;
-
- // this is to delete the dummy "auto" filled in by UI
- if( haskey(d,"device") && d["device"]:"" == "auto" ) {
- d = remove(d, "device");
- y2debug("device 'auto' dropped");
-
- }
- return d;
- });
-
- return clean_drives;
- }
-
- /**
- * 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( 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 {
- 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();
- settings = maplist( map d, settings, ``{
- string device = d["device"]:"";
- string udev_string = "";
- if( device == "" ) {
- d["device"] = find_first_disk();
- y2milestone("empty device in profile set to %1", d["device"]:"");
- } 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;
- }
- });
- });
- }
- 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+2)*cyl_size; // FIXME: why 2? 1 should be enough
- 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 = kmgt_str_to_byte( pe["size"]:"0" );
- 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["type"]:`x == `CT_EVMS ) {
- 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);
- 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;
- }
-
- /**
- * 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);
- RootPart::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 ( Storage::IsRealDisk( data) )
- {
- 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
- }
-