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 >
Wrap
Text File
|
2006-11-29
|
29KB
|
786 lines
/**
* 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
}