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
/
include
/
autoinstall
/
autopart.ycp
< prev
next >
Wrap
Text File
|
2006-11-29
|
65KB
|
1,573 lines
/*
$Id: autopart.ycp 33409 2006-10-13 14:22:46Z ug $
*/
{
textdomain "autoinst";
import "FileSystems";
include "partitioning/partition_defines.ycp";
map get_gap_info( map disk, map pd, boolean add_exist_linux );
map add_cylinder_info( map conf, map gap );
map get_perfect_list( list ps, map g );
map process_partition_data( string dev, map solution );
map find_matching_disk( list<string> disks, map target, map conf );
map try_resize_windows( map disk );
map remove_possible_partitions( map disk, map conf );
map distribute_space( integer rest, list weights, list added, list ps );
void add_part_recursive( list ps, map g );
map normalize_gaps( list ps, map g );
integer do_weighting( list ps, map g );
symbol cur_mode = `free;
integer cur_weight = -10000;
map cur_gap = $[];
list GetNoneLinuxPartitions(string device) {
list ret = [];
foreach ( string dev, map disk, Storage::GetTargetMap(), ``{
if( Storage::IsRealDisk( disk ) && dev == device)
{
list<map> l = (list<map>) filter( map p, disk["partitions"]:[],
``(!p["delete"]:false &&
!p["format"]:false &&
!Partitions::IsLinuxPartition(p["fsid"]:0)) );
l = filter(map p, l, ``(!contains( [`xfs, `ext2, `ext3, `jfs, `reiser],
p["used_fs"]:`unknown)));
l = filter(map p, l,
``(!FileSystems::IsSystemMp( p["mount"]:"", false )));
if( size(l)>0 )
{
list<integer> ln = maplist( map p, l, ``(p["nr"]:0));
ret = union( ret, ln );
}
}
});
y2milestone( "GetNoneLinuxPartitions ret=%1", ret );
return( ret );
}
list<integer> GetAllPartitions(string device) {
list<integer> ret = [];
foreach ( string dev, map disk, Storage::GetTargetMap(), ``{
if( Storage::IsRealDisk( disk ) && dev == device)
{
list<integer> l = maplist( map p, disk["partitions"]:[],
``(p["nr"]:0));
ret = (list<integer>)union( ret, l );
}
});
y2milestone( "All Partitions ret=%1", ret );
return( ret );
}
/**
* Read partition data from XML control file
* @return map flexible propsal map
*/
define list<map> preprocess_partition_config(list<map> xmlflex) {
y2debug("xml input: %1", xmlflex );
map<string,any> tm = Storage::GetTargetMap();
list<map>partitioning = maplist(map d, xmlflex, ``{
foreach( string key, [ "keep_partition_id", "keep_partition_num"], ``{
list num = [];
list<string> nlist = splitstring(d[key]:"", ",");
foreach( string n, nlist, ``{ num = union( num, [tointeger(n)] );});
d[key] = num;
});
list fsys = [];
list<string> nlist = splitstring( d["keep_partition_fsys"]:"" , "," );
foreach( string n, nlist,
``{
symbol fs = FileSystems::FsToSymbol(n);
if( fs != `none )
{
fsys = union( fsys, [ fs ] );
}
});
d["keep_partition_fsys"] = fsys;
list<map> user_partitions = d["partitions"]:[];
if (size(user_partitions) == 0)
{
y2milestone("no partitions specified, creating default scheme");
map root = $[];
root["mount"] = "/";
root["size"] = "max";
map swap = $[];
swap["mount"] = "swap";
swap["size"] = "auto";
user_partitions=add(user_partitions, swap);
user_partitions=add(user_partitions, root);
}
list partitions = [];
foreach(map partition, user_partitions,
``{
if (haskey(partition, "maxsize"))
{
partition["max"] = kmgt_str_to_byte(partition["maxsize"]:"");
}
if (partition["size"]:"" != "")
{
string s = partition["size"]:"";
if( tolower(s) == "auto" )
{
partition["size"] = -1;
}
else if( tolower(s) == "max" )
{
partition["size"] = 0;
}
else
{
partition["size"] = kmgt_str_to_byte( s );
}
}
if( partition["size"]:0 == -1 && partition["mount"]:"" == "swap" )
{
partition["size"] = 1024*1024*Partitions::SwapSizeMb(0);
}
if( partition["mount"]:"" == Partitions::BootMount() )
{
if( partition["size"]:0 == -1 )
partition["size"] = Partitions::MinimalNeededBootsize();
if( partition["filesystem"]:`none == `none )
partition["filesystem"] = Partitions::DefaultBootFs();
if( partition["filesystem_id"]:0 == 0 )
partition["filesystem_id"] = Partitions::FsidBoot();
//partition["max_cyl"] = Partitions::BootCyl();
}
if( partition["size"]:0 == -1 )
partition["size"] = 0;
if (partition["used_by_type"]:`UB_NONE==`UB_LVM)
partition["filesystem_id"] = Partitions::fsid_lvm;
else if (partition["used_by_type"]:`UB_NONE==`UB_EVMS)
partition["filesystem_id"] = Partitions::fsid_lvm;
else if (partition["used_by_type"]:`UB_NONE==`UB_MD)
partition["filesystem_id"] = Partitions::fsid_raid;
partition["fsid"] = partition["filesystem_id"]:Partitions::fsid_native;
y2debug("partition: %1", partition);
partitions = add( partitions, partition );
});
if (d["type"]:`CT_UNKNONW!=`CT_LVM && d["type"]:`CT_UNKNONW!=`CT_EVMS) {
d["partitions"] = partitions;
}
return (d);
});
y2milestone( "conf: %1", partitioning );
return( partitioning );
}
define map try_add_boot( map conf, map disk ) {
boolean boot =
size(filter( map e, conf["partitions"]:[],
``(e["mount"]:""==Partitions::BootMount() || (e["partition_id"]:0 == Partitions::FsidBoot() && Partitions::FsidBoot() != 131 ) ))) > 0;
boolean root = size(filter( map e, conf["partitions"]:[],
``(e["mount"]:""=="/"))) > 0;
map tc = (map) eval(conf);
if( !boot && root &&
(disk["cyl_count"]:0 > Partitions::BootCyl() ||
Arch::ia64 () || Arch::ppc () || Arch::sparc ()) )
{
map pb = $[];
if( ! Arch::ppc () ) {
pb["mount"] = Partitions::BootMount();
pb["fsys"] = Partitions::DefaultBootFs();
}
pb["size"] = Partitions::MinimalNeededBootsize();
pb["filesystem"] = Partitions::DefaultBootFs();
pb["fsid"] = Partitions::FsidBoot(); // FIXME: might be useless
pb["filesystem_id"] = Partitions::FsidBoot();
pb["id"] = Partitions::FsidBoot(); // FIXME: might be useless
pb["auto_added"] = true;
pb["type"] = `primary; // FIXME: might be useless
pb["partition_type"] = "primary";
pb["nr"] = 1;
//pb["max_cyl"] = Partitions::BootCyl();
//tc["partitions"] = add( tc["partitions"]:[], pb );
tc["partitions"] = merge( [ pb ], tc["partitions"]:[] );
y2milestone( "boot added automagically pb %1", pb );
}
return( tc );
}
/**
* Find matching disk
*/
define map find_matching_disk( list<string> disks, map target, map conf )
``{
map<string,map> solutions = $[];
cur_weight = -100000;
cur_gap = $[];
foreach( string k, disks,
``{
map e = target[k]:$[];
map pd = conf;
y2milestone( "processing disk %1", k );
y2milestone( "parts %1", conf["partitions"]:[] );
map tc = try_add_boot( conf, e );
cur_mode = `free;
if( !tc["prefer_remove"]:false )
{
map gap = get_gap_info( e, pd , false );
tc = add_cylinder_info( tc, gap );
map l = get_perfect_list( tc["partitions"]:[], gap );
if( size(l)>0 )
{
solutions[k] = eval(l);
solutions[k,"disk"] = eval(e);
}
cur_mode = `reuse;
map egap = get_gap_info( e, pd, true );
if( size(egap["gap"]:[]) > size(gap["gap"]:[]) )
{
tc = add_cylinder_info( tc, egap );
l = get_perfect_list( tc["partitions"]:[], egap );
if( size(l)>0 &&
(!haskey(solutions,k) ||
(haskey( l, "weight" ) &&
l["weigth"]:0 > solutions[k,"weigth"]:0 )))
{
y2milestone( "solution reuse existing" );
solutions[k] = eval(l);
solutions[k,"disk"] = eval(e);
}
}
cur_mode = `resize;
map rw = try_resize_windows( e );
if( size( filter( map p, rw["partitions"]:[],
``(haskey(p, "winfo")) ))>0 )
{
egap = get_gap_info( rw, pd, true );
tc = add_cylinder_info( tc, egap );
l = get_perfect_list( tc["partitions"]:[], egap );
if( size(l)>0 &&
(!haskey(solutions,k) ||
(haskey( l, "weight" ) &&
l["weigth"]:0 > solutions[k,"weigth"]:0 )))
{
y2milestone( "solution resizing windows" );
solutions[k] = eval(l);
solutions[k,"disk"] = eval(rw);
}
}
}
else
{
cur_mode = `free;
map rp = remove_possible_partitions( e, tc );
map gap = get_gap_info( rp, pd, false );
tc = add_cylinder_info( tc, gap );
map l = get_perfect_list( tc["partitions"]:[], gap );
if( size(l)>0 )
{
solutions[k] = eval(l);
solutions[k,"disk"] = eval(rp);
}
}
});
map ret = $[];
if( size(solutions)>0 )
{
foreach( string k, map e, solutions,
``{
y2milestone( "disk %1 weight %2", k, e["weight"]:0 );
});
list<string> disks = maplist( string k, map e, solutions, ``(k) );
disks = sort( string a, string b, disks,
``(solutions[a,"weight"]:0>solutions[b,"weight"]:0));
y2milestone( "sorted disks %1", disks );
ret = solutions[disks[0]:""]:$[];
ret["device"] = disks[0]:"";
}
return( ret );
}
/**
* Process partition data
*/
define map process_partition_data( string dev, map solution )
``{
map disk = solution["disk"]:$[];
list<map> partitions = [];
string value = "";
map mapvalue = $[];
boolean remove_boot = false;
if( size( filter( map e, solution["partitions"]:[],
``(e["mount"]:""==Partitions::BootMount() &&
e["auto_added"]:false)))>0 )
{
foreach( map e, solution["solution","gap"]:[],
``{
foreach( list a, e["added"]:[],
``{
integer pindex = a[0]:0;
if( solution["partitions",pindex,"mount"]:"" == "/" &&
disk["cyl_count"]:0 > Partitions::BootCyl() &&
e["end"]:0 <= Partitions::BootCyl() )
{
remove_boot = true;
}
});
});
}
integer index = 0;
if( remove_boot )
{
foreach( map e, solution["solution","gap"]:[],
``{
list nlist = [];
foreach( list a, e["added"]:[],
``{
integer pindex = a[0]:0;
if( solution["partitions",pindex,"mount"]:"" ==
Partitions::BootMount() )
{
integer rest = a[2]:0;
y2milestone( "remove unneeded %3 %1 cyl %2",
e["added"]:[], rest, Partitions::BootMount() );
list<list> nlist = filter( list l, e["added"]:[], ``(l[0]:0!=pindex));
if( size(nlist)>0 && !e["exists"]:false )
{
list weight = maplist( list l, nlist, ``(l[2]:0) );
map r = $[];
r = distribute_space( rest, weight, nlist,
solution["partitions"]:[] );
nlist = eval(r["added"]:[]);
solution["solution","gap",index,"cylinders"] =
e["cylinders"]:0 - r["diff"]:0;
}
solution["solution","gap",index,"added"] = eval(nlist);
y2milestone( "remove unneeded %2 %1", e["added"]:[],
Partitions::BootMount() );
}
pindex = pindex+1;
});
index = index + 1;
});
}
index = 0;
foreach( map e, solution["solution","gap"]:[],
``{
if( !e["exists"]:false && e["cylinders"]:0>0 )
{
integer increase = 0;
list<integer> weight =
maplist( list l, e["added"]:[],
``(solution["partitions",l[0]:0,"grow"]:false ? 1 : 0) );
if( find( integer l, weight, ``(l>0) ) != nil )
{
map r = $[];
r = distribute_space( e["cylinders"]:0, weight, e["added"]:[],
solution["partitions"]:[] );
solution["solution","gap",index,"added"] = eval(r["added"]:[]);
solution["solution","gap",index,"cylinders"] =
e["cylinders"]:0 - r["diff"]:0;
y2milestone( "increase increasable p %1 cyl %2",
solution["solution","gap",index,"added"]:[],
solution["solution","gap",index,"cylinders"]:0 );
}
}
index = index + 1;
});
foreach( map e, solution["solution","gap"]:[],
``{
if( e["exists"]:false )
{
integer index = 0;
integer pindex = e["added",0,0]:0;
string mount = solution["partitions",pindex,"mount"]:"";
integer fsid = Partitions::fsid_native;
if( mount == "swap" )
{
fsid = Partitions::fsid_swap;
}
if( solution["partitions",pindex,"id"]:0 != 0 )
{
fsid = solution["partitions",pindex,"id"]:0;
}
foreach( map p, disk["partitions"]:[],
``{
if( !p["delete"]:false && p["nr"]:0 == e["added",0,1]:0 )
{
p["format"] = solution["partitions",pindex,"format"]:true;
if( solution["partitions",pindex,"resize"]:false == true ) {
p["resize"] = true;
p["region"] = solution["partitions",pindex,"region"]:[];
}
p["mount"] = mount;
if (e["reuse"]:false)
p["used_fs"] = solution["partitions",pindex,"filesystem"]:p["detected_fs"]:`reiser;
else
p["used_fs"] = solution["partitions",pindex,"filesystem"]:`reiser;
value = solution["partitions",pindex,"fstopt"]:"";
if( size(value)>0 )
{
p["fstopt"] = value;
}
else
{
p["fstopt"] = FileSystems::DefaultFstabOptions( p );
}
mapvalue = solution["partitions",pindex,"fs_options"]:$[];
if( size(mapvalue)>0 )
{
p["fs_options"] = mapvalue;
}
value = solution["partitions",pindex,"label"]:"";
if( size(value)>0 )
{
symbol mb = solution["partitions",pindex,"mountby"]:`no_mb;
if( mb != `no_mb ) {
p["mountby"] = mb;
}
p["label"] = value;
}
if (solution["partitions",pindex,"loop_fs"]:false
|| solution["partitions",pindex,"crypt_fs"]:false)
{
//p["loop_fs"] = solution["partitions",pindex,"crypt_fs"]:false;
p["enc_type"] = solution["partitions",pindex,"enc_type"]:`twofish;
Storage::UpdateClassified( p["device"]:"",
solution["partitions",pindex,"crypt_key"]:"" );
//p["crypt"] = solution["partitions",pindex,"crypt"]:"twofish256";
}
if( p["fsid"]:0 != fsid )
{
p["change_fsid"] = true;
p["ori_fsid"] = p["fsid"]:0;
p["fsid"] = fsid;
}
if (solution["partitions",pindex,"lvm_group"]:"" != "")
{
p["used_fs"] = `unknown;
p["fsid"] = Partitions::fsid_lvm;
p["format"] = false;
p["lvm_group"] = solution["partitions",pindex,"lvm_group"]:"";
p["mount"] = "";
p["fstype"] = "Linux LVM";
}
else if (solution["partitions",pindex,"evms_group"]:"" != "") {
p["used_fs"] = `unknown;
p["fsid"] = Partitions::fsid_lvm;
p["format"] = false;
string lvm = (solution["partitions",pindex,"evms_group"]:true)?("lvm2"):("lvm");
p["evms_group"] = "evms/"+lvm+"/"+solution["partitions",pindex,"evms_group"]:"";
p["mount"] = "";
p["fstype"] = "EVMS";
}
else if (solution["partitions",pindex,"raid_name"]:"" != "")
{
p["used_fs"] = `unknown;
p["fsid"] = Partitions::fsid_raid;
p["format"] = false;
p["raid_name"] = solution["partitions",pindex,"raid_name"]:"";
p["raid_type"] = solution["partitions",pindex,"raid_type"]:"raid";
p["mount"] = "";
p["fstype"] = "Linux RAID";
}
disk["partitions",index] = p;
y2milestone( "reuse auto partition %1", p );
}
index = index + 1;
});
}
else
{
list region = [ e["start"]:0, e["end"]:0-e["start"]:0+1 ];
map part = $[];
if( e["extended"]:false && e["created"]:0 > 0 && size(e["created_primary"]:[]) == 0)
{
part["create"] = true;
part["nr"] = e["created"]:0;
part["device"] = Storage::GetDeviceName( dev, part["nr"]:-1 );
part["region"] = eval(region);
part["type"] = `extended;
part["fsid"] = Partitions::fsid_extended_win;
part["fstype"] = Partitions::FsIdToString( part["fsid"]:0 );
y2milestone( "extended auto partition %1", part );
partitions = add( partitions, eval(part));
}
foreach( list a, e["added"]:[],
``{
part = $[];
integer pindex = a[0]:0;
string mount = solution["partitions",pindex,"mount"]:"";
integer fsid = Partitions::fsid_native;
part["format"] = solution["partitions",pindex,"format"]:true;
if( mount == "swap" )
{
fsid = Partitions::fsid_swap;
}
if( solution["partitions",pindex,"filesystem_id"]:0 != 0 )
{
fsid = solution["partitions",pindex,"filesystem_id"]:0;
if( !haskey( solution["partitions",pindex]:$[], "filesystem" ))
{
part["format"] = false;
}
y2milestone( "partition id %1 format %2 part %3", fsid,
part["format"]:false,
solution["partitions",pindex]:$[] );
}
part["create"] = true;
part["nr"] = a[1]:0;
part["device"] = Storage::GetDeviceName( dev, part["nr"]:0 );
region[1] = a[2]:0;
part["region"] = eval(region);
region[0] = region[0]:0 + region[1]:0;
part["type"] = `primary;
if( e["extended"]:false )
{
part["type"] = `logical;
}
if(contains(e["created_primary"]:[], a[1]:0 ))
{
part["type"] = `primary;
}
part["mount"] = mount;
symbol mb = solution["partitions",pindex,"mountby"]:`no_mb;
if( mb != `no_mb ) {
part["mountby"] = mb;
}
part["used_fs"] =
solution["partitions",pindex,"filesystem"]:((mount == "swap")?(`swap):(`reiser));
value = solution["partitions",pindex,"fstopt"]:"";
if( size(value)>0 )
{
part["fstopt"] = value;
}
else
{
part["fstopt"] = FileSystems::DefaultFstabOptions( part );
}
mapvalue = solution["partitions",pindex,"fs_options"]:$[];
if( size(mapvalue)>0 )
{
part["fs_options"] = mapvalue;
}
if (solution["partitions",pindex,"loop_fs"]:false
|| solution["partitions",pindex,"crypt_fs"]:false)
{
//part["loop_fs"] = solution["partitions",pindex,"crypt_fs"]:false;
part["enc_type"] = solution["partitions",pindex,"enc_type"]:`twofish;
Storage::UpdateClassified( part["device"]:"",
solution["partitions",pindex,"crypt_key"]:"" );
//part["crypt"] = solution["partitions",pindex,"crypt"]:"twofish256";
}
value = solution["partitions",pindex,"label"]:"";
if( size(value)>0 )
{
part["label"] = value;
}
part["fsid"] = fsid;
part["fstype"] = Partitions::FsIdToString( fsid );
if (solution["partitions",pindex,"lvm_group"]:"" != "")
{
part["used_fs"] = `unknown;
part["fsid"] = Partitions::fsid_lvm;
part["format"] = false;
part["lvm_group"] = solution["partitions",pindex,"lvm_group"]:"";
part["mount"] = "";
part["fstype"] = "Linux LVM";
}
else if (solution["partitions",pindex,"evms_group"]:"" != "") {
part["used_fs"] = `unknown;
part["fsid"] = Partitions::fsid_lvm;
part["format"] = false;
part["evms_group"] = solution["partitions",pindex,"evms_group"]:"";
part["mount"] = "";
part["fstype"] = "EVMS";
}
else if (solution["partitions",pindex,"raid_name"]:"" != "")
{
part["used_fs"] = `unknown;
part["fsid"] = Partitions::fsid_raid;
part["format"] = false;
part["raid_name"] = solution["partitions",pindex,"raid_name"]:"";
part["raid_type"] = solution["partitions",pindex,"raid_type"]:"raid";
part["mount"] = "";
part["fstype"] = "Linux RAID";
}
y2milestone( "auto partition %1", part );
partitions = add( partitions, eval(part));
if (a[1]:0 + 1 == e["created"]:0 && e["extended"]:false )
{
part = $[];
list ext_region = [ region[0]:0, e["end"]:0-region[0]:0+1 ];
part["create"] = true;
part["nr"] = e["created"]:0;
part["device"] = Storage::GetDeviceName( dev, part["nr"]:-1 );
part["region"] = ext_region;
part["type"] = `extended;
part["fsid"] = Partitions::fsid_extended_win;
part["fstype"] = Partitions::FsIdToString( part["fsid"]:0 );
y2milestone( "extended auto partition %1", part );
partitions = add( partitions, eval(part));
}
});
partitions = sort( map a, map b, partitions, ``(a["nr"]:0<b["nr"]:0));
}
});
disk["partitions"] = union( disk["partitions"]:[], partitions );
y2milestone( "disk %1", disk );
return( disk );
}
define map find_matching_partition_size(map gap, integer nr)
{
list mg = filter(map g, gap["gap"]:[], ``(g["nr"]:-1 == nr && g["reuse"]:false));
y2milestone("usepart partition: %1", mg[0]:$[]);
return mg[0]:$[];
}
/**
* Add Cylinder Information
*/
define map add_cylinder_info( map conf, map gap )
``{
integer big_cyl = 4 * 1024 * 1024 * 1024;
integer cyl_size = gap["cyl_size"]:1;
/*
// FIXME: Why is sorting needed here?
conf["partitions"] =
sort( map a, map b, conf["partitions"]:[],
``({
if( a["max_cyl"]:big_cyl != b["max_cyl"]:big_cyl )
return( a["max_cyl"]:big_cyl < b["max_cyl"]:big_cyl );
else
return( a["size"]:0 > b["size"]:0 );
}));
*/
y2milestone( "parts %1", conf["partitions"]:[] );
integer sum = 0;
conf["partitions"] = maplist( map p, conf["partitions"]:[],
``{
sum = sum + p["pct"]:0;
p["cylinders"] = (p["size"]:0+cyl_size-1)/cyl_size;
// p["cylinders"] = (p["size"]:0)/cyl_size;
map mg = find_matching_partition_size(gap,p["usepart"]:0);
if (mg != $[])
{
p["cylinders"] = mg["cylinders"]:0;
p["size"] = mg["size"]:0;
if (p["usepart"]:0< gap["max_primary"]:0)
{
p["partition_type"] = "primary";
}
}
if( p["cylinders"]:0 == 0 )
{
p["cylinders"] = 1;
}
return( p );
});
y2milestone( "sum %1", sum );
y2milestone( "parts %1", conf["partitions"]:[] );
if( sum>100 )
{
integer rest = sum - 100;
conf["partitions"] = maplist( map p, conf["partitions"]:[],
``{
if( haskey( p, "pct" ) )
{
integer pct = p["pct"]:0;
integer diff = ((rest * pct) + sum/2) / sum;
sum = sum - pct;
rest = rest - diff;
p["pct"] = pct - diff;
}
return( p );
});
}
conf["partitions"] = maplist( map p, conf["partitions"]:[],
``{
if( haskey( p, "pct" ) )
{
integer cyl = gap["sum"]:0 / 100 * p["pct"]:0;
cyl = (cyl+cyl_size/2) / cyl_size;
if( cyl == 0 )
{
cyl = 1;
}
p["want_cyl"] = cyl;
}
if( p["max"]:0 > 0 )
{
integer cyl = (p["max"]:0+cyl_size-1) / cyl_size;
p["size_max_cyl"] = cyl;
if( p["want_cyl"]:0 > cyl )
{
p["want_cyl"] = cyl;
}
}
return( p );
});
y2milestone( "parts %1", conf["partitions"]:[] );
return( conf );
}
/**
* Compute perfect partition list
* @param ps Partition List from control file
* @param g Calculated Gaps
* @return map Best partition list using the gaps
*/
define map get_perfect_list( list ps, map g ) {
y2milestone( "requested partitions %1", ps );
y2milestone( "calculated gaps %1", g );
/**
* If gaps are available
* AND (
* extended partitions are possible and there are
* primaries left and number of requested partitions(+1) is less than all available
* primaries and logical slots
* OR
* extended is not possible and number of requested partitions is less than all
* available primaries and logical slots )
*/
if( size(g["gap"]:[])>0 &&
((g["extended_possible"]:false &&
// size(g["free_pnr"]:[])>0 && // reusing all 4 primaries will fail with this
size(ps)+1 <= size(g["ext_pnr"]:[])+size(g["free_pnr"]:[])) ||
(!g["extended_possible"]:false &&
size(ps) <= size(g["ext_pnr"]:[])+size(g["free_pnr"]:[]))) )
{
map lg = (map) eval(g);
// prepare local gap var
lg["gap"] = maplist( map e, lg["gap"]:[],
``{
e["orig_cyl"] = e["cylinders"]:0;
e["added"] = [];
return( e );
});
lg["procpart"] = 0;
list lp = (list) eval(ps);
if( g["extended_possible"]:false &&
size(ps)+1>=size(g["free_pnr"]:[]) &&
size(filter(map up, (list<map>)ps, ``(
up["partition_type"]:"none" == "primary" ||
contains(lg["free_pnr"]:[], up["partition_nr"]:0) ))) == 0
)
{
y2milestone( "creating extended" );
integer index = 0;
foreach( map e, lg["gap"]:[],
``{
if( !e["exists"]:false )
{
map gap = (map) eval(lg);
gap["gap",index,"created"] = gap["free_pnr",0]:1;
gap["free_pnr"] = remove( gap["free_pnr"]:[1], 0 );
gap["gap",index,"extended"] = true;
add_part_recursive( ps, gap );
}
index = index+1;
});
}
else
{
y2milestone( "not creating extended now" );
add_part_recursive( ps, lg );
}
}
map ret = $[];
if( size(cur_gap)>0 )
{
ret["weight"] = cur_weight;
ret["solution"] = eval(cur_gap);
ret["partitions"] = eval(ps);
}
y2milestone( "ret weight %1", ret["weight"]:-1000000 );
y2milestone( "ret solution %1", ret["solution","gap"]:[] );
return( ret );
}
/**
* Recursive Adding of partitions
* @param ps Partition list from control file
* @param g Calculated gaps
* @return void
*/
define void add_part_recursive( list ps, map g )
``{
y2milestone( "partition index %1", g["procpart"]:0 );
y2milestone( "partitions %1", ps );
y2milestone( "gap %1", g );
// creation_needed indicates the case, that we do not
// create a single partition but are reusing some
boolean creation_needed = false;
foreach( map p, (list<map>)ps, ``{
if( p["create"]:true == true ) {
creation_needed = true;
}
});
y2milestone("creation is needed? %1",creation_needed);
map lg = (map) eval(g);
integer gindex = 0;
integer pindex = lg["procpart"]:0;
map part = ps[pindex]:$[];
lg["procpart"] = pindex + 1;
y2milestone( "working on partition %1", part );
foreach( map e, lg["gap"]:[],
``{
y2milestone( "start: gap section %1", e );
if( part["max_cyl"]:0 <= e["end"]:0 &&
part["cylinders"]:0 <= e["cylinders"]:0 &&
(!e["extended"]:false && (size(lg["free_pnr"]:[])>0 || ! creation_needed ) ||
e["extended"]:false && size(lg["ext_pnr"]:[])>0)
)
{
map llg = (map) eval(lg);
list addl = [ pindex ];
// number of needed primaries by user
integer sp = size(filter(map up, (list<map>)ps,
``(up["partition_type"]:"none" == "primary" ||
contains(llg["free_pnr"]:[], up["partition_nr"]:0))));
y2milestone("number of primaries requested: %1", sp );
integer cp = 0;
foreach(map gg, llg["gap"]:[], ``{
cp = cp + size(gg["created_primary"]:[]);
});
boolean ex = false;
y2milestone("number of created primaries: %1", cp );
// Extended
if( llg["extended_possible"]:false &&
!e["extended"]:false &&
size(ps)+1>=size(llg["free_pnr"]:[]) && // maybe not needed
cp == sp && sp > 0 )
{
y2milestone( "creating extended" );
map gap = (map) eval(lg);
llg["gap",gindex,"created"] = llg["free_pnr",0]:1;
llg["free_pnr"] = remove( llg["free_pnr"]:[1], 0 );
llg["gap",gindex,"extended"] = true;
// reset
llg["procpart"] = pindex ;
ex = true;
}
// Logical
else if( e["extended"]:false ) // ||
/*
( ps[pindex,"partition_type"]:"none" != "primary" &&
ps[pindex,"partition_type"]:"none" != "extended")
)
*/
{
if (!e["reuse"]:false)
{
addl = add( addl, llg["ext_pnr",0]:5 );
llg["ext_pnr"] = remove( llg["ext_pnr"]:[0], 0 );
} else {
addl = add( addl, e["nr"]:0 );
}
}
// Primary
else
{
if (e["exists"]:false)
{
addl = add( addl, e["nr"]:0 );
llg["gap",gindex,"created_primary"] = add(llg["gap",gindex,"created_primary"]:[],
e["nr"]:0 );
} else {
addl = add( addl, llg["free_pnr",0]:1 );
llg["gap",gindex,"created_primary"] = add(llg["gap",gindex,"created_primary"]:[],
llg["free_pnr",0]:1 );
llg["free_pnr"] = remove( llg["free_pnr"]:[0], 0 );
}
}
if (!ex)
{
llg["gap",gindex,"added"] =
add( llg["gap",gindex,"added"]:[], addl );
}
if (!ex) {
if( e["exists"]:false )
{
llg["gap",gindex,"cylinders"] = 0;
}
else
{
llg["gap",gindex,"cylinders"] =
llg["gap",gindex,"cylinders"]:0 - part["cylinders"]:0;
}
}
if( pindex+1 < size(ps) || ex )
{
add_part_recursive( ps, llg );
}
else
{
map ng = normalize_gaps(ps, llg);
integer val = do_weighting( ps, ng );
y2milestone( "val %1 cur_weight %2 size %3", val, cur_weight, size(cur_gap));
if( val > cur_weight || size(cur_gap)==0 )
{
cur_weight = val;
cur_gap = (map)eval(ng);
}
}
}
gindex = gindex+1;
});
};
/**
* Normalize Gaps
*/
define map normalize_gaps( list ps, map g )
``{
y2milestone( "normalize_gaps: gap %1", g );
integer gindex = 0;
integer pindex = 0;
foreach( map e, g["gap"]:[],
``{
y2milestone( "gap section %1", e );
if( e["exists"]:false )
{
if( size(e["added"]:[])>0 && size(e["added",0]:[])==2 )
{
e["added",0] = add( e["added",0]:[], e["orig_cyl"]:1 );
}
}
else
{
integer rest = e["cylinders"]:0;
integer needed = 0;
integer tidx = 0;
foreach( list p, e["added"]:[],
``{
tidx = p[0]:0;
if( ps[tidx,"want_cyl"]:0 > ps[tidx,"cylinders"]:0 )
{
needed = needed + ps[tidx,"want_cyl"]:0 -
ps[tidx,"cylinders"]:0;
}
});
y2milestone( "needed %1 rest %2", needed, rest );
if( needed > rest )
{
list tr = [];
list weight =
maplist( list l, e["added"]:[],
``({
integer idx = l[0]:0;
integer d = ps[idx,"want_cyl"]:0 -
ps[idx,"cylinders"]:0;
if( d>0 )
{
l = add( l, ps[idx,"cylinders"]:0 );
}
tr = add( tr, l );
return( d>0 ? d : 0 );
}));
y2milestone( "tr %1", tr );
map r = $[];
r = distribute_space( rest, weight, tr, ps );
g["gap",gindex,"added"] = eval(r["added"]:[]);
g["gap",gindex,"cylinders"] = e["cylinders"]:0 - r["diff"]:0;
y2milestone( "partly satisfy %1 cyl %2", g["gap",gindex,"added"]:[],
g["gap",gindex,"cylinders"]:0 );
}
else
{
g["gap",gindex,"cylinders"] = e["cylinders"]:0 - needed;
}
pindex = 0;
foreach( list p, g["gap",gindex,"added"]:[],
``{
if( size(p)<3 )
{
tidx = p[0]:0;
if( ps[tidx,"want_cyl"]:0 > ps[tidx,"cylinders"]:0 )
{
p = add( p, ps[tidx,"want_cyl"]:0 );
}
else
{
p = add( p, ps[tidx,"cylinders"]:0 );
}
g["gap",gindex,"added",pindex] = p;
y2milestone( "satisfy p %1 cyl %2", p, e["cylinders"]:0 );
}
pindex = pindex+1;
});
y2milestone( "added %1", g["gap",gindex,"added"]:[] );
}
gindex = gindex + 1;
});
gindex = 0;
foreach( map e, g["gap"]:[],
``{
if( !e["exists"]:false && e["cylinders"]:0>0 )
{
list<integer> weight = maplist( list l, e["added"]:[],
``(ps[l[0]:0,"size"]:0==0 ? 1 : 0) );
if( find( integer l, weight, ``(l>0) ) != nil )
{
map r = $[];
r = distribute_space( e["cylinders"]:0, weight, e["added"]:[],
ps );
g["gap",gindex,"added"] = eval(r["added"]:[]);
g["gap",gindex,"cylinders"] = e["cylinders"]:0 - r["diff"]:0;
y2milestone( "increase max p %1 cyl %2", g["gap",gindex,"added"]:[],
g["gap",gindex,"cylinders"]:0 );
}
}
gindex = gindex + 1;
});
gindex = 0;
foreach( map e, g["gap"]:[],
``{
if( !e["exists"]:false && e["cylinders"]:0>0 &&
e["cylinders"]:0 < g["disk_cyl"]:0/20 )
{
list weight = maplist( list l, e["added"]:[], ``(l[2]:0) );
map r = $[];
r = distribute_space( e["cylinders"]:0, weight, e["added"]:[], ps );
g["gap",gindex,"added"] = eval(r["added"]:[]);
g["gap",gindex,"cylinders"] = e["cylinders"]:0 - r["diff"]:0;
y2milestone( "close small gap p %1 cyl %2", g["gap",gindex,"added"]:[],
g["gap",gindex,"cylinders"]:0 );
}
gindex = gindex + 1;
});
y2milestone( "gap %1", g );
return( g );
};
/**
* Distribute Spaces
*/
define map distribute_space( integer rest, list weights, list added, list ps )
``{
integer diff_sum = 0;
integer sum = 0;
integer index = 0;
integer pindex = 0;
y2milestone( "rest %1 weights %2 added %3", rest, weights, added );
foreach( list p, (list<list>)added,
``{
pindex = p[0]:0;
if( ps[pindex,"size_max_cyl"]:0==0 || ps[pindex,"grow"]:false ||
ps[pindex,"size_max_cyl"]:0 > p[2]:0 )
{
sum = sum + weights[index]:0;
}
index = index+1;
});
index = 0;
y2milestone( "sum %1 rest %2 added %3", sum, rest, added );
foreach( list p, (list<list>)added,
``{
pindex = p[0]:0;
if( size(p)==3 && sum>0 &&
(ps[pindex,"size_max_cyl"]:0==0 || ps[pindex,"grow"]:false ||
ps[pindex,"size_max_cyl"]:0 > p[2]:0) )
{
integer diff = ((rest*weights[index]:0) + sum/2) / sum;
if( ps[pindex,"size_max_cyl"]:0>0 &&
!ps[pindex,"grow"]:false &&
diff > ps[pindex,"size_max_cyl"]:0-p[2]:0 )
{
diff = ps[pindex,"size_max_cyl"]:0-p[2]:0;
}
sum = sum - weights[index]:0;
rest = rest - diff;
added[index,2] = added[index,2]:0 + diff;
diff_sum = diff_sum + diff;
y2milestone( "sum %1 rest %2 diff %3 added %4", sum, rest, diff,
added[index]:[] );
}
index = index+1;
});
map ret = $[ "added":added, "diff" : diff_sum ];
y2milestone( "ret (distribute_space) %1", ret );
return( ret );
}
/**
* Calculate plan weights
*/
define integer do_weighting( list ps, map g )
``{
y2milestone( "gap %1", g["gap"]:[] );
integer ret = 0;
integer index = 0;
if( cur_mode == `free )
{
ret = 0;
}
if( cur_mode == `reuse )
{
ret = ret - 100;
}
else if( cur_mode == `resize )
{
ret = ret - 1000;
}
else if( cur_mode == `desparate )
{
ret = ret - 1000000;
}
y2milestone( "weight after mode ret %1", ret );
foreach( map e, g["gap"]:[],
``{
y2milestone( "added %1", e["added"]:[] );
if( !e["exists"]:false && e["cylinders"]:0 > 0 )
{
ret = ret - 5;
if( e["cylinders"]:0 < g["disk_cyl"]:0/20 )
{
ret = ret - 10;
}
y2milestone("weight (cyl) %1", ret );
}
y2milestone( "weight after gaps %1", ret );
foreach( list p, e["added"]:[],
``{
index = p[0]:0;
if( e["exists"]:false && ps[index,"mount"]:""=="swap" &&
e["swap"]:false )
{
ret = ret + 100;
y2milestone( "weight after swap reuse %1", ret );
}
if( ps[index,"want_cyl"]:0>0 )
{
integer diff = ps[index,"want_cyl"]:0 - p[2]:0;
integer normdiff = diff * 100 / p[2]:0;
if( diff < 0 )
{
normdiff = -normdiff;
}
else if( diff > 0 )
{
normdiff = normdiff / 10;
}
ret = ret - normdiff;
ret = ret + ps[index,"want_cyl"]:0*g["cyl_size"]:1 /
(100 * 1024 * 1024);
y2milestone( "after pct parts %1", ret );
}
if( ps[index,"size"]:0==0 )
{
ret = ret + p[2]:0 * g["cyl_size"]:1 / (50 * 1024 * 1024);
y2milestone( "after maximizes parts %1", ret );
}
if( ps[index,"size_max_cyl"]:0 > 0 &&
ps[index,"size_max_cyl"]:0 < p[2]:0 )
{
integer diff = p[2]:0 - ps[index,"size_max_cyl"]:0;
integer normdiff = diff * 100 / ps[index,"size_max_cyl"]:0;
ret = ret - normdiff;
y2milestone( "after maximal size %1", ret );
}
});
/*
if( e["cylinders"]:0 > 0 )
{
y2milestone("ret (before rounding): %1", ret);
ret = ret - (e["cylinders"]:0 * g["cyl_size"]:1) / (1024*1024*1024);
y2milestone("weight (after rounding): %1", ret);
}
*/
});
y2milestone( "weight: %1", ret );
return( ret );
};
/**
* Remove partitions
* @param disk disk data
* @param pm partitioning as in the control file.
* @return map the new partition map with removed partitions
*/
define map remove_possible_partitions( map disk , map pm)
{
boolean remove_special_partitions = pm["remove_special_partitions"]:false;
list keep_partition_num = pm["keep_partition_num"]:[];
list keep_partition_id = pm["keep_partition_id"]:[];
list keep_partition_fsys = pm["keep_partition_fsys"]:[];
// Special partitions
list nodelpart = [ 0x12, 0xde, 257 ];
// Handle <usepart> which is analog to create=false and partition_nr>0
foreach(map p, pm["partitions"]:[], ``{
if (p["usepart"]:0 != 0 )
keep_partition_num=add(keep_partition_num, p["usepart"]:0 );
});
map ret = (map)disk;
ret["partitions"] = maplist( map p, ret["partitions"]:[],
``{
integer fsid = p["fsid"]:0;
if( (remove_special_partitions ||
!contains( nodelpart, fsid ) ) &&
p["type"]:`primary != `extended &&
!contains( keep_partition_num, p["nr"]:0 ) &&
!contains( keep_partition_id, fsid ) &&
!contains( keep_partition_fsys, p["used_fs"]:`none ))
{
p["delete"] = true;
if (haskey(p, "raid_name")) {
p["old_raid_name"] = p["raid_name"]:"";
p=remove(p, "raid_name");
}
}
return( p );
});
integer max_prim = Partitions::MaxPrimary(disk["label"]:"msdos");
// delete extended if no logical remain
if( size( filter( map p, ret["partitions"]:[],
``(p["type"]:`primary == `extended)))>0 &&
size( filter( map p, ret["partitions"]:[],
``(p["nr"]:0>max_prim && !p["delete"]:false) ))==0 )
{
ret["partitions"] = maplist( map p, ret["partitions"]:[],
``{
if( p["type"]:`primary == `extended )
{
p["delete"] = true;
}
return( p );
});
}
y2milestone("after removal: %1", ret);
return( ret );
}
/*
define map remove_possible_partitions( map disk, map conf )
``{
list nodelpart = [ 0x12, 0xde, 257 ];
map ret = (map)eval(disk);
ret["partitions"] = maplist( map p, ret["partitions"]:[],
``{
integer fsid = p["fsid"]:0;
if( (conf["remove_special_partitions"]:false ||
!contains( nodelpart, fsid ) ) &&
p["type"]:`primary != `extended &&
!contains( conf["keep_partition_num"]:[], p["nr"]:0 ) &&
!contains( conf["keep_partition_id"]:[], fsid ) &&
!contains( conf["keep_partition_fsys"]:[], p["used_fs"]:`none ))
{
p["delete"] = true;
}
return( p );
});
integer max_prim = Partitions::MaxPrimary(disk["label"]:"msdos");
if( size( filter( map p, ret["partitions"]:[],
``(p["type"]:`primary == `extended)))>0 &&
size( filter( map p, ret["partitions"]:[],
``(p["nr"]:0>max_prim && !p["delete"]:false) ))==0 )
{
ret["partitions"] = maplist( map p, ret["partitions"]:[],
``{
if( p["type"]:`primary == `extended )
{
p["delete"] = true;
}
return( p );
});
}
return( ret );
};
*/
/**
* Try resizing windows partition
*
*/
define map try_resize_windows( map disk )
``{
integer cyl_size = disk["cyl_size"]:1;
map win = $[];
map ret = (map)eval(disk);
ret["partitions"] = maplist( map p, ret["partitions"]:[], ``{
integer fsid = p["fsid"]:0;
if( Partitions::IsDosPartition( fsid ) )
{
integer psize = (p["region",0]:0 + p["region",1]:1 - 1) * cyl_size;
win = Storage::GetFreeSpace( p["device"]:"", psize, `fat32,
false );
y2milestone( "win=%1", win );
if( win != nil && psize > 300*1024*1024 )
{
p["winfo"] = win;
p["region",1] = (win["new_size"]:0 + cyl_size - 1) / cyl_size;
y2milestone( "win part %1", p );
}
}
return( p );
});
return( ret );
};
/**
* Collect gap information
*
*/
define list<map> get_gaps( integer start, integer end,
map pd,
list<map> part,
boolean add_exist_linux )
``{
y2milestone("partitions: %1", pd["partitions"]:[] );
list<integer> usepart_p = maplist(map pa, pd["partitions"]:[],
``{
return pa["usepart"]:0;
});
list<integer> reuse = filter(integer i, usepart_p, ``(i!=0));
y2milestone("reuse: %1", reuse);
y2milestone( "start %1 end %2 add_exist %3", start, end, add_exist_linux );
list<map> ret = [];
map entry = $[];
foreach( map p, part,
``{
integer s = p["region",0]:0;
integer e = s + p["region",1]:1 - 1;
entry = $[];
y2milestone("Getting gap from part: %1", p );
y2milestone("start %1 s %2 e %3", start, s, e );
if( start < s )
{
entry["start"] = start;
entry["end"] = s-1;
ret = add( ret, eval(entry) );
}
if( add_exist_linux &&
(p["fsid"]:0==Partitions::fsid_native ||
p["fsid"]:0==Partitions::fsid_swap) )
{
entry["swap"] = p["fsid"]:0==Partitions::fsid_swap;
entry["start"] = s;
entry["end"] = e;
entry["exists"] = true;
entry["nr"] = p["nr"]:0;
ret = add( ret, entry );
}
if (contains(reuse, p["nr"]:0))
{
// This partition is to be used as specified in the control file
entry["swap"] = p["fsid"]:0==Partitions::fsid_swap;
entry["start"] = s;
entry["end"] = e;
entry["exists"] = true;
entry["reuse"] = true;
entry["nr"] = p["nr"]:0;
ret = add( ret, entry );
}
start = e+1;
});
if( start < end )
{
entry = $[];
entry["start"] = start;
entry["end"] = end;
ret = add( ret, entry );
}
y2milestone( "ret %1", ret );
return( ret );
}
/**
* Collect gap information
*
*/
define map get_gap_info( map disk, map pd, boolean add_exist_linux )
``{
map ret = $[];
list<map> gap = [];
list<map> plist = filter( map p, disk["partitions"]:[], ``(!p["delete"]:false) );
plist = sort( map a, map b, plist, ``(a["region",0]:0<b["region",0]:0) );
list exist_pnr = sort( maplist( map e, plist, ``(e["nr"]:0) ));
integer max_prim = Partitions::MaxPrimary(disk["label"]:"msdos");
boolean has_ext = Partitions::HasExtended( disk["label"]:"msdos" );
// check if we support extended partitions
if( has_ext )
{
// see if disk has an extended already
map ext = filter( map p, plist,
``(p["type"]:`primary == `extended))[0]:$[];
ret["extended_possible"] = size(ext)==0;
if( size(ext)>0 )
{
gap = get_gaps( ext["region",0]:0,
ext["region",0]:0 + ext["region",1]:1-1,
pd,
filter( map p, plist, ``(p["nr"]:0>max_prim)),
add_exist_linux );
gap = maplist( map e, gap,
``{
e["extended"]=true;
return e;
});
plist = filter( map p, plist, ``(p["nr"]:0<=max_prim));
}
}
else
{
ret["extended_possible"] = false;
}
gap = (list<map>)union( gap,
get_gaps( 0, disk["cyl_count"]:1-1, pd, plist, add_exist_linux ));
integer av_size = 0;
gap = maplist( map e, gap,
``{
e["cylinders"] = e["end"]:0 - e["start"]:0 + 1;
e["size"] = e["cylinders"]:0 * disk["cyl_size"]:1;
av_size = av_size + e["size"]:0;
return( e );
});
gap = maplist( map e, gap,
``{
e["sizepct"] = (e["size"]:0 * 201 / 2) / av_size;
if( e["sizepct"]:0 == 0 )
{
e["sizepct"] = 1;
}
return( e );
});
ret["cyl_size"] = disk["cyl_size"]:1;
ret["disk_cyl"] = disk["cyl_count"]:1;
ret["max_primary"] = disk["max_primary"]:0;
ret["sum"] = av_size;
integer max_pnr = max_prim;
integer pnr = 1;
list free_pnr = [];
y2milestone( "exist_pnr %1", exist_pnr );
while( pnr<=max_pnr )
{
if( !contains( exist_pnr, pnr ) )
{
free_pnr = add( free_pnr, pnr );
}
pnr = pnr + 1;
}
ret["free_pnr"] = free_pnr;
list<integer> ext_pnr = [ 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,
45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63];
integer max_logical = disk["max_logical"]:15;
if( max_logical<63 )
{
ext_pnr = filter( integer i, ext_pnr, ``(i<=max_logical));
}
if( !ret["extended_possible"]:false )
{
if( !has_ext )
{
ext_pnr = [];
}
else
{
integer maxext = exist_pnr[size(exist_pnr)-1]:4;
pnr = 5;
while( pnr<=maxext )
{
ext_pnr = remove( ext_pnr, 0 );
pnr = pnr+1;
}
}
}
ret["ext_pnr"] = ext_pnr;
ret["gap"] = sort(map a, map b, gap, ``(a["start"]:0<b["start"]:0));
y2milestone( "ret %1", ret );
return( ret );
}
}