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 / AutoinstLVM.ycp < prev    next >
Text File  |  2006-11-29  |  20KB  |  502 lines

  1. /**
  2.  * File:    modules/AutoinstLVM.ycp
  3.  * Module:    Auto-Installation
  4.  * Summary:    LVM
  5.  * Authors:    Anas Nashif <nashif@suse.de>
  6.  *
  7.  * $Id: AutoinstLVM.ycp 32415 2006-08-17 15:06:17Z ug $
  8.  */
  9. {
  10.  
  11.     module "AutoinstLVM";
  12.     textdomain "autoinst";
  13.  
  14.     import "Storage";
  15.     import "Report";
  16.     import "Partitions";
  17.     import "FileSystems";
  18.     import "AutoinstStorage";
  19.     import "Label";
  20.  
  21.     include "partitioning/lvm_pv_lib.ycp";
  22.     include "partitioning/lvm_lib.ycp";
  23.  
  24.     include "partitioning/lvm_lv_lib.ycp";
  25.  
  26.     include "partitioning/partition_defines.ycp";
  27.  
  28.     global symbol  vmType    = `CT_LVM;
  29.  
  30.     global boolean ZeroNewPartitions = true;
  31.  
  32.     global map<string, map> ExistingLVM = $[];
  33.  
  34.     global list<string> ExistingVGs = [];
  35.  
  36.  
  37.     // LVM map as imported from Profile
  38.     global map<string, map> lvm = $[]; 
  39.  
  40.  
  41. // useless
  42. //    boolean pvs_on_unconfigured = false;
  43.  
  44.  
  45.     // temporary copy of variable from Storage
  46.     // map <string, map> targetMap = $[];
  47.  
  48.     // temporary copy of variable from Storage
  49.     map<string, map> targetMap = $[];
  50.  
  51.     boolean old_available = false;
  52.  
  53.  
  54.  
  55.     /** 
  56.      * Constructer
  57.      */
  58.     global define void AutoinstLVM() {
  59.         return;
  60.     }
  61.  
  62.  
  63.     /**
  64.      * Initialize
  65.      * @return void
  66.      */
  67.     global define boolean Init () {
  68.         y2milestone("entering Init");
  69.         y2milestone("AutoTargetMap is %1",AutoinstStorage::AutoTargetMap);
  70.         lvm   = filter(string k, map v, 
  71.                         AutoinstStorage::AutoTargetMap, ``(v["type"]:`CT_UNKNOWN==`CT_LVM));
  72.  
  73.         // either LVM or EVMS is allowed.
  74.         if (size(lvm) == 0) {
  75.             lvm   = filter(string k, map v,
  76.                             AutoinstStorage::AutoTargetMap, ``(v["type"]:`CT_UNKNOWN==`CT_EVMS));
  77.                 if (size(lvm) == 0) {
  78.                     // no LVM and no EVMS is wanted. We can go now.
  79.                     return false;
  80.                 }
  81.             vmType = `CT_EVMS;
  82.         }
  83.  
  84.         // check for existing VM
  85.         targetMap = Storage::GetTargetMap();
  86.         y2milestone("GetTargetMap returns %1",targetMap);
  87.         //ExistingLVM    = filter(string k, map v, Storage::GetTargetMap(), ``(v["type"]:`CT_UNKNOWN==`CT_LVM));
  88.         ExistingLVM    = filter(string k, map v, Storage::GetTargetMap(), ``(v["type"]:`CT_UNKNOWN==vmType));
  89.         ExistingVGs    = maplist (string  d, map g, ExistingLVM, ``{
  90.             return (substring(d, 5) );
  91.         });
  92.  
  93.         y2milestone("Existing VGs: %1", ExistingVGs );
  94.         y2milestone("Existing LVM: %1", ExistingLVM);
  95.  
  96.         symbol dropType = ( vmType == `CT_LVM ? `CT_EVMS : `CT_LVM );
  97.  
  98.         // if we want to create EVMS, drop all existing LVMs now
  99.         // and vice versa
  100.         // it's not possible to mix LVM and EVMS with autoyast
  101.         //
  102.         map<string, map> toDrop = filter(string k, map v, Storage::GetTargetMap(), ``(v["type"]:`CT_UNKNOWN==dropType));
  103.         foreach (string device, map volume_group, toDrop , ``{
  104.             string  vgname  = substring(device, 5);
  105.             y2milestone("removing %1 %2",dropType,vgname);
  106.             removeVolumeGroup(vgname); // FIXME: I expect this to work recursive
  107.         });
  108.  
  109.  
  110.         // FIXME
  111.         foreach (string v, ExistingVGs, ``{
  112.             string dev = sformat("/dev/%1", v);
  113.                 if (size(ExistingLVM[dev,"partitions"]:[]) > 0 ) {
  114.                     old_available = true;
  115.                 }
  116.         });
  117.  
  118.  
  119.         // Process data
  120.         lvm = mapmap(string device, map disk, lvm, ``{
  121.             foreach( string key, ["keep_lv"], ``{
  122.                 list num = [];
  123.                 list<string> nlist = splitstring(disk[key]:"", ",");
  124.                 foreach( string n, nlist, ``{ 
  125.                     num = union( num, [n] );
  126.                 });
  127.                 disk[key] = num;
  128.             });
  129.  
  130.             list fsys = [];
  131.             list<string> nlist = splitstring( disk["keep_lv_fsys"]:"" , "," );
  132.             foreach( string n, nlist, ``{
  133.                 symbol fs = FileSystems::FsToSymbol(n);
  134.                 if( fs != `none ) {
  135.                     fsys = union( fsys, [ fs ] );
  136.                 }
  137.             });
  138.             disk["keep_lv_fsys"] = fsys;
  139.             disk["pesize"] = pesize_str_to_byte(disk["pesize"]:"4M");
  140.  
  141.             string     vgname    = substring(device, 5);
  142.             disk["partitions"]  = maplist(map lv, disk["partitions"]:[], ``{
  143.                 string lvsize_str    = lv["size"]:"";
  144.                 string mount_point      = lv["mount"]:"";
  145.                 integer lvsize         = 0;
  146.  
  147. // useless? maybe a sideeffect is wanted
  148. //                list<map> parts    = get_possible_pvs( Storage::GetTargetMap() );
  149.  
  150.                 integer vgsize = targetMap[device,"size_k"]:0*1024;
  151.  
  152.                 if (lvsize_str == "auto" && mount_point == "swap") {
  153.                     y2milestone("swap slot size: %1", vgsize/1024*1024 );
  154.                     lvsize = 1024*1024*Partitions::SwapSizeMb(vgsize/(1024*1024)); 
  155.                 } else if (lvsize_str!= "") {
  156.                     lvsize = kmgt_str_to_byte(lvsize_str);
  157.                 }
  158.  
  159.                 lv["size_k"] = lvsize/1024;
  160.                 if( vmType == `CT_LVM ) {
  161.                     lv["type"] = `lvm;
  162.                 } else if( vmType == `CT_EVMS ) {
  163.                     lv["type"] = `evms;
  164.                     lv["evms_name"] = lv["lv_name"]:"";
  165.                 }
  166.                 lv["name"] = lv["lv_name"]:"";
  167.                 return(lv);
  168.             });
  169.             return($[device:disk]);
  170.         });
  171.  
  172.     return true;
  173.     }
  174.  
  175.     /**
  176.      * Delete possible partitions
  177.      */
  178.     define boolean remove_possible_volumes(string vgname) {
  179.         y2milestone("Deleting possible VGs and LVs");
  180.         if (ExistingLVM == $[])
  181.             return true;
  182.  
  183.         map vg = ExistingLVM["/dev/" +vgname]:$[];
  184.         list<map> lvs = vg["partitions"]:[];
  185.         y2milestone("Existing LVs: %1", lvs);
  186.  
  187.         foreach(map lv, lvs, ``{
  188.             if (!contains(lvm["/dev/"+vgname, "keep_lv"]:[], lv["name"]:"")) {
  189.                 removeLogicalVolume( "/dev/"+vgname,
  190.                                      "/dev/"+vgname+"/"+lv["name"]:"" ); //FIXME: does removeLogicalVolume work for EVMS?
  191.                 }
  192.             });
  193.  
  194.         if (size(lvm["/dev/"+vgname, "keep_lv"]:[]) == 0 &&
  195.             ExistingLVM["/dev/" +vgname]:$[] != $[]) {
  196.             removeVolumeGroup( vgname ); //FIXME: does removeVolumeGroup work for EVMS?
  197.         }
  198.  
  199.         return true;
  200.     }
  201.  
  202.     /**
  203.      * Keep logical volume
  204.      * @param string volume group name
  205.      * @param string logical volume
  206.      * @return void
  207.      */
  208. /* FIXME: this looks useless to me.
  209.  
  210.     global define map KeepLV (string vgname, map lv, map<string,map> targetMap  ) {
  211.         y2milestone("entering KeepLV with %1 - %2 - %3",vgname,lv,targetMap);
  212.         map modLV = $[
  213.               "create"        : false,
  214.               "region"        : lv["region"]:[],
  215.               "fsid"        : 142,      //FIXME: EVMS?
  216.               "fstype"        : "LV",     //FIXME: EVMS?
  217.               "nr"        : lv["nr"]:"",
  218.               "mount"        : lv["mount"]:"" ,
  219.               "used_fs"        : lv["used_fs"]:`reiser,
  220.               "format"        : lv["format"]:false ,
  221.               "type"        : `lvm,     //FIXME: EVMS?
  222.               "device"        : "/dev/" + vgname + "/" + lv["nr"]:""
  223.     ];
  224.     
  225.     return( $[  "targets":Storage::SetPartition( targetMap, modLV ) ]);
  226.     
  227.     }
  228. */
  229.   
  230.  
  231.     /**
  232.      * Return only those PVs on disks touched by the control file, dont add PVs of
  233.      * unconfigured disks.
  234.      * @param string volume group name
  235.      * @return list existing PVs
  236.      */
  237.     global define list<map> get_existing_pvs ( string vgname ) {
  238.         y2milestone("entering get_existing_pvs with %1",vgname);
  239.         map<string, map> tm = $[];    
  240.  
  241.         symbol usedBy = `UB_LVM;
  242.         foreach(string k, map v, AutoinstStorage::AutoTargetMap, ``{
  243. //        if (Storage::IsRealDisk( v ))
  244.             y2milestone("AutoTargetMap = %1", v );
  245.  
  246.             // FIXME: how about v["type"]:`CT_UNKNOWN == `CT_DISK
  247.             if ( v["type"]:`CT_UNKNOWN != `CT_LVM && v["type"]:`CT_UNKNOWN != `CT_EVMS) {
  248.                 tm[k] = v;
  249.                 integer i = 0;
  250.                 foreach( map p, v["partitions"]:[], ``{
  251.                     if( haskey(p,"lvm_group") ) {
  252.                         tm[k,"partitions",i,"used_by_type"] = `UB_LVM;
  253.                         tm[k,"partitions",i,"used_by"]      = p["lvm_group"]:"";
  254.                     } else if( haskey(p,"evms_group") ) {
  255.                         tm[k,"partitions",i,"used_by_type"] = `UB_EVMS;
  256.                         tm[k,"partitions",i,"used_by"]      = p["evms_group"]:"";
  257.                         usedBy = `UB_EVMS;
  258.                     }
  259.                     i = i + 1;
  260.                 });
  261.             } else if (k == "/dev/md") {
  262.                 // FIXME: will this ever be reached?
  263.                 tm[k] = v;
  264.             }
  265.         });
  266.  
  267.         y2milestone("tm: %1", tm);
  268.  
  269.         // all possible PVs on all available devices
  270.         list<map> all_possible_pvs = filter( map part, get_possible_pvs( Storage::GetTargetMap() ),
  271.                          ``( ((part["used_by"]:"" == vgname && part["used_by_type"]:`UB_NONE == usedBy ) || 
  272.                               part["used_by_type"]:`UB_NONE == `UB_NONE) && !part["delete"]:false ));
  273.  
  274.         y2milestone("all pvs= %1", all_possible_pvs);
  275.  
  276.         // FIXME
  277.         return (all_possible_pvs);
  278.     }
  279.  
  280.     /**
  281.      * Return list of deleted PVS
  282.      * @param string volume group name
  283.      * @return list<map> list of deleted PVs
  284.      */
  285.      /* FIXME: useless?
  286.      
  287.     global define list<map> get_deleted_pvs ( string vgname ) {
  288.         y2milestone("entering get_deleted_pvs with %1",vgname);
  289.     list<list<map> > ret = [];
  290.     foreach( string dev, map devmap, Storage::GetTargetMap(),
  291.          ``{
  292.         ret = add( ret,
  293.                filter( map part, devmap["partitions"]:[],
  294.                    ``(
  295.                   part["lvm_group"]:"" == vgname &&
  296.                   part["delete"]:false  &&
  297.                   ( part["fsid"]:0 == Partitions::fsid_lvm ||
  298.                     part["fsid"]:0 == Partitions::fsid_raid ||
  299.                     part["fsid"]:0 == Partitions::fsid_native )
  300.                   )
  301.                    )
  302.                );
  303.     });
  304.     y2milestone("deleted PVs: %1",  flatten(ret) );
  305.     return( flatten(ret) );
  306.     }
  307. */
  308.     
  309.     /**
  310.      * Write LVM Configuration
  311.      * @return boolean true on success
  312.      */
  313.     global define boolean Write () {
  314.         y2milestone("entering Write");
  315.         Storage::SetZeroNewPartitions(ZeroNewPartitions);
  316.  
  317.         list    lvm_vgs          = get_vgs( targetMap ); // FIXME: does not work for EVMS
  318.         string current_vg     = "";
  319.  
  320.         boolean error = false;
  321.  
  322.  
  323.         foreach (string device, map volume_group, lvm , ``{
  324.             y2milestone("volume_group is %1", volume_group);
  325.             string     use    = volume_group["use"]:"none";
  326.             boolean     lvm2    = volume_group["lvm2"]:true;
  327.             string lvm_string = lvm2 ? "lvm2" : "lvm";
  328.  
  329.             string     vgname    = substring(device, 5);
  330.             current_vg = vgname;
  331.  
  332.             list<map>     new_pvs    = get_existing_pvs(vgname);
  333.  
  334.             if (volume_group["prefer_remove"]:false) {
  335.                 remove_possible_volumes(vgname);
  336.             }
  337.  
  338.             map vg = $[];
  339.  
  340.             if (size(volume_group["keep_lv"]:[]) == 0 ) {
  341.                 vg["vgname"] = vgname;
  342.                 vg["pesize"] = volume_group["pesize"]:1;
  343.                 vg["lvm2"]   = lvm2;
  344.                 map addVG = $[];
  345.                 if( vmType == `CT_LVM ) {
  346.                         addVG = addVolumeGroup(vg, targetMap, [] );
  347.                         current_vg      = addVG["vg"]:"none";
  348.                         y2milestone("addVolumeGroup returns %1",addVG);
  349.                 } else if( vmType == `CT_EVMS ) {
  350.                         Storage::CreateEvmsCo( lvm_string + "/" + vgname, vg["pesize"]:1024,vg["lvm2"]:false );
  351.                         current_vg      = addVG["vg"]:"none";
  352.                         y2milestone("add_evms_volume returns %1",addVG);
  353.                 }
  354.                 targetMap = Storage::GetTargetMap();
  355.                 y2milestone("Storage::GetTargetMap returns %1",targetMap);
  356.                 lvm_vgs = get_vgs( targetMap );
  357.             }
  358.  
  359.             list<string> new_pvs_devices= maplist(map pv, new_pvs, ``{
  360.                 return(pv["device"]:"");
  361.             });
  362.             y2milestone("Existing PVs: %1",  new_pvs );
  363.             map atm = AutoinstStorage::AutoTargetMap;
  364.             foreach(map pv, new_pvs, ``{
  365.                 if (pv["create"]:false) {
  366.                     boolean to_add = true;
  367.                     if( vmType == `CT_LVM ) {
  368.                             // exclude partitions that are NOT supposed to be in the LVM
  369.                             foreach( map atm_vol, atm[pv["maindev"]:"","partitions"]:[], ``{
  370.                                 if( pv["nr"]:0 == atm_vol["partition_nr"]:-1 ) {
  371.                                     if( atm_vol["lvm_group"]:"" != current_vg ) {
  372.                                         y2milestone("do not add %1",atm_vol);
  373.                                         to_add = false;
  374.                                     }
  375.                                 }
  376.                             });
  377.                             if( to_add ) {
  378.                                 y2milestone("addPhysicalVolume %1 , %2",pv["device"]:"", current_vg );
  379.                                 addPhysicalVolume(targetMap, pv["device"]:"", current_vg );
  380.                             }
  381.                     } else if( vmType == `CT_EVMS ) {
  382.                             // exclude partitions that are NOT supposed to be in the EVMS
  383.                             foreach( map atm_vol, atm[pv["maindev"]:"","partitions"]:[], ``{
  384.                                 if( pv["nr"]:0 == atm_vol["partition_nr"]:-1 ) {
  385.                                     if( atm_vol["evms_group"]:"" != current_vg ) {
  386.                                         y2milestone("do not add %1",atm_vol);
  387.                                         to_add = false;
  388.                                     }
  389.                                 }
  390.                             });
  391.                             if( to_add ) {
  392.                                 y2milestone("Storage::ExtendEvmsCo %1/%2",lvm_string,pv["device"]:"");
  393.                                 Storage::ExtendEvmsCo(lvm_string+"/"+vgname, pv["device"]:"");
  394.                             }
  395.                     }
  396.                 }
  397.             });
  398.  
  399.             // calculating the "max" for logical volume
  400.             map<string, map> tmp_tm = Storage::GetTargetMap();
  401.             integer freeSpace = 0;
  402.             integer buffer = 0;
  403.             if( vmType == `CT_LVM ) {
  404.                 freeSpace = tmp_tm[device,"size_k"]:0;
  405.                 buffer = tmp_tm[device,"cyl_size"]:0;
  406.             } else if( vmType == `CT_EVMS ) {
  407.                 freeSpace = tmp_tm[ "/dev/evms/"+lvm_string+"/"+vgname, "size_k"]:0;
  408.                 buffer =    tmp_tm[ "/dev/evms/"+lvm_string+"/"+vgname, "cyl_size"]:0;
  409.             }
  410.             buffer = (buffer * 2) / 1024;
  411.  
  412.             volume_group["partitions"] = maplist( map lv, volume_group["partitions"]:[], ``{
  413.                 integer s = kmgt_str_to_byte( lv["size"]:"10000" );
  414.                 if( s <= 100 && s > 0 ) {
  415.                     // we assume percentage for this lv
  416.                     integer integer_k = freeSpace * tointeger(lv["size"]:"0") / 100;
  417.                     lv["size_k"] = integer_k;
  418.                     y2milestone("percentage for lv %1. Size_k is %2",lv,integer_k);
  419.                 }
  420.                 return lv;
  421.             });
  422.  
  423.             foreach(map lv,  volume_group["partitions"]:[], ``{
  424.                 freeSpace = freeSpace - lv["size_k"]:0;
  425.                 y2milestone("freeSpace = %1",freeSpace);
  426.             });
  427.             freeSpace = freeSpace - buffer; // that's a buffer for rounding errors with cylinder boundaries
  428.  
  429.             foreach(map lv,  volume_group["partitions"]:[], ``{
  430.                 if( lv["size_k"]:0 == 0 && freeSpace > 0 ) {
  431.                     // if "max" calculation is turned on for the LV
  432.                     lv["size_k"] = freeSpace;
  433.                     lv["size"]   = sformat("%1K",freeSpace);
  434.                 }
  435.  
  436.                 list<map> lvlist =  ExistingLVM[device, "partitions"]:[];
  437.  
  438.                 if (contains(volume_group["keep_lv"]:[], lv["nr"]:"_error_")) {
  439.                     list<map> lvtokeep = filter(map p, lvlist, ``(p["nr"]:"" == lv["lv_name"]:""));
  440.                     map this_lv = lvtokeep[0]:$[]; 
  441.  
  442.                     y2milestone("Keeping LV: %1", this_lv);            
  443.  
  444.                     lv["used_fs"]    =    this_lv["used_fs"]:`reiser;
  445.  
  446.                     map lvret = $[];
  447.                     if (lv["resize"]:false ) {
  448.                         map reslv = $[
  449.                                       "create"        : false,
  450.                                       "region"        : lv["region"]:[],
  451.                                       "fsid"          : 142,
  452.                                       "lv_size"       : lv["lv_size"]:0,
  453.                                       "fstype"        : "LV",
  454.                                       "nr"            : lv["nr"]:"",
  455.                                       "mount"         : lv["mount"]:"" ,
  456.                                       "used_fs"       : this_lv["used_fs"]:`reiser,
  457.                                       "format"        : lv["format"]:false ,
  458.                                       "type"          : `lvm,
  459.                                       "device"        : "/dev/" + current_vg + "/" + lv["name"]:""
  460.                                     ];
  461.                         reslv["changed_size"] = true;
  462.                         Storage::ResizeVolume( "/dev/" + current_vg + "/" + lv["name"]:"",
  463.                                                "/dev/" + current_vg,
  464.                                                lv["lv_size"]:0/1024 );
  465.                     } else {
  466.                         Storage::ChangeVolumeProperties( lv );
  467.                     }
  468.                     targetMap      = lvret["targets"]:targetMap;
  469.                 } else if ( lv["create"]:true ) {
  470.                     lv["used_fs"] = lv["filesystem"]:`reiser;
  471.                     lv["create"] = true;
  472.                     lv["format"] = lv["format"]:true;
  473.                     if( vmType == `CT_LVM ) {
  474.                         lv["device"] = "/dev/" + current_vg + "/" + lv["name"]:"";
  475.                     } else if( vmType == `CT_EVMS ) {
  476.                         // FIXME: is lv["device"] needed at all here?
  477.                         lv["device"] = "/dev/evms/"+lvm_string+"/"+vgname+"/"+lv["name"]:"";
  478.                     }
  479.                     if( vmType == `CT_LVM ) {
  480.                         addLogicalVolume(lv, current_vg); // FIXME: will not work for EVMS
  481.                         y2milestone("calling addLogicalVolume with lv = %1 and current_vg = %2",lv, current_vg);
  482.                     } else if( vmType == `CT_EVMS ) {
  483.                         y2milestone("Storage::CreateEvmsVolume %1/%2",lvm_string,vgname);
  484.                         y2milestone("lv = %1",lv);
  485.                         Storage::CreateEvmsVolume(lvm_string+"/"+vgname,lv["name"]:"",lv["size_k"]:0,lv["stripes"]:1);
  486.                         Storage::ChangeVolumeProperties(lv);
  487.                         if( lv["stripesize"]:0 > 0 )
  488.                             Storage::ChangeEvmsStripeSize( lvm_string+"/"+vgname, lv["name"]:"",
  489.                                                                            lv["stripesize"]:0 );
  490.                     }
  491.                     targetMap = Storage::GetTargetMap();
  492.                     y2milestone("Storage::GetTargetMap returns %1",targetMap);
  493.                 }
  494.             });
  495.  
  496.         });
  497.         y2milestone("targetmap: %1" , targetMap );
  498.         return true;
  499.     }
  500. }
  501.  
  502.