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 / Profile.ycp < prev    next >
Text File  |  2006-11-29  |  22KB  |  672 lines

  1. /**
  2.  * File:    modules/Profile.ycp
  3.  * Module:    Auto-Installation
  4.  * Summary:    Profile handling
  5.  * Authors:    Anas Nashif <nashif@suse.de>
  6.  *
  7.  * $Id: Profile.ycp 34426 2006-11-16 09:25:17Z ug $
  8.  */
  9. {
  10.     module "Profile";
  11.     textdomain "autoinst";
  12.  
  13.     import "Stage";
  14.     import "Mode";
  15.     import "AutoinstConfig";
  16.     import "XML";
  17.     import "Popup";
  18.     import "ProductControl";
  19.     import "Directory";
  20.     import "PackageSystem";
  21.  
  22.     include "autoinstall/xml.ycp";
  23.  
  24.  
  25.     // The Complete current Profile
  26.     global map<string,any> current = $[];
  27.  
  28.     // defined in Y2ModuleConfig
  29.     global map<string, map> ModuleMap = $[];
  30.  
  31.  
  32.     global string Version = "";
  33.  
  34.     string Description = "";
  35.  
  36.     global boolean changed = false;
  37.  
  38.     global boolean prepare = true;
  39.  
  40.     /**
  41.      * Constructor
  42.      * @return void
  43.      */
  44.     global define void Profile ()
  45.     {
  46.         //
  47.         // setup profile XML parameters for writing
  48.         //
  49.         profileSetup();
  50.         if (Stage::initial ())
  51.         {
  52.             SCR::Execute(.target.mkdir, AutoinstConfig::profile_dir);
  53.         }
  54.         return;
  55.     }
  56.  
  57.  
  58.     /**
  59.      * Detect Version
  60.      * @return string
  61.      */
  62.     define string DetectVersion() {
  63.         return "";
  64.     }
  65.  
  66.     /**
  67.      * compatibility to new storage lib in 10.0
  68.      */
  69.     define void storageLibCompat() {
  70.         list<map> newPart = [];
  71.         foreach( map d, current["partitioning"]:[], {
  72.             if( haskey(d, "is_lvm_vg") && d["is_lvm_vg"]:false == true ) {
  73.                 d = remove( d, "is_lvm_vg" );
  74.                 d["type"] = `CT_LVM;
  75.             } else if( haskey(d, "device") && d["device"]:"" == "/dev/md" ) {
  76.                 d["type"] = `CT_MD;
  77.             } else if( haskey(d, "is_evms_vg") && d["is_evms_vg"]:false == true ) {
  78.                     d["type"] = `CT_EVMS;
  79.             } else if( ! haskey(d,"type") ) {
  80.                 d["type"] = `CT_DISK;
  81.             }
  82.  
  83.             // actually, this is not a compatibility hook for the new
  84.             // storage lib. It's a hook to be compatibel with the autoyast
  85.             // documentation for reusing partitions
  86.             //
  87.             d["partitions"] = maplist( map p, d["partitions"]:[], ``{
  88.                 if( haskey(p, "create") && p["create"]:true == false &&
  89.                     haskey(p, "partition_nr") ) {
  90.                     p["usepart"] = p["partition_nr"]:0; // useless default
  91.                 }
  92.                 if( haskey(p, "partition_id") ) {
  93.                     // that's a bit strange. There is a naming mixup between
  94.                     // autoyast and the storage part of yast. Actually filesystem_id
  95.                     // does not make sense at all but in autoyast it is the
  96.                     // partition id (maybe that's because yast calls
  97.                     // the partition id "fsid" internally).
  98.                     // partition_id in the profile does not work at all, so we copy
  99.                     // that value to filesystem_id
  100.                     p["filesystem_id"] = p["partition_id"]:0;
  101.                 }
  102.                 return p;
  103.             });
  104.             newPart = add( newPart, d );
  105.         });
  106.         y2milestone("partitioning is now %1",newPart);
  107.         current["partitioning"] = newPart;
  108.     }
  109.  
  110.     /**
  111.      * compatibility to new language,keyboard and timezone client in 10.1
  112.      */
  113.     global define void generalCompat() {
  114.         if( haskey( current, "general" ) ) {
  115.             if( haskey( current["general"]:$[], "keyboard" ) ) {
  116.                 current["keyboard"] = current["general","keyboard"]:$[];
  117.                 current["general"] = remove( current["general"]:$[], "keyboard" );
  118.             }
  119.             if( haskey( current["general"]:$[], "language" ) ) {
  120.                 current["language"] = $[ "language":current["general","language"]:"" ];
  121.                 current["general"] = remove( current["general"]:$[], "language" );
  122.             }
  123.             if( haskey( current["general"]:$[], "clock" ) ) {
  124.                 current["timezone"] = current["general","clock"]:$[];
  125.                 current["general"] = remove( current["general"]:$[], "clock" );
  126.             }
  127.             if( haskey( current["software"]:$[], "additional_locales" ) ) {
  128.                 if( ! haskey(current, "language") ) {
  129.                     current["language"] = $[];
  130.                 }
  131.                 current["language","languages"] = mergestring( current["software","additional_locales"]:[], "," );
  132.                 current["software"] = remove( current["software"]:$[], "additional_locales" );
  133.             }
  134.         }
  135.     }
  136.  
  137.     /**
  138.      * Read Profile properties and Version
  139.      * @param map Profile Properties
  140.      * @return void
  141.      */
  142.     global define void ReadProperties (map properties) {
  143.         Version = properties["version"]:"";
  144.         Description = properties["description"]:"";
  145.  
  146.         if (Version != "3.0" || Version == "")
  147.         {
  148.             Version = DetectVersion();
  149.             if (Version == "")
  150.             {
  151.                 y2milestone("Can't detect Profile Version");
  152.                 return;
  153.             }
  154.         } else {
  155.             y2milestone("AutoYaST Profile Version  %1 Detected.", Version);
  156.         }
  157.         return;
  158.     }
  159.  
  160.  
  161.  
  162.     /**
  163.      * Import Profile
  164.      * @param map profile
  165.      * @return void
  166.      */
  167.     global define void Import(map<string, any> profile)
  168.     {
  169.         y2milestone("importing profile");
  170.         current  = profile;
  171.  
  172.         ReadProperties(current["properties"]:$[]);
  173.  
  174.         // old style
  175.         if (haskey(profile, "configure") || haskey(profile, "install")) {
  176.             map _configure = profile["configure"]:$[];
  177.             map _install = profile["install"]:$[];
  178.             current = remove( current, "configure" );
  179.             current = remove( current, "install" );
  180.             map tmp = (map<string, any>)union( _configure, _install );
  181.             current = (map<string, any>)union( tmp, current );
  182.         }
  183.  
  184.         // should not be needed anymore with new libsax
  185.         //if (!current["x11", "configure_x11"]:false)
  186.         //    ProductControl::DisabledModules=add(ProductControl::DisabledModules, "x11");
  187.  
  188.         // raise the network immediately after configuring it
  189.         if( haskey(current, "networking") && ! haskey(current["networking"]:$[], "start_immediately") ) {
  190.             current["networking","start_immediately"] = true;
  191.             y2milestone("start_immediately set to true");
  192.         }
  193.         storageLibCompat(); // compatibility to new storage library (SL 10.0)
  194.         generalCompat();    // compatibility to new language,keyboard and timezone (SL10.1)
  195.  
  196.         y2debug("Current Profile=%1", current );
  197.         return;
  198.     }
  199.  
  200.  
  201.     /**
  202.      * Prepare Profile for saving and remove empty data structs
  203.      * @return void
  204.      */
  205.     global define void Prepare()
  206.     {
  207.         if (!prepare)
  208.             return;
  209.  
  210.         Popup::ShowFeedback(_("Collecting configuration data..."), 
  211.                 _("This may take a while"));
  212.  
  213.         list<string> e = [];
  214.  
  215.         foreach(string p, map d, ModuleMap, {
  216.             //
  217.             // Set resource name, if not using default value
  218.             //
  219.             string resource = d["X-SuSE-YaST-AutoInstResource"]:"";
  220.             if (resource == "")
  221.                 resource = p;
  222.  
  223.             string tomerge = d["X-SuSE-YaST-AutoInstMerge"]:"";
  224.             string module_auto =d["X-SuSE-YaST-AutoInstClient"]:"none";
  225.             if ( (boolean) WFM::CallFunction(module_auto, ["GetModified"]))
  226.             {
  227.                 any resource_data = WFM::CallFunction(module_auto, ["Export"]);
  228.  
  229.                 integer s = 0;
  230.                 if ( tomerge == "") {
  231.                     if ( d["X-SuSE-YaST-AutoInstDataType"]:"map" == "map" )
  232.                     {
  233.                         s = size((map)resource_data);
  234.                     }
  235.                     else
  236.                     {
  237.                         s = size((list)resource_data);
  238.                     }
  239.                 }
  240.  
  241.                 if ( s != 0 || tomerge != "")
  242.                 {
  243.  
  244.                     if (size(tomerge) > 0 )
  245.                     {
  246.                         integer i = 0;
  247.                         string tomergetypes = d["X-SuSE-YaST-AutoInstMergeTypes"]:"";
  248.                         list MergeTypes = splitstring(tomergetypes, ",");
  249.  
  250.                         foreach( string res, (list<string>)splitstring(tomerge, ",") , ``{
  251.                             if ( MergeTypes[i]:"map" == "map")
  252.                             {
  253.                                 map<string,any> rd = (map<string,any>)resource_data;
  254.                                 current[res] = rd[res]:$[];
  255.                             } else {
  256.                                 map<string,any> rd =(map<string,any>)resource_data;
  257.                                 current[res] = rd[res]:[];
  258.                             }
  259.                             i = i + 1;
  260.                         });
  261.                     } else {
  262.                             current[resource] = resource_data;
  263.                     }
  264.                 }
  265.                 else if (s == 0 )
  266.                 {
  267.                     e = add ( e, resource);
  268.                 }
  269.             }
  270.         });
  271.  
  272.  
  273.         foreach(string k, any v, current, ``{
  274.                 if (!haskey(current, k) && !contains(e, k ))
  275.                     current[k] = v;
  276.         });
  277.  
  278.         Popup::ClearFeedback();
  279.         prepare = false;
  280.         return;
  281.  
  282.     }
  283.  
  284.     /**
  285.      * Reset profile to initial status
  286.      * @return void
  287.      */
  288.     global define void Reset ()
  289.     {
  290.         y2milestone("Resetting profile contents");
  291.         current = $[];
  292.         return;
  293.     }
  294.  
  295.     /**
  296.      * Save YCP data into XML
  297.      * @param  path to file
  298.      * @return    boolean true on success
  299.      */
  300.     global define boolean Save (string file)
  301.     {
  302.         Prepare();
  303.         y2debug("Saving data (%1) to XML file %2", current, file);
  304.         return (XML::YCPToXMLFile(`profile, current,  file));
  305.     }
  306.  
  307.  
  308.     /**
  309.      * Save the current data into a file to be read after a reboot.
  310.      * @param    -
  311.      * @return  true on success
  312.      * @see    Restore()
  313.      */
  314.     global define boolean SaveProfileStructure ( string parsedControlFile)
  315.     {
  316.         y2milestone("Saving control file in YCP format");
  317.         return SCR::Write( .target.ycp, parsedControlFile, current );
  318.     }
  319.  
  320.     /**
  321.      * Read YCP data as the control file
  322.      * @param ycp file
  323.      * @return boolean
  324.      */
  325.     global define boolean ReadProfileStructure ( string parsedControlFile )
  326.     {
  327.         current = (map<string,any>) SCR::Read( .target.ycp, [ parsedControlFile, $[]] );
  328.         if (current == $[])
  329.             return false;
  330.         else
  331.             Import (current);
  332.  
  333.         return true;
  334.     }
  335.  
  336.     /**
  337.      * Provide Compatibility to older distributions.
  338.      * @param list lvm_standalone Stand alone LVM configuration
  339.      * @return list LVM configuration integrated into partitioning resource
  340.      */
  341.     global define list<map> convertLVM (list<map> lvm_standalone )
  342.     {
  343.         list<map> all_lvm = [];
  344.  
  345.         foreach (map group, lvm_standalone, ``{
  346.             map new_lvm = $[];
  347.             string vg = group["lvm_name"]:"";
  348.  
  349.             new_lvm["device"]       = sformat("/dev/%1", vg );
  350.             new_lvm["use"]      = "all";
  351.             new_lvm["pesize"]       = group["pesize"]:"";
  352.             list partitions = maplist(map lv, group["logical_volumes"]:[], ``{
  353.  
  354.                 symbol lv_fs = `reiser;
  355.                 string lv_fs_tmp     = lv["lv_fs"]:"reiser";
  356.                 term tfs = toterm(lv_fs_tmp);
  357.                 lv_fs = (symbol)symbolof(tfs);
  358.  
  359.                 return( $[ "filesystem": lv_fs,
  360.                            "lv_name":    lv["lv_name"]:"",
  361.                            "mount":  lv["lv_mount"]:"",
  362.                            "size":   lv["lv_size"]:"",
  363.                            "stripes":    lv["stripes"]:1
  364.                         ]);
  365.             });
  366.             new_lvm["partitions"] = partitions;
  367.             all_lvm = add (all_lvm, new_lvm);
  368.  
  369.         });
  370.         y2milestone("Converted LVM: %1", all_lvm);
  371.  
  372.         return (all_lvm);
  373.     }
  374.  
  375.     /**
  376.      * Provide Compatibility to older distributions.
  377.      * @param list raid_standalone Stand alone RAID configuration
  378.      * @return map RAID configuration integrated into partitioning resource
  379.      */
  380.     global define map convertRAID (list<map> raid_standalone )
  381.     {
  382.         map raid = $[];
  383.  
  384.         raid["device"]    = "/dev/md";
  385.         raid["use"]    = "all";
  386.  
  387.         list partitions = maplist(map r, raid_standalone, ``{
  388.  
  389.             symbol fs =  r["filesystem"]:`reiser;
  390.  
  391.  
  392.             map raid_options = $[];
  393.  
  394.             raid_options["chunk_size"]            = r["chunk_size"]:"";
  395.             raid_options["raid_type"]            = r["raid_type"]:"raid1";
  396.             raid_options["parity_algorithm"]        = r["parity_algorithm"]:"";
  397.             raid_options["persistent_superblock"]    = r["persistent_superblock"]:false;
  398.  
  399.             integer nr = tointeger(substring(r["device_name"]:"/dev/md0", 7));
  400.  
  401.  
  402.  
  403.             map ret = $[
  404.                         "raid_options"    : raid_options,
  405.                         "format"    : r["format"]:false,
  406.                         "partition_nr"    : nr
  407.  
  408.             ];
  409.  
  410.             if (haskey(r, "mount"))
  411.             {
  412.                 ret["mount"] = r["mount"]:"";
  413.             }
  414.             if (haskey(r, "partition_id"))
  415.             {
  416.                 ret["partition_id"] = r["partition_id"]:131;
  417.             }
  418.             if (haskey(r, "filesystem"))
  419.             {
  420.                 ret["filesystem"] = fs;
  421.             }
  422.             if (haskey(r, "lvm_group"))
  423.             {
  424.                 ret["lvm_group"] = r["lvm_group"]:"";
  425.             }
  426.  
  427.             return (ret);
  428.  
  429.         });
  430.         raid["partitions"]    = partitions;
  431.  
  432.         return (raid);
  433.     }
  434.  
  435.  
  436.     /**
  437.      * General compatibility issues
  438.      * @param current profile
  439.      * @return map converted profile
  440.      */
  441.     define map<string, any> Compat(map<string, any> _current)
  442.     {
  443.         // scripts
  444.         if ( haskey(_current, "pre-scripts") ||
  445.             haskey(_current, "post-scripts") ||
  446.             haskey(_current, "chroot-scripts")        )
  447.         {
  448.             list pre = _current["pre-scripts"]:[];
  449.             list post = _current["post-scripts"]:[];
  450.             list chroot = _current["chroot-scripts"]:[];
  451.             map scripts = $[
  452.                             "pre-scripts":pre,
  453.                             "post-scripts":post,
  454.                             "chroot-scripts":chroot
  455.             ];
  456.             _current = remove(_current, "pre-scripts");
  457.             _current = remove(_current, "post-scripts");
  458.             _current = remove(_current, "chroot-scripts");
  459.  
  460.             _current["scripts"] = scripts;
  461.         }
  462.  
  463.         // general
  464.         boolean old = false;
  465.  
  466.         map<string, any> general_options
  467.                                 = _current["general"]:$[];
  468.         map security        = _current["security"]:$[];
  469.         map report        = _current["report"]:$[];
  470.  
  471.         foreach(string k, any v, general_options , ``{
  472.             if (k == "keyboard" && is(v, string))
  473.                 old = true;
  474.             else if (k == "mouse" && is(v, string))
  475.                 old = true;
  476.             else if (k == "encryption_method")
  477.                 old = true;
  478.             else if (k == "timezone" &&  is(v, string))
  479.                 old = true;
  480.         });
  481.  
  482.         map new_general = $[];
  483.  
  484.         if (old) {
  485.             y2milestone("Old format, converting.....");
  486.             new_general["language"]    = general_options["language"]:"";
  487.             map keyboard = $[];
  488.             keyboard["keymap"]        = general_options["keyboard"]:"";
  489.             new_general["keyboard"]    = keyboard;
  490.  
  491.             map clock = $[];
  492.             clock["timezone"]        = general_options["timezone"]:"";
  493.             if ( general_options["hwclock"]:"" == "localtime")
  494.             {
  495.                 clock["hwclock"] = "localtime";
  496.             }
  497.             else if  ( general_options["hwclock"]:""  == "GMT")
  498.             {
  499.                 clock["hwclock"] = "GMT";
  500.             }
  501.             new_general["clock"]    = clock;
  502.  
  503.             map mode = $[];
  504.             if (haskey(general_options, "reboot")) {
  505.                 mode["reboot"] =  general_options["reboot"]:false;
  506.             }
  507.             if (haskey(report, "confirm")) {
  508.                 mode["confirm"]    = report["confirm"]:false;
  509.                 report = remove(report, "confirm");
  510.             }
  511.             new_general["mode"]    = mode;
  512.  
  513.  
  514.             if (haskey(general_options, "encryption_method"))
  515.             {
  516.                 security["encryption"] = general_options["encryption_method"]:"";
  517.             }
  518.  
  519.             map net = _current["networking"]:$[];
  520.             list<map<string, string> > ifaces = net["interfaces"]:[];
  521.  
  522.             list newifaces = maplist(map<string, string> iface , ifaces, ``{
  523.                 map newiface = mapmap(string k, string v, iface, ``{
  524.                     return ($[tolower(k): v]);
  525.                 });
  526.                 return newiface;
  527.             });
  528.  
  529.             net["interfaces"] =  newifaces;
  530.  
  531.             _current["general"] = new_general;
  532.             _current["report"] = report;
  533.             _current["security"] = security;
  534.             _current["networking"] = net;
  535.         }
  536.  
  537.         // RAID
  538.         list<map> old_raid = _current["raid"]:[];
  539.         if (size(old_raid) > 0 )
  540.         {
  541.             map new_raid = convertRAID(old_raid);
  542.             list d = _current["partitioning"]:[];
  543.             d =add (d, new_raid );
  544.             _current["partitioning"] = d;
  545.         }
  546.  
  547.         // LVM
  548.         list<map> old_lvm = _current["lvm"]:[];
  549.         if (size(old_lvm) > 0 )
  550.         {
  551.             list<map> new_lvm = convertLVM(old_lvm);
  552.             list<map> d = _current["partitioning"]:[];
  553.             d = (list<map>) union (d, new_lvm );
  554.             _current["partitioning"] = d;
  555.         }
  556.         return _current;
  557.     }
  558.  
  559.  
  560.     /**
  561.      * Read XML into  YCP data
  562.      * @param  path to file
  563.      * @return    boolean
  564.      */
  565.     global define boolean ReadXML (string file) {
  566.         y2debug("Reading %1", file);
  567.         current = XML::XMLToYCPFile(file);
  568.  
  569.         if ( current != $[]  && size(current) == 0 )
  570.         {
  571.         // autoyast has read the autoyast configuration file but something went wrong
  572.         string message = _("The XML parser reported an error while parsing the autoyast profile. The error message is:\n");
  573.         message = message + XML::XMLError();
  574.         Popup::Error ( message );
  575.             return (false);
  576.         }
  577.         Import (current);
  578.         return (true);
  579.     }
  580.  
  581.  
  582.     define map<string,any> setMValue( list<any> l, any v, map<string,any> m );
  583.     define list<any> setLValue( list<any> l, any v, list<any> m );
  584.  
  585.  
  586.     /*
  587.         setMValue together with setLValue are helper functions for
  588.         setElementyList
  589.     */
  590.     map<string,any> setMValue( list<any> l, any v, map<string,any> m ) {
  591.         string i = (string)l[0]:"";
  592.         list<any> tmp = remove(l,0);
  593.         if( size(tmp) > 0 ) {
  594.             if( is( tmp[0]:nil, string ) ) {
  595.                 m[i] = setMValue( tmp, v, m[i]:$[] );
  596.             } else {
  597.                 y2milestone("I'm in else");
  598.                 m[i] = setLValue( tmp, v, m[i]:[] );
  599.             }
  600.         } else {
  601.             y2milestone("setting %1 to %2",i,v);
  602.             m[i] = v;
  603.         }
  604.         return m;
  605.     }
  606.  
  607.     list<any> setLValue( list<any> l, any v, list<any> m ) {
  608.         integer i = (integer)l[0]:0;
  609.         list<any> tmp = remove(l,0);
  610.         if( is( tmp[0]:nil, string ) ) {
  611.             m[i] = setMValue( tmp, v, m[i]:$[] );
  612.         } else {
  613.             m[i] = setLValue( tmp, v, m[i]:[] );
  614.         }
  615.         return m;
  616.     }
  617.  
  618.     /**
  619.      *  this function is a replacement for this code:
  620.      *      list<any> l = [ "key1",0,"key3" ]; 
  621.      *      m[ l ] = v;
  622.      *  @return map
  623.      */
  624.     global define map<string,any> setElementByList( list<any> l, any v, map<string,any> m ) {
  625.         m = setMValue( l, v, m );
  626.         return m;
  627.     }
  628.  
  629.     global void checkProfile() {
  630.         string file = AutoinstConfig::tmpDir + "/" + "valid.xml";
  631.         Save(file);
  632.         string summary = "Some schema check failed!\nPlease attach your logfile to bug id 211014\n\n";
  633.         boolean valid = false;
  634.  
  635.         list<list> validators = [
  636.             [
  637.             _("Checking XML with RNG validation..."),
  638.             "/usr/bin/xmllint --noout --relaxng "
  639.             + Directory::schemadir + "/autoyast/rng/profile.rng", ""
  640.             ]
  641.         ];
  642.         if ( ! Stage::cont() && PackageSystem::Installed("jing") ) {
  643.             validators = add( validators, [
  644.             _("Checking XML with RNC validation..."),
  645.             "/usr/bin/jing >&2 -c "
  646.             + Directory::schemadir + "/autoyast/rnc/profile.rnc", "jing_sucks"
  647.             ] );
  648.         }
  649.  
  650.         foreach (list i, validators, {
  651.             string header = i[0]:"";
  652.             string cmd = i[1]:"" + " " + file;
  653.  
  654.             summary = summary + header + "\n";
  655.  
  656.             map o = (map)SCR::Execute (.target.bash_output, cmd);
  657.             y2debug("validation output: %1", o);
  658.  
  659.             summary = summary + cmd + "\n";
  660.             summary = summary + o["stderr"]:"" + "\n";
  661.             summary = summary + "\n";
  662.             if( o["exit"]:1 != 0 || (i[2]:"" == "jing_sucks" && size(o["stderr"]:"") > 0 ) )
  663.                     valid = false;
  664.         });
  665.         if( ! valid ) {
  666.             Popup::Error(summary);
  667.             y2milestone("Profile check failed please attach the log to bug id 211014: %1",summary);
  668.         }
  669.     }
  670.  
  671. }
  672.