ACC SHELL

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

/**
 * 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