ACC SHELL
/**
* File: modules/AutoinstLVM.ycp
* Module: Auto-Installation
* Summary: LVM
* Authors: Anas Nashif <nashif@suse.de>
*
* $Id: AutoinstLVM.ycp 61609 2010-04-08 09:55:31Z ug $
*/
{
module "AutoinstLVM";
textdomain "autoinst";
import "Storage";
import "Report";
import "Partitions";
import "FileSystems";
import "AutoinstStorage";
import "Label";
include "partitioning/lvm_lv_lib.ycp";
global map<string, map> ExistingLVM = $[];
global list<string> ExistingVGs = [];
global map<string, list<string> > keepLVM = $[];
// LVM map as imported from Profile
global map<string, map> lvm = $[];
// useless
// boolean pvs_on_unconfigured = false;
// temporary copy of variable from Storage
// map <string, map> targetMap = $[];
// temporary copy of variable from Storage
map<string, map> targetMap = $[];
boolean old_available = false;
/**
* Constructer
*/
global define void AutoinstLVM() {
return;
}
/**
* Initialize
* @return void
*/
global define boolean Init () {
y2milestone("entering Init");
y2milestone("AutoTargetMap is %1",AutoinstStorage::AutoTargetMap);
lvm = filter(string k, map v,
AutoinstStorage::AutoTargetMap, ``(v["type"]:`CT_UNKNOWN==`CT_LVM));
// check for existing VM
targetMap = Storage::GetTargetMap();
y2milestone("GetTargetMap returns %1",targetMap);
ExistingLVM = filter(string k, map v, Storage::GetTargetMap(), ``(v["type"]:`CT_UNKNOWN==`CT_LVM));
if( haskey( ExistingLVM, "/dev/evms" ) ) {
ExistingLVM = remove( ExistingLVM, "/dev/evms" );
}
ExistingVGs = maplist (string d, map g, ExistingLVM, ``{
return (substring(d, 5) );
});
/* look for VGs to reuse */
foreach ( string k, map v, AutoinstStorage::AutoTargetMap, ``{
foreach ( map p, v["partitions"]:[], ``{
if( haskey( p, "lvm_group" ) && p["create"]:true == false && p["format"]:true == false ) {
keepLVM[p["lvm_group"]:"x"] = [];
if( !contains( ExistingVGs, p["lvm_group"]:"x" ) )
Report::Error( sformat( _("Cannot reuse volume group %1. The volume group does not exist."), p["lvm_group"]:"x" ) );
map atm = AutoinstStorage::AutoTargetMap;
foreach ( map vg_p, atm["/dev/"+p["lvm_group"]:"x","partitions"]:[], ``{
if( vg_p["create"]:true == false )
keepLVM[p["lvm_group"]:"x"] = add( keepLVM[p["lvm_group"]:"x"]:[], vg_p["lv_name"]:"" );
});
}
});
});
y2milestone("Existing VGs: %1", ExistingVGs);
y2milestone("Existing LVM: %1", ExistingLVM);
y2milestone("keep LVM: %1", keepLVM);
// FIXME
foreach (string v, ExistingVGs, ``{
string dev = sformat("/dev/%1", v);
if (size(ExistingLVM[dev,"partitions"]:[]) > 0 ) {
old_available = true;
}
});
// Process data
lvm = mapmap(string device, map disk, lvm, ``{
disk["pesize"] = AutoinstStorage::humanStringToByte(disk["pesize"]:"4M", true);
string vgname = substring(device, 5);
disk["partitions"] = maplist(map lv, disk["partitions"]:[], ``{
string lvsize_str = lv["size"]:"";
string mount_point = lv["mount"]:"";
integer lvsize = 0;
integer vgsize = targetMap[device,"size_k"]:0*1024;
if (lvsize_str == "auto" && mount_point == "swap") {
y2milestone("swap slot size: %1", vgsize/1024*1024 );
lvsize = 1024*1024*Partitions::SwapSizeMb(vgsize/(1024*1024));
} else if (lvsize_str!= "") {
lvsize = AutoinstStorage::humanStringToByte( lvsize_str, true );
}
lv["size_k"] = lvsize/1024;
lv["type"] = `lvm;
lv["name"] = lv["lv_name"]:"";
return(lv);
});
return($[device:disk]);
});
return true;
}
/**
* Delete possible partitions
*/
define boolean remove_possible_volumes(string vgname) {
y2milestone("Deleting possible VGs and LVs");
if (ExistingLVM == $[])
return true;
map vg = ExistingLVM["/dev/" +vgname]:$[];
list<map> lvs = vg["partitions"]:[];
y2milestone("Existing LVs: %1", lvs);
foreach(map lv, lvs, ``{
if (!contains(keepLVM[vgname]:[], lv["name"]:"")) {
Storage::DeleteDevice("/dev/"+vgname+"/"+lv["name"]:"");
}
});
if( ! haskey( keepLVM, vgname ) && ExistingLVM["/dev/" +vgname]:$[] != $[] )
Storage::DeleteLvmVg(vgname);
return true;
}
/**
* Return only those PVs on disks touched by the control file, dont add PVs of
* unconfigured disks.
* @param string volume group name
* @return list existing PVs
*/
global define list<map> get_existing_pvs ( string vgname ) {
y2milestone("entering get_existing_pvs with %1",vgname);
symbol usedBy = `UB_LVM;
// all possible PVs on all available devices
list<map> all_possible_pvs = filter( map part, get_possible_pvs( Storage::GetTargetMap() ),
``( ((part["used_by_device"]:"" == "/dev/"+vgname && part["used_by_type"]:`UB_NONE == usedBy ) ||
part["used_by_type"]:`UB_NONE == `UB_NONE) && !part["delete"]:false ));
y2milestone("all pvs= %1", all_possible_pvs);
// FIXME
return (all_possible_pvs);
}
/**
* Write LVM Configuration
* @return boolean true on success
*/
global define boolean Write () {
y2milestone("entering Write");
Storage::SetZeroNewPartitions(AutoinstStorage::ZeroNewPartitions);
list lvm_vgs = get_vgs( targetMap );
string current_vg = "";
boolean error = false;
foreach (string device, map volume_group, lvm , ``{
y2milestone("volume_group is %1", volume_group);
string use = volume_group["use"]:"none";
boolean lvm2 = volume_group["lvm2"]:true;
string lvm_string = lvm2 ? "lvm2" : "lvm";
string vgname = substring(device, 5);
current_vg = vgname;
list<map> new_pvs = get_existing_pvs(vgname);
integer pesize = volume_group["pesize"]:1;
if (volume_group["prefer_remove"]:false) {
remove_possible_volumes(vgname);
}
if (size(volume_group["keep_lv"]:[]) == 0 ) {
boolean ret = Storage::CreateLvmVg(vgname, volume_group["pesize"]:4194304, lvm2);
current_vg = vgname;
y2milestone("CreateLvmVg returns %1", ret);
targetMap = Storage::GetTargetMap();
y2milestone("Storage::GetTargetMap returns %1",targetMap);
lvm_vgs = get_vgs( targetMap );
}
list<string> new_pvs_devices= maplist(map pv, new_pvs, ``{
return(pv["device"]:"");
});
y2milestone("Existing PVs: %1", new_pvs );
map atm = AutoinstStorage::AutoTargetMap;
integer smallest_physical = 0;
foreach(map pv, new_pvs, ``{
boolean to_add = false;
if (pv["create"]:false) {
to_add = true;
// exclude partitions that are NOT supposed to be in the LVM
foreach( map atm_vol, atm[pv["maindev"]:"","partitions"]:[], ``{
if( pv["nr"]:0 == atm_vol["partition_nr"]:-1 ) {
if( atm_vol["lvm_group"]:"" != current_vg ) {
y2milestone("do not add %1",atm_vol);
to_add = false;
}
}
});
} else {
to_add = false;
// exclude partitions that are NOT supposed to be in the LVM
foreach( map atm_vol, atm[pv["maindev"]:"","partitions"]:[], ``{
if( pv["nr"]:0 == atm_vol["partition_nr"]:-1 ) {
if( atm_vol["lvm_group"]:"" == current_vg ) {
y2milestone("add %1",atm_vol);
to_add = true;
}
}
});
}
if( to_add ) {
y2milestone("addPhysicalVolume %1 , %2",pv["device"]:"", current_vg );
if( smallest_physical == 0 || pv["size_k"]:0 < smallest_physical )
smallest_physical = pv["size_k"]:0;
addPhysicalVolume(targetMap, pv["device"]:"", current_vg );
}
});
// calculating the "max" for logical volume
map<string, map> tmp_tm = Storage::GetTargetMap();
integer freeSpace = 0;
integer buffer = 0;
freeSpace = tmp_tm[device,"size_k"]:0;
buffer = tmp_tm[device,"cyl_size"]:0;
buffer = (buffer * 2) / 1024;
integer max_counter = 0;
volume_group["partitions"] = maplist( map lv, volume_group["partitions"]:[], ``{
integer s = AutoinstStorage::humanStringToByte( lv["size"]:"10000", true );
if( s <= 100 && s > 0 ) {
// we assume percentage for this lv
integer integer_k = freeSpace * tointeger(lv["size"]:"0") / 100;
lv["size_k"] = integer_k;
y2milestone("percentage for lv %1. Size_k is %2",lv,integer_k);
} else if( lv["size"]:"" == "max" && lv["stripes"]:0 <= 1 ) {
max_counter = max_counter + 1;
}
return lv;
});
foreach(map lv, volume_group["partitions"]:[], ``{
freeSpace = freeSpace - lv["size_k"]:0;
y2milestone("freeSpace = %1",freeSpace);
});
freeSpace = freeSpace - buffer; // that's a buffer for rounding errors with cylinder boundaries
foreach(map lv, volume_group["partitions"]:[], ``{
if( lv["size_k"]:0 == 0 && freeSpace > 0 ) {
// if "max" calculation is turned on for the LV
if( lv["stripes"]:0 > 1 ) {
lv["size_k"] = smallest_physical * lv["stripes"]:1;
lv["size"] = sformat("%1K",smallest_physical * lv["stripes"]:1);
freeSpace = freeSpace - lv["size_k"]:0;
smallest_physical = 0;
y2milestone("max-config for striped LV found. Setting size to %1", lv["size"]:"0");
} else {
lv["size_k"] = freeSpace / max_counter;
lv["size"] = sformat("%1K",freeSpace);
}
}
y2milestone("size_k before rounding %1",lv["size_k"]:0);
lv["size_k"] = (integer)( (lv["size_k"]:0*1024) / pesize ) * pesize / 1024; // rounding
y2milestone("size_k after rounding %1",lv["size_k"]:0);
list<map> lvlist = ExistingLVM[device, "partitions"]:[];
if( contains(keepLVM[vgname]:[], lv["lv_name"]:"") ) {
list<map> lvtokeep = filter(map p, lvlist, ``(p["nr"]:"" == lv["lv_name"]:""));
map this_lv = lvtokeep[0]:$[];
y2milestone("Keeping LV: %1", this_lv);
y2milestone("lv = %1",lv);
lv["device"] = "/dev/"+vgname+"/"+lv["lv_name"]:"";
lv["used_fs"] = this_lv["used_fs"]:Partitions::DefaultFs();
map lvret = $[];
if (lv["resize"]:false ) {
map reslv = $[
"create" : false,
"region" : lv["region"]:[],
"fsid" : 142,
"lv_size" : lv["lv_size"]:0,
"fstype" : "LV",
"nr" : lv["nr"]:"",
"mount" : lv["mount"]:"" ,
"used_fs" : this_lv["used_fs"]:Partitions::DefaultFs(),
"format" : lv["format"]:false ,
"device" : lv["device"]:""
];
reslv["changed_size"] = true;
Storage::ResizeVolume( "/dev/" + current_vg + "/" + lv["name"]:"",
"/dev/" + current_vg,
lv["lv_size"]:0/1024 );
} else {
Storage::ChangeVolumeProperties( lv );
}
targetMap = lvret["targets"]:targetMap;
} else if ( lv["create"]:true ) {
lv["used_fs"] = lv["filesystem"]:Partitions::DefaultFs();
lv["create"] = true;
lv["format"] = lv["format"]:true;
lv["device"] = "/dev/" + current_vg + "/" + lv["name"]:"";
addLogicalVolume(lv, current_vg);
y2milestone("calling addLogicalVolume with lv = %1 and current_vg = %2",lv, current_vg);
targetMap = Storage::GetTargetMap();
y2milestone("Storage::GetTargetMap returns %1",targetMap);
}
});
});
y2milestone("targetmap: %1" , targetMap );
return true;
}
}
ACC SHELL 2018