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 / AutoInstallRules.ycp < prev    next >
Text File  |  2006-11-29  |  28KB  |  879 lines

  1. /**
  2.  * File:    modules/AutoInstallRules.ycp
  3.  * Package:    Auto-installation
  4.  * Summary:    Process Auto-Installation Rules
  5.  * Author:    Anas Nashif <nashif@suse.de>
  6.  *
  7.  * $Id: AutoInstallRules.ycp 29265 2006-03-22 14:48:47Z ug $
  8.  */
  9. {
  10.  
  11.     module "AutoInstallRules";
  12.     textdomain "autoinst";
  13.  
  14.  
  15.     import "Arch";
  16.     import "Stage";
  17.     import "Installation";
  18.     import "AutoinstConfig";
  19.     import "XML";
  20.     import "Storage";
  21.     import "Kernel";
  22.     import "Mode";
  23.     import "Profile";
  24.     import "Label";
  25.     import "Report";
  26.     import "Popup";
  27.     import "URL";
  28.     import "IP";
  29.     import "Product";
  30.  
  31.     include "autoinstall/io.ycp";
  32.  
  33.     global boolean userrules = false;
  34.     global boolean dontmergeIsDefault = true;
  35.     global list<string> dontmergeBackup = [];
  36.  
  37.     global symbol Behaviour = `many;
  38.  
  39.     /////////////////////////////////////////////
  40.     // Pre-defined Rules
  41.     /////////////////////////////////////////////
  42.  
  43.     // All system attributes;
  44.     map ATTR = $[];
  45.  
  46.     global string installed_product = "";
  47.  
  48.     global string installed_product_version = "";
  49.  
  50.     global string hostname = "";
  51.  
  52.     global string hostaddress = "";
  53.  
  54.     global string network = "";
  55.  
  56.     global string domain = "";
  57.  
  58.     global string arch = "";
  59.  
  60.     global string karch = "";
  61.  
  62.     // Taken from smbios
  63.     global string product = "";
  64.  
  65.     // Taken from smbios
  66.     global string product_vendor = "";
  67.  
  68.     // Taken from smbios
  69.     global string board_vendor = "";
  70.  
  71.     // Taken from smbios
  72.     global string board = "";
  73.  
  74.     global integer memsize = 0;
  75.  
  76.     global list<map<string, any> > disksize = [];
  77.  
  78.     global integer totaldisk = 0;
  79.  
  80.     global string hostid = "";
  81.  
  82.     global string mac = "";
  83.  
  84.     global integer linux = 0;
  85.  
  86.     global integer others = 0;
  87.  
  88.     global string xserver = "";
  89.  
  90.     global string haspcmcia = "0";
  91.  
  92.     /////////////////////////////////////////////
  93.     /////////////////////////////////////////////
  94.  
  95.     global list NonLinuxPartitions = [];
  96.  
  97.     global list LinuxPartitions = [];
  98.  
  99.  
  100.     global map<string, any> UserRules = $[];
  101.  
  102.     // Local Variables
  103.     string shell = "";
  104.     map env = $[];
  105.  
  106.     global list<string> tomerge = [];
  107.  
  108.  
  109.  
  110.     /**
  111.      * Cleanup XML file from namespaces put by xslt
  112.      */
  113.     global define boolean XML_cleanup(string in, string out) ``{
  114.         map ycpin = XML::XMLToYCPFile(in);
  115.         y2debug("Writing clean XML file to  %1, YCP is (%2)", out, ycpin);
  116.         return XML::YCPToXMLFile(`profile, ycpin, out);
  117.     }
  118.  
  119.  
  120.     /**
  121.      * StdErrLog()
  122.      * Dialog for error messages
  123.      */
  124.     global define void StdErrLog( string stderr) ``{
  125.         UI::OpenDialog(
  126.                        `opt( `decorated ),
  127.                        `VBox(
  128.                              `VSpacing(0.5),
  129.                              `HSpacing(50),
  130.                              `HBox (
  131.                                     `HSpacing(0.5),
  132.                                     `LogView(`id(`log),  Label::ErrorMsg()  , 10, 100 ),
  133.                                     `HSpacing(0.5)
  134.                                     ),
  135.                              `VSpacing(0.2),
  136.                              `PushButton( `id(`ok), `opt(`default), Label::OKButton() ),
  137.                              `VSpacing(0.5)
  138.                              )
  139.                        );
  140.  
  141.         UI::ChangeWidget(`id(`log),`Value, stderr);
  142.         UI::UserInput();
  143.         UI::CloseDialog();
  144.  
  145.     };
  146.     /**
  147.      * getMAC()
  148.      * Return MAC address of active device
  149.      * @return string mac address
  150.      */
  151.     global define string getMAC()
  152.     {
  153.         string tmpmac = "";
  154.         if (Stage::initial ())
  155.         {
  156.             tmpmac  = (string)SCR::Read (.etc.install_inf.HWAddr);
  157.         }
  158.         string cleanmac = deletechars((tmpmac!=nil)?tmpmac:"", ":");
  159.         return cleanmac;
  160.     }
  161.  
  162.  
  163.     /**
  164.      * Return host id (hex ip )
  165.      * @return string host ID
  166.      */
  167.     global define string getHostid ()
  168.     {
  169.         string hex = IP::ToHex(hostaddress);
  170.         return hex;
  171.     }
  172.  
  173.  
  174.     /**
  175.      * Probe all system data to build  a set of rules
  176.      * @return void
  177.      */
  178.     global define void ProbeRules ()
  179.     {
  180.  
  181.         // SMBIOS Data
  182.         list bios = (list) SCR::Read(.probe.bios);
  183.  
  184.         if (size(bios) != 1)
  185.         {
  186.             y2warning("Warning: BIOS list size is %1", size(bios));
  187.         }
  188.  
  189.         map biosinfo = (map)(bios[0]:$[]);
  190.         list<map> smbios = (list<map>)(biosinfo["smbios"]:[]);
  191.  
  192.         map sysinfo = $[];
  193.         map boardinfo = $[];
  194.  
  195.         foreach(map inf, smbios, ``{
  196.             if (inf["type"]:"" == "sysinfo")
  197.             {
  198.                 sysinfo = inf;
  199.             }
  200.             else if (inf["type"]:"" == "boardinfo")
  201.             {
  202.                 boardinfo = inf;
  203.             }
  204.         });
  205.  
  206.         if (size(sysinfo) > 0)
  207.         {
  208.             product = (string)(sysinfo["product"]:"default");
  209.             product_vendor = (string)(sysinfo["manufacturer"]:"default");
  210.         }
  211.  
  212.         if (size(boardinfo) > 0)
  213.         {
  214.             board = (string)(boardinfo["product"]:"default");
  215.             board_vendor = (string)(boardinfo["manufacturer"]:"default");
  216.         }
  217.  
  218.         ATTR["product"] = product;
  219.         ATTR["product_vendor"] = product_vendor;
  220.         ATTR["board"] = board;
  221.         ATTR["board_vendor"] = board_vendor;
  222.  
  223.         //
  224.         // Architecture
  225.         //
  226.  
  227.         arch = Arch::architecture ();
  228.         karch = Kernel::GetPackages ()[0]:"kernel-default";
  229.  
  230.         ATTR["arch"] = arch;
  231.         ATTR["karch"] = karch;
  232.  
  233.         //
  234.         // Memory
  235.         //
  236.  
  237.         integer memory = 0;
  238.         list memories = (list)SCR::Read(.probe.memory);
  239.         memory = memories[0,"resource","phys_mem",0,"range"]:0;
  240.         memsize =  memory / ( 1024 * 1024);
  241.         ATTR["memsize"] = memsize;
  242.  
  243.         //
  244.         // Disk sizes
  245.         //
  246.  
  247.         map<string,map> storage =  Storage::GetTargetMap();
  248.         map<string,map> PhysicalTargetMap = filter(string k, map v, storage ,
  249.                 ``(Storage::IsRealDisk(v) ));
  250.         totaldisk = 0;
  251.         disksize = maplist( string k, map v,  PhysicalTargetMap,
  252.                             ``{
  253.                                 integer size_in_mb = v["size_k"]:0 / 1024;
  254.                                 totaldisk = totaldisk + size_in_mb;
  255.                                 return($["device":k, "size": size_in_mb]);
  256.                             });
  257.         y2debug("disksize: %1", disksize);
  258.         //
  259.         // MAC
  260.         //
  261.         mac = getMAC();
  262.         ATTR["mac"] = mac;
  263.  
  264.         //
  265.         // Network
  266.         //
  267.         if (Stage::initial ())
  268.         {
  269.             hostaddress  = (string)SCR::Read(.etc.install_inf.IP);
  270.         }
  271.         else
  272.         {
  273.             hostaddress  = "192.168.1.1"; // FIXME
  274.         }
  275.         ATTR["hostaddress"] = hostaddress;
  276.  
  277.         //
  278.         // Hostid (i.e. a8c00101);
  279.         //
  280.         hostid = getHostid();
  281.  
  282.         ATTR["hostid"] = hostid;
  283.  
  284.  
  285.         hostname = (string)SCR::Read(.etc.install_inf.Hostname);
  286.         ATTR["hostname"] = hostname;
  287.         domain = (string)SCR::Read(.etc.install_inf.Domain);
  288.         ATTR["domain"] = domain;
  289.         network = (string)SCR::Read(.etc.install_inf.Network);
  290.         ATTR["network"] = network;
  291.         haspcmcia = (string)SCR::Read(.etc.install_inf.HasPCMCIA);
  292.         ATTR["haspcmcia"] = haspcmcia;
  293.         xserver = (string)SCR::Read(.etc.install_inf.XServer);
  294.         ATTR["xserver"] = xserver;
  295.  
  296.         NonLinuxPartitions = Storage::GetForeignPrimary();
  297.         others = size(NonLinuxPartitions );
  298.  
  299.         y2milestone ("Other primaries: %1", NonLinuxPartitions);
  300.  
  301.         LinuxPartitions = Storage::GetOtherLinuxPartitions();
  302.         linux = size(LinuxPartitions);
  303.  
  304.         y2milestone ("Other linux parts: %1",  LinuxPartitions);
  305.  
  306.         installed_product = Product::name;
  307.         installed_product_version = Product::version;
  308.         ATTR["installed_product"] = installed_product;
  309.         ATTR["installed_product_version"] = installed_product_version;
  310.  
  311.         y2milestone("Installing %1 %2", installed_product, installed_product_version);
  312.  
  313.         return;
  314.     }
  315.  
  316.  
  317.  
  318.  
  319.     /**
  320.      * Create shell command for rule verification
  321.      * @param match
  322.      * @param var
  323.      * @param val
  324.      * @param op
  325.      * @param matchtype
  326.      * @return void
  327.      */
  328.     define void shellseg (boolean match, string var, any val, string op, string matchtype)
  329.     {
  330.         if (op == "and")
  331.             op = " && ";
  332.         else if (op == "or")
  333.             op = " || ";
  334.  
  335.         string tmpshell = " ( [";
  336.         y2debug("Match type: %1", matchtype);
  337.         if (is( val, string) && (string)val == "*")
  338.         {
  339.             // match anything
  340.             tmpshell = tmpshell + " \"1\" = \"1\" ";
  341.         }
  342.         else if (matchtype == "exact")
  343.         {
  344.             tmpshell = tmpshell + sformat(" \"$%1\" = \"%2\" ", var,  val);
  345.         }
  346.         else if (matchtype == "greater")
  347.         {
  348.             tmpshell = tmpshell + sformat(" \"$%1\" -gt \"%2\" ",  var,  val);
  349.         }
  350.         else if (matchtype == "lower")
  351.         {
  352.             tmpshell = tmpshell + sformat(" \"$%1\" -lt \"%2\" ",  var,  val);
  353.         }
  354.         else if (matchtype == "range")
  355.         {
  356.             list<string> range =splitstring(tostring(val), "-");
  357.             y2debug("Range: %1", range);
  358.             tmpshell = tmpshell + sformat(" \"$%1\" -gt \"%2\" -a \"$%1\" -lt \"%3\" ",  var,  range[0]:"0",  range[1]:"0");
  359.         }
  360.         else if( matchtype == "regex" )
  361.         {
  362.             tmpshell = tmpshell + sformat("[ \"$%1\" =~ \"%2\" ]",  var,  val);
  363.         }
  364.  
  365.         if (match)
  366.         {
  367.             shell = shell + sformat(" %1 %2] )", op, tmpshell);
  368.         }
  369.         else
  370.         {
  371.             shell = tmpshell + "] ) ";
  372.         }
  373.  
  374.         y2debug("var: %1, val: %2", var, val);
  375.         y2debug("shell: %1", shell);
  376.         return;
  377.     }
  378.  
  379.  
  380.     /**
  381.      * Verify rules using the shell
  382.      * @return integer
  383.      */
  384.     define integer verifyrules ()
  385.     {
  386.  
  387.         string script = sformat("if %1; then exit 0; else exit 1; fi", shell);
  388.         map ret = (map)SCR::Execute (.target.bash_output, script, env);
  389.  
  390.         y2milestone("Bash return: %1 (%2) (%3)", script, ret, env);
  391.  
  392.         return ret["exit"]:-1;
  393.     }
  394.  
  395.     string SubVars(string file)
  396.     {
  397.         y2milestone("file: %1" , file);
  398.         string var = "";
  399.         any first = findfirstof(file, "@");
  400.         any last = findlastof(file, "@");
  401.         if (first!= nil && last!=nil)
  402.         {
  403.             integer ffirst = (integer) first + 1;
  404.             integer llast = (integer) last;
  405.             if (first!=last)
  406.             {
  407.                 var = substring(file,ffirst  , llast - ffirst );
  408.             }
  409.         }
  410.         y2milestone("var: %1", var);
  411.         if (var!="")
  412.         {
  413.             string val = ATTR[var]:"";
  414.             string new = regexpsub(file,"(.*)@.*@(.*)",sformat("\\1%1\\2", val));
  415.             if (new!="")
  416.                 return new;
  417.         }
  418.         y2milestone("val: %1", file);
  419.         return file;
  420.  
  421.     }
  422.     /**
  423.      * Read rules file
  424.      * @return void
  425.      */
  426.     global define void Read()
  427.     {
  428.         UserRules = XML::XMLToYCPFile( AutoinstConfig::local_rules_file );
  429.  
  430.         if( UserRules == nil ) {
  431.             string message = _("Parsing the rules file failed. XML parser reports:\n");
  432.             Popup::Error( message + XML::XMLError() );
  433.         }
  434.         y2milestone("Rules: %1", UserRules);
  435.  
  436.         list<map <string, map> > rulelist = UserRules["rules"]:[];
  437.         if (rulelist == nil)        // check result of implicit type conversion
  438.         {
  439.             y2error ("Key 'rules' has wrong type");
  440.             rulelist = [];
  441.         }
  442.  
  443.         boolean ismatch = false;
  444.         boolean go_on = true;
  445.         foreach ( map<string, map> ruleset, rulelist, ``{
  446.             y2debug("Ruleset: %1", ruleset);
  447.             if (go_on) {
  448.                 foreach(string rule, map ruledef, ruleset, ``{
  449.                     y2debug("Rule: %1", rule);
  450.                     y2debug("Ruledef: %1", ruledef);
  451.  
  452.                     string match = ruledef["match"]:"undefined";
  453.  
  454.                     string op = ruledef["operator"]:"and";
  455.                     string matchtype = ruledef["match_type"]:"exact";
  456.  
  457.                     list<string> easy_rules = [
  458.                     "hostname",
  459.                     "hostaddress",
  460.                     "installed_product_version",
  461.                     "installed_product",
  462.                     "domain",
  463.                     "network",
  464.                     "mac",
  465.                     "karch",
  466.                     "hostid",
  467.                     "arch",
  468.                     "board",
  469.                     "board_vendor",
  470.                     "product_vendor",
  471.                     "product" ];
  472.                     if ( contains(easy_rules, rule))
  473.                     {
  474.                         shellseg(ismatch, rule, match, op, matchtype);
  475.                         ismatch = true;
  476.                         env[rule] = ATTR[rule]:"";
  477.                     }
  478.                     else if ( rule == "custom1" ||  rule == "custom2" || rule == "custom3" ||  rule == "custom4" || rule == "custom5")
  479.                     {
  480.                         string script = ruledef["script"]:"exit -1";
  481.                         string tmpdir = AutoinstConfig::tmpDir;
  482.  
  483.                         string scriptPath = sformat("%1/%2", tmpdir,  "rule_" + rule);
  484.  
  485.                         y2milestone("Writing rule script into %1", scriptPath);
  486.                         SCR::Write(.target.string, scriptPath, script);
  487.  
  488.                         map out = (map) SCR::Execute (.target.bash_output, "/bin/sh " + scriptPath, $[]);
  489.                         string script_result = out["stdout"]:"";
  490.                         shellseg(ismatch, rule, match, op, matchtype);
  491.                         ismatch = true;
  492.                         ATTR[rule] = script_result;
  493.                         env[rule] = script_result;
  494.                     }
  495.                     else if ( rule == "linux" )
  496.                     {
  497.                         shellseg(ismatch, rule, match, op, matchtype);
  498.                         ismatch = true;
  499.                         env[rule] = linux;
  500.                     }
  501.                     else if ( rule == "others" )
  502.                     {
  503.                         shellseg(ismatch, rule, match, op, matchtype);
  504.                         ismatch = true;
  505.                         env[rule] = others;
  506.                     }
  507.                     else if ( rule == "xserver" )
  508.                     {
  509.                         shellseg(ismatch, rule, match, op, matchtype);
  510.                         ismatch = true;
  511.                         env[rule] = xserver;
  512.                     }
  513.                     else if ( rule == "memsize" )
  514.                     {
  515.                         shellseg(ismatch, rule, match, op, matchtype);
  516.                         ismatch = true;
  517.                         env[rule] = memsize;
  518.                     }
  519.                     else if ( rule == "totaldisk" )
  520.                     {
  521.                         shellseg(ismatch, rule, match, op, matchtype);
  522.                         ismatch = true;
  523.                         env[rule] = totaldisk;
  524.                     }
  525.                     else if ( rule == "haspcmcia" )
  526.                     {
  527.                         shellseg(ismatch, rule, match, op, matchtype);
  528.                         ismatch = true;
  529.                         env[rule] = haspcmcia;
  530.                     }
  531.                     else if ( rule == "disksize" )
  532.                     {
  533.                         y2debug("creating rule check for disksize");
  534.                         list<string> disk = splitstring(match, " ");
  535.                         integer i = 0;
  536.                         string t  = "";
  537.                         if (shell != "" )
  538.                         {
  539.                             t  = shell + sformat(" %1 ( ", (op == "and") ? "&&" : "||" );
  540.                         }
  541.                         else
  542.                         {
  543.                             t  = shell + sformat(" ( ");
  544.                         }
  545.                         foreach(map<string, any> dev, disksize, {
  546.                             string var1 = sformat("disksize_size%1", i );
  547.                             string var2 = sformat("disksize_device%1", i );
  548.  
  549.                             if (matchtype == "exact") {
  550.                                 t = t + sformat(" [ \"$%1\" = \"%2\" -a \"$%3\" = \"%4\" ] ", var1, disk[1]:"" , var2, disk[0]:"");
  551.                             } else if (matchtype == "greater") {
  552.                                 t = t + sformat(" [ \"$%1\" -gt \"%2\"  -a \"$%3\" = \"%4\" ] ", var1, disk[1]:"" , var2, disk[0]:"");
  553.                             } else if (matchtype == "lower") {
  554.                                 t = t + sformat(" [ \"$%1\" -lt \"%2\" -a \"$%3\" = \"%4\" ] ", var1, disk[1]:"" , var2, disk[0]:"");
  555.                             }
  556.  
  557.                             env[var1] = dev["size"]:-1;
  558.                             env[var2] = dev["device"]:"";
  559.                             i = i + 1;
  560.                             if ( size(disksize) > i )
  561.                             {
  562.                                 t = t + " || ";
  563.                             }
  564.                         });
  565.                         t = t + " ) ";
  566.                         shell = t;
  567.                         y2debug("shell: %1", shell);
  568.                         ismatch = true;
  569.                     }
  570.                     else if ( rule == "result" )
  571.                     {
  572.                         if ( verifyrules() == 0 )
  573.                         {
  574.                             string profile_name = ruledef["profile"]:"";
  575.                             profile_name = SubVars(profile_name);
  576.                             y2milestone("Final Profile name: %1", profile_name
  577.                                     );
  578.                             if (ruledef["match_with_base"]:true)
  579.                             {
  580.                                 tomerge = add(tomerge, profile_name);
  581.                             }
  582.                             // backdoor for merging problems.
  583.                             if( haskey(ruledef, "dont_merge") ) {
  584.                                 if( dontmergeIsDefault ) {
  585.                                     dontmergeBackup = AutoinstConfig::dontmerge;
  586.                                     AutoinstConfig::dontmerge = [];
  587.                                 }
  588.                                 AutoinstConfig::dontmerge = (list<string>)union( AutoinstConfig::dontmerge, ruledef["dont_merge"]:[] );
  589.                                 dontmergeIsDefault = false;
  590.                                 y2milestone("user defined dont_merge for rules found. dontmerge is %1", AutoinstConfig::dontmerge);
  591.                             }
  592.                             go_on = ruledef["continue"]:false;
  593.                         }
  594.                         else
  595.                         {
  596.                             go_on = true;
  597.                         }
  598.                         shell = "";
  599.                         ismatch = false;
  600.                     }
  601.  
  602.                 });
  603.             }
  604.         });
  605.         return;
  606.     }
  607.  
  608.  
  609.  
  610.     /**
  611.      * Return list of file to merge (Order matters)
  612.      * @return list list of files
  613.      */
  614.     global define list<string> Files ()
  615.     {
  616.         return tomerge;
  617.     }
  618.  
  619.     /**
  620.      * Return list of file to merge (Order matters)
  621.      * @return boolean
  622.      */
  623.     global define boolean GetRules ()
  624.     {
  625.         y2milestone("Getting Rules: %1", tomerge);
  626.  
  627.         string scheme = AutoinstConfig::scheme;
  628.         string host = AutoinstConfig::host;
  629.         string filepath = AutoinstConfig::filepath;
  630.         string directory = AutoinstConfig::directory;
  631.  
  632.         list<string> valid = [];
  633.         boolean stop = false;
  634.         foreach(string file, tomerge, ``{
  635.             if (!stop) {
  636.                 string dir = dirname ( file );
  637.                 if (dir != "") {
  638.                     SCR::Execute(.target.mkdir, AutoinstConfig::local_rules_location + "/" + dir);
  639.                 }
  640.  
  641.                 string localfile = AutoinstConfig::local_rules_location + "/" + file  ;
  642.                 if (!Get( scheme, host, directory + "/" + file, localfile)) {
  643.                     y2error("Error while fetching file:  %1", directory + "/" + file);
  644.                 } else {
  645.                     if (Behaviour == `one) {
  646.                         stop = true;
  647.                     }
  648.                     valid = add(valid, file);
  649.                 }
  650.             }
  651.         });
  652.         tomerge = valid;
  653.         if (size ( tomerge ) == 0 ) {
  654.             y2milestone("No files from rules found");
  655.             return (false);
  656.         } else {
  657.             return (true);
  658.         }
  659.     }
  660.  
  661.  
  662.     /**
  663.      * Merge Rule results
  664.      * @param result_profile the resulting control file path
  665.      * @return boolean true on success
  666.      */
  667.     global define boolean Merge (  string result_profile   )
  668.     {
  669.  
  670.         string tmpdir = AutoinstConfig::tmpDir;
  671.         boolean ok = true;
  672.         boolean skip = false;
  673.         boolean error = false;
  674.  
  675.         string base_profile  =  tmpdir + "/base_profile.xml";
  676.  
  677.         foreach(string file, tomerge,
  678.                 ``{
  679.             y2milestone("Working on file: %1", file);
  680.  
  681.             string current_profile = AutoinstConfig::local_rules_location + "/" + file;
  682.             if (!skip)
  683.             {
  684.                 if (!XML_cleanup(current_profile,  tmpdir + "/base_profile.xml"))
  685.                 {
  686.                     y2error("Error reading XML file");
  687.                     string message = _("The XML parser reported an error while parsing the autoyast profile. The error message is:\n");
  688.                     message = message + XML::XMLError();
  689.                     Popup::Error ( message );
  690.                     error = true;
  691.                 }
  692.                 skip = true;
  693.             }
  694.             else if (!error )
  695.             {
  696.                 string MergeCommand = "/usr/bin/xsltproc --novalid --param replace \"'false'\" ";
  697.                 string dontmerge_str = "";
  698.                 integer i = 1;
  699.                 foreach (string dm,  AutoinstConfig::dontmerge, ``{
  700.                     dontmerge_str = dontmerge_str + sformat(" --param dontmerge%1 \"'%2'\" ", i,  dm);
  701.                     i = i + 1;
  702.                 });
  703.                 MergeCommand = MergeCommand + dontmerge_str;
  704.  
  705.                 MergeCommand = MergeCommand + "--param with ";
  706.                 MergeCommand = MergeCommand + "\"'" + current_profile + "'\"  ";
  707.                 MergeCommand = MergeCommand + "--output " +  tmpdir + "/result.xml";
  708.                 MergeCommand = MergeCommand + " /usr/share/autoinstall/xslt/merge.xslt ";
  709.                 MergeCommand = MergeCommand +   base_profile + " ";
  710.  
  711.                 map xsltret = (map)SCR::Execute(.target.bash_output, MergeCommand);
  712.                 y2milestone("Merge result: %1", xsltret);
  713.                 if (xsltret["exit"]:-1 != 0 || xsltret["stderr"]:"" != "")
  714.                 {
  715.                     y2error("Merge Failed");
  716.                     StdErrLog(xsltret["stderr"]:"");
  717.                     ok =  false;
  718.                 }
  719.  
  720.                 XML_cleanup(tmpdir + "/result.xml",  tmpdir + "/base_profile.xml");
  721.  
  722.             }
  723.             else
  724.             {
  725.                 y2error ("Error while merging control files");
  726.             }
  727.         });
  728.  
  729.         if (error )
  730.         {
  731.             return !error;
  732.         }
  733.  
  734.         SCR::Execute(.target.bash, "cp " +  tmpdir + "/base_profile.xml " + result_profile );
  735.  
  736.         y2milestone("Ok=%1", ok);
  737.         dontmergeIsDefault = true;
  738.         AutoinstConfig::dontmerge = dontmergeBackup;
  739.         return ok;
  740.     }
  741.  
  742.  
  743.     /**
  744.      * Process Rules
  745.      * @param string result_profile
  746.      * @return boolean
  747.      */
  748.     global define boolean Process(  string result_profile  )
  749.     {
  750.  
  751.         boolean ok = true;
  752.         string tmpdir = AutoinstConfig::tmpDir;
  753.         string prefinal = AutoinstConfig::local_rules_location + "/prefinal_autoinst.xml" ;
  754.         if (!Merge (  prefinal ) )
  755.         {
  756.             return false;
  757.         }
  758.  
  759.         tomerge = [];
  760.  
  761.  
  762.         // Now check if there any classes defined in theis pre final control file
  763.         if (! Profile::ReadXML( prefinal ))
  764.         {
  765.             Popup::Error(_("Error while parsing the control file.
  766. Check the log files for more details or fix the
  767. control file and try again.
  768. "));
  769.             return false;
  770.         }
  771.         y2milestone("Checking classes...");
  772.         if ( haskey(Profile::current, "classes") )
  773.         {
  774.             y2milestone("User defined classes available, processing....");
  775.             list<map> classes = Profile::current["classes"]:[];
  776.             foreach(map class, classes,
  777.                     ``{
  778.                 // backdoor for merging problems.
  779.                 if( haskey(class, "dont_merge") ) {
  780.                     if( dontmergeIsDefault )
  781.                         AutoinstConfig::dontmerge = [];
  782.                     AutoinstConfig::dontmerge = (list<string>)union( AutoinstConfig::dontmerge, class["dont_merge"]:[] );
  783.                     dontmergeIsDefault = false;
  784.                     y2milestone("user defined dont_merge for class found. dontmerge is %1", AutoinstConfig::dontmerge);
  785.                 }
  786.  
  787.                 tomerge = add(tomerge,  "classes/" + class["class_name"]:"none" + "/" + class["configuration"]:"none");
  788.             });
  789.  
  790.             y2milestone("New files to process: %1", tomerge);
  791.             Behaviour = `multiple;
  792.             boolean ret  = GetRules();
  793.             if (ret)
  794.             {
  795.                 tomerge = prepend(tomerge, "prefinal_autoinst.xml");
  796.                 ok = Merge ( result_profile );
  797.             }
  798.             else
  799.             {
  800.                 Report::Error(_("
  801. User-defined classes could not be retrieved.  Make sure all classes 
  802. are defined correctly and available for this system via the network
  803. or locally. The system cannot be installed with the original control 
  804. file without using classes.
  805. "));
  806.  
  807.                 ok = false;
  808.                 SCR::Execute(.target.bash, "cp " + prefinal + " "  + result_profile );
  809.             }
  810.         }
  811.         else
  812.         {
  813.             SCR::Execute(.target.bash, "cp " + prefinal + " "  + result_profile );
  814.         }
  815.         y2milestone("returns=%1", ok );
  816.         return ok;
  817.  
  818.     }
  819.  
  820.  
  821.     /**
  822.      * Create default rule in case no rules file is available
  823.      * This adds a list of file starting from full hex ip representation to
  824.      * only the first letter. Then default and finally mac address.
  825.      * @return void
  826.      */
  827.     global define void CreateDefault()
  828.     {
  829.         Behaviour = `one;
  830.         string tmp_hex_ip = hostid;
  831.         tomerge = add(tomerge, tmp_hex_ip );
  832.         while (size(tmp_hex_ip) != 1)
  833.         {
  834.             tmp_hex_ip = substring(tmp_hex_ip, 0 , size ( tmp_hex_ip ) - 1 );
  835.             tomerge = add(tomerge, tmp_hex_ip );
  836.         }
  837.         tomerge = add(tomerge, toupper(mac) );
  838.         tomerge = add(tomerge, tolower(mac) );
  839.         tomerge = add(tomerge, "default" );
  840.         y2milestone("Created default rules=%1", tomerge);
  841.         return;
  842.     }
  843.  
  844.    /**
  845.     * Create default rule in case no rules file is available (Only one file which is given by the user)
  846.     * @param filename file name
  847.     * @return void
  848.     */
  849.     global define void CreateFile(string filename) 
  850.     {
  851.         tomerge = add (tomerge, filename);
  852.         y2milestone("Created default rules: %1", tomerge);
  853.         return;
  854.     }
  855.     /**
  856.      * Constructor
  857.      *
  858.      */
  859.     global define void AutoInstallRules () ``{
  860.         return;
  861.     }
  862.  
  863.  
  864.     /**
  865.       * Initialize
  866.       */
  867.     global define void Init () ``{
  868.  
  869.         if (Stage::initial () || Mode::test ())
  870.         {
  871.             ProbeRules();
  872.         }
  873.  
  874.         return;
  875.     }
  876.  
  877.  
  878. }
  879.