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 / VM_XEN.ycp < prev    next >
Text File  |  2006-11-29  |  82KB  |  2,671 lines

  1. /**
  2.  * File:    modules/VM_XEN.ycp
  3.  * Package:    XEN specific functions and values
  4.  * Authors:    Ladislav Slezak <lslezak@suse.cz>
  5.  *        Michael G. Fritch <mgfritch@novell.com>
  6.  * $Id: VM_XEN.ycp 34035 2006-11-04 00:38:38Z mgfritch $
  7.  */
  8. {
  9.     module "VM_XEN";
  10.  
  11.     import "VM_Common";
  12.     import "Popup";
  13.     import "Report";
  14.     import "HTML";
  15.     import "Mode";
  16.     import "Arch";
  17.     import "String";
  18.     import "Label";
  19.     import "Service";
  20.  
  21.     textdomain "vm";
  22.  
  23.     global list <map <string,any> > disks = [];
  24.  
  25.     list <map <string,string> > default_network = [];
  26.     global list <map <string,string> > network = [];
  27.  
  28.     string img_prefix = "/var/lib/xen/images/";
  29.  
  30.     string conf_path = "/etc/xen/vm/";
  31.     string conf_prefix = "vm";
  32.  
  33.     string kernel_path = "";
  34.  
  35.     string initrd_path = "";
  36.  
  37.     global string xm = "/usr/sbin/xm";
  38.     global string xend = "/etc/init.d/xend";
  39.  
  40.     string default_restart = "onreboot";  //FIXME: config file option 'restart' is depreciated!!!
  41.     string restart = default_restart;  //FIXME: config file option 'restart' is depreciated!!!
  42.  
  43.     string default_boot_device = "d";
  44.     string boot_device = default_boot_device;
  45.  
  46.     string default_cdrom_image = "";
  47.     string cdrom_image = default_cdrom_image;
  48.  
  49.     string default_cdrom_image_type = "phy";
  50.     string cdrom_image_type = default_cdrom_image_type;
  51.  
  52.     global map SubExport() {
  53.     map ret = $[
  54.         "Common"        : VM_Common::Export(),
  55.         "disks"            : disks,
  56.         "network"        : network,
  57.         "kernel_path"        : kernel_path,
  58.         "initrd_path"        : initrd_path,
  59.         "restart"        : restart,
  60.         "boot_device"        : boot_device,
  61.         "cdrom_image"        : cdrom_image,
  62.         "cdrom_image_type"    : cdrom_image_type
  63.     ];
  64.  
  65.     y2milestone("SubExport() returned: %1", ret);
  66.     return ret;
  67.     }
  68.  
  69.     global map Export() {
  70.     map ret = VM_Common::autoyast_profile_settings;
  71.     if (ret == nil || size(ret) <= 0) {
  72.         ret = SubExport();
  73.     }
  74.     y2milestone("Export() returned: %1", ret);
  75.     return ret;
  76.     }
  77.  
  78.     global boolean Import(map full_input) {
  79.  
  80.     // save the parsed xml profile settings
  81.     VM_Common::autoyast_profile_settings = full_input;
  82.  
  83.     // retrieve the AutoYaST settings for the current proposal_type
  84.     map input = full_input[VM_Common::proposal_type]:$[];
  85.  
  86.     if (input == nil || size(input) <= 0) {
  87.         input = full_input;
  88.     }
  89.  
  90.     y2milestone("Import() settings: %1", input);
  91.  
  92.     // import the VM_Common AutoYaST settings
  93.     VM_Common::Import(input["Common"]:$[]);
  94.  
  95.     disks =            input["disks"]:disks;
  96.     network =        input["network"]:network;
  97.     kernel_path =        input["kernel_path"]:kernel_path;
  98.     initrd_path =        input["initrd_path"]:initrd_path;
  99.     restart =        input["restart"]:restart; //FIXME: config file option 'restart' is depreciated!!!
  100.     boot_device =        input["boot_device"]:boot_device;
  101.     cdrom_image =        input["cdrom_image"]:cdrom_image;
  102.     cdrom_image_type =    input["cdrom_image_type"]:cdrom_image_type;
  103.  
  104.     return true;
  105.     }
  106.  
  107.     global string getConfigFilePath() {
  108.     return conf_path;
  109.     }
  110.  
  111.     global boolean setMemorySize(integer msize)
  112.     {
  113.     VM_Common::SetModified(msize != VM_Common::memory_size);
  114.     VM_Common::memory_size = msize;
  115.     return true;
  116.     }
  117.  
  118.     global integer getMemorySize()
  119.     {
  120.     return VM_Common::memory_size;
  121.     }
  122.  
  123.     global boolean resetMemorySize()
  124.     {
  125.     VM_Common::memory_size = VM_Common::default_memory_size;
  126.  
  127.     boolean isNetWare = false;
  128.     if (VM_Common::GetCustomKernel()) {
  129.         isNetWare = VM_Common::IsNetWareKernel(VM_Common::GetKernelImage());
  130.         }
  131.     if (isNetWare && VM_Common::proposal_type != "install") {
  132.         if (VM_Common::memory_size < 512) {
  133.             VM_Common::memory_size = 512; // if NetWare, increase the memory_size=512
  134.         }
  135.     }
  136.  
  137.     return true;
  138.     }
  139.  
  140.     global boolean setNumberOfCpus(integer msize)
  141.     {
  142.     VM_Common::SetModified(msize != VM_Common::number_of_cpus);
  143.     VM_Common::number_of_cpus = msize;
  144.     return true;
  145.     }
  146.  
  147.     global integer getNumberOfCpus()
  148.     {
  149.     return VM_Common::number_of_cpus;
  150.     }
  151.  
  152.     global boolean resetNumberOfCpus()
  153.     {
  154.     if (VM_Common::GetVirtualizationType() == "full")
  155.         VM_Common::number_of_cpus = 1; // full virtualization requires this value to be set to 1
  156.     else
  157.         VM_Common::number_of_cpus = VM_Common::default_number_of_cpus;
  158.     return true;
  159.     }
  160.  
  161.     global boolean setNE2000(integer msize)
  162.     {
  163.     VM_Common::SetModified(msize != VM_Common::ne2000);
  164.     VM_Common::ne2000 = msize;
  165.     return true;
  166.     }
  167.  
  168.     global integer getNE2000()
  169.     {
  170.     return VM_Common::ne2000;
  171.     }
  172.  
  173.     global boolean resetNE2000()
  174.     {
  175.     VM_Common::ne2000 = VM_Common::default_ne2000;
  176.     return true;
  177.     }
  178.  
  179.     global boolean setStdVga(integer msize)
  180.     {
  181.     VM_Common::SetModified(msize != VM_Common::stdvga);
  182.     VM_Common::stdvga = msize;
  183.     return true;
  184.     }
  185.  
  186.     global integer getStdVga()
  187.     {
  188.     return VM_Common::stdvga;
  189.     }
  190.  
  191.     global boolean resetStdVga()
  192.     {
  193.     VM_Common::stdvga = VM_Common::default_stdvga;
  194.     return true;
  195.     }
  196.  
  197.     global boolean setSdl(integer msize)
  198.     {
  199.     VM_Common::SetModified(msize != VM_Common::sdl);
  200.     VM_Common::sdl = msize;
  201.     return true;
  202.     }
  203.  
  204.     global integer getSdl()
  205.     {
  206.     return VM_Common::sdl;
  207.     }
  208.  
  209.     global boolean resetSdl()
  210.     {
  211.     VM_Common::sdl = VM_Common::default_sdl;
  212.     return true;
  213.     }
  214.  
  215.     global boolean setLocaltime(integer msize)
  216.     {
  217.     VM_Common::SetModified(msize != VM_Common::localtime);
  218.     VM_Common::localtime = msize;
  219.     return true;
  220.     }
  221.  
  222.     global integer getLocaltime()
  223.     {
  224.     return VM_Common::localtime;
  225.     }
  226.  
  227.     global boolean resetLocaltime()
  228.     {
  229.     
  230.     // if NetWare always set localtime=1 in para virtualization otherwise default it 0 (UTC)
  231.     boolean isNetWare = false;
  232.     if (VM_Common::GetCustomKernel()) {
  233.         isNetWare = VM_Common::IsNetWareKernel(VM_Common::GetKernelImage());
  234.         }
  235.     if (isNetWare && VM_Common::proposal_type != "install")
  236.         VM_Common::localtime = 1;
  237.     else
  238.         VM_Common::localtime = VM_Common::default_localtime;
  239.     return true;
  240.     }
  241.  
  242.     global boolean setRestart(string mode) {
  243.     if (contains([ "always", "never", "onreboot" ], mode))
  244.     {
  245.         VM_Common::SetModified(restart != mode);
  246.         restart = mode;
  247.         return true;
  248.     }
  249.  
  250.     return false;
  251.     }
  252.  
  253.     global string getRestart() {
  254.     return restart;
  255.     }
  256.  
  257.     global boolean resetRestart() {
  258.     restart = default_restart;
  259.     return true;
  260.     }
  261.  
  262.     global boolean setStartMode(string mode)
  263.     {
  264.     y2milestone("start_mode: %1", mode);
  265.     VM_Common::SetModified(mode != VM_Common::start_mode);
  266.     VM_Common::start_mode = mode;
  267.     return true;
  268.     }
  269.  
  270.     global string getStartMode()
  271.     {
  272.     return VM_Common::start_mode;
  273.     }
  274.  
  275.     global boolean resetStartMode()
  276.     {
  277.     VM_Common::start_mode = VM_Common::default_start_mode;
  278.     return true;
  279.     }
  280.  
  281.     global boolean setOnPowerOff(string mode)
  282.     {
  283.     y2milestone("on_poweroff: %1", mode);
  284.     VM_Common::SetModified(mode != VM_Common::on_poweroff);
  285.     VM_Common::on_poweroff = mode;
  286.     return true;
  287.     }
  288.  
  289.     global string getOnPowerOff()
  290.     {
  291.     return VM_Common::on_poweroff;
  292.     }
  293.  
  294.     global boolean setOnReboot(string mode)
  295.     {
  296.     y2milestone("on_reboot: %1", mode);
  297.     VM_Common::SetModified(mode != VM_Common::on_reboot);
  298.     VM_Common::on_reboot = mode;
  299.     return true;
  300.     }
  301.  
  302.     global string getOnReboot()
  303.     {
  304.     return VM_Common::on_reboot;
  305.     }
  306.  
  307.     global boolean setOnCrash(string mode)
  308.     {
  309.     y2milestone("on_crash: %1", mode);
  310.     VM_Common::SetModified(mode != VM_Common::on_crash);
  311.     VM_Common::on_crash = mode;
  312.     return true;
  313.     }
  314.  
  315.     global string getOnCrash()
  316.     {
  317.     return VM_Common::on_crash;
  318.     }
  319.  
  320.     global boolean isXendRunning() {
  321.     integer running = Service::Status("xend");
  322.     if (running != 0) {
  323.         // xend is not running
  324.         y2error("Service '%1' is not running.", xend);
  325.         // Popup yes/no dialog
  326.         // %1 - file location of the xend service
  327.         if ( ! Popup::AnyQuestionRichText(_("Warning: Xend is not running"), 
  328.                 sformat(_("<p>A Xen virtual machine requires the xend service (%1) to be running.</p><p>Start the xend service now?</p>"), xend), 
  329.                 45, 5, Label::YesButton(), Label::NoButton(), `focus_yes) ) {
  330.             y2warning("Contining without service '%1'", xend);
  331.             return false;
  332.         }
  333.  
  334.         // restart xend
  335.         y2milestone("Restarting service '%1'", xend);
  336.         boolean success = Service::Restart("xend");
  337.         if ( ! success ) {
  338.             y2error("Failed to restart service '%1'", xend);
  339.             // Popup error message
  340.             // %1 - file location of the xend service
  341.             Report::Error(sformat(_("Failed to restart the xend service (%1)"), xend));
  342.             return false;
  343.         }
  344.     }
  345.     return true;
  346.     }
  347.  
  348.     global string XMInfo(string key) {
  349.     isXendRunning();
  350.  
  351.     // run 'xm info command'
  352.     string cmd = sformat("%1 info | grep ^%2", xm, key);
  353.  
  354.     map out = (map)SCR::Execute(.target.bash_output, cmd);
  355.     y2debug("xm_info - %1 out: %2", key, out);
  356.  
  357.     list<string> output = splitstring(out["stdout"]:"", "\n");
  358.     string info_line = output[0]:"";
  359.  
  360.     string value = regexpsub(info_line, sformat("%1[ \t]*:[ \t]*(.*)",key), "\\1");
  361.     y2milestone("xm_info - %1: %2", key, value);
  362.  
  363.     return value;
  364.     }
  365.  
  366.     global integer FreeMemory() {
  367.  
  368.     string msize = XMInfo("free_memory");
  369.     integer ret = tointeger(msize);
  370.     if (ret == nil)
  371.     {
  372.         ret = 0;
  373.     }
  374.  
  375.     return ret;
  376.     }
  377.  
  378.     global integer MaxFreeMemory() {
  379.  
  380.     string msize = XMInfo("max_free_memory");
  381.     integer ret = tointeger(msize);
  382.  
  383.     if (ret == nil)
  384.     {
  385.         ret = 0;
  386.     }
  387.  
  388.     return ret;
  389.     }
  390.  
  391.     global integer MaxParaMemory() {
  392.  
  393.     string msize = XMInfo("max_para_memory");
  394.     integer ret = tointeger(msize);
  395.     if (ret == nil)
  396.     {
  397.         ret = 0;
  398.     }
  399.  
  400.     return ret;
  401.     }
  402.  
  403.     global integer MaxHVMMemory() {
  404.  
  405.     string msize = XMInfo("max_hvm_memory");
  406.     integer ret = tointeger(msize);
  407.     if (ret == nil)
  408.     {
  409.         ret = 0;
  410.     }
  411.  
  412.     return ret;
  413.     }
  414.  
  415.     global map<string,any> getOptionsProposal()
  416.     {
  417.     list<string> tmp = [];
  418.  
  419.     // Proposal for virtual machine installation
  420.     // %1 = Name of Virtual Machine (i.e. 'vm1')
  421.     tmp = add (tmp, sformat (_("Name of Virtual Machine: %1"), VM_Common::config_name));
  422.  
  423.     if (VM_Common::proposal_type != "install") {
  424.         y2milestone("mode: %1", getStartMode());
  425.  
  426.         // Proposal for virtual machine settings - %1 is a start mode (On boot/Manually)
  427.         tmp = add (tmp, sformat (_("Activation: %1"),
  428.             VM_Common::start_mode_names[getStartMode()]:_("Unknown")));
  429.  
  430.         // Proposal for virtual machine settings
  431.         tmp = add (tmp, sformat (_("On Power Off: %1"),
  432.             VM_Common::lifecycle_event_mapping[VM_Common::on_poweroff]:_("Unknown") ));
  433.  
  434.         // Proposal for virtual machine settings
  435.         tmp = add (tmp, sformat (_("On Reboot: %1"),
  436.             VM_Common::lifecycle_event_mapping[VM_Common::on_reboot]:_("Unknown") ));
  437.  
  438.         // Proposal for virtual machine settings
  439.         tmp = add (tmp, sformat (_("On Crash: %1"),
  440.             VM_Common::lifecycle_event_mapping[VM_Common::on_crash]:_("Unknown") ));
  441.     }
  442.  
  443.     map<string,any> ret = $[ "preformatted_proposal" :
  444.          HTML::List (tmp)
  445.     ];
  446.  
  447.     return ret;
  448.     }
  449.  
  450.     global map<string,any> getHardwareProposal()
  451.     {
  452.     list<string> tmp = [];
  453.  
  454.     // Proposal for virtual machine installation
  455.     // %1 = integer value
  456.     tmp = add (tmp, sformat (_("Memory Size: %1 MB"), getMemorySize()));
  457.  
  458.     if (VM_Common::GetVirtualizationType() == "para")
  459.     {
  460.         // Proposal for virtual machine installation
  461.         // %1 = integer value
  462.         tmp = add (tmp, sformat (_("Number of Virtual CPUs: %1"), VM_Common::number_of_cpus));
  463.     }
  464.  
  465.     y2milestone("mode: %1", getStartMode());
  466.  
  467.     if (VM_Common::GetVirtualizationType() == "full")
  468.     {
  469.         // Proposal for virtual machine installation
  470.         tmp = add (tmp, sformat (_("Virtual Graphics Card: %1"),
  471.                      VM_Common::stdvga_names[getStdVga()]:_("Unknown")));
  472.         // Proposal for virtual machine installation
  473.         tmp = add (tmp, sformat (_("Graphics Viewer: %1"),
  474.                      VM_Common::sdl_names[getSdl()]:_("Unknown")));
  475.     }
  476.  
  477.     // Proposal for virtual machine installation
  478.     tmp = add (tmp, sformat (_("Hardware Clock: %1"),
  479.                  VM_Common::localtime_names[getLocaltime()]:_("Unknown")));
  480.  
  481.  
  482.     map<string,any> ret = $[ "preformatted_proposal" :
  483.          HTML::List (tmp)
  484.     ];
  485.  
  486.     // skip memory check in autoyast configuration mode
  487.     if (!Mode::config())
  488.     {
  489.         // check maximum available free memory
  490.         integer fm = (VM_Common::GetVirtualizationType() == "para") ? MaxParaMemory() : MaxHVMMemory();
  491.  
  492.         if (getMemorySize() > fm)
  493.         {
  494.         // error in the installation proposal - do not allow to continue
  495.         ret = add(ret, "warning", sformat(_("Not enough free memory (%1 MB available)."), fm));
  496.         ret = add(ret, "warning_level", `blocker);
  497.         }
  498.     }
  499.  
  500.     return ret;
  501.     }
  502.  
  503.     global define boolean setDiskConfig(list<map<string,any> > dconf)
  504.     {
  505.     VM_Common::SetModified(disks != dconf);
  506.     disks = dconf;
  507.     return true;
  508.     }
  509.  
  510.     global define list<map<string,any> > getDiskConfig() {
  511.     return disks;
  512.     }
  513.  
  514.     global define boolean resetDiskConfig() {
  515.     if (VM_Common::proposal_type == "install") {
  516.         // source : "hda" = relative image file name (in /var/lib/xen/images/$config_name directory)
  517.         //          "/xen/image/hda" = absolute file name of the image
  518.         // type : "loop-create" - loopback device - create the image,
  519.         //        "loop-use" - loopback device - use existing image,
  520.         //        "phys" - use physical system partition or LVM volume group
  521.         // target - virtual device in the VM
  522.         // ro - read-only flag
  523.         // size - size of the image (when type is "loop-create")
  524.         list <map <string,any> > default_disks = [ $["size" : 4096, "sparse" : true, "target" : "hda", "type" : "loop-create", "prefix" : img_prefix, "source" : "hda", "ro" : false ] ];
  525.         disks = default_disks;
  526.     }
  527.     else {
  528.         disks = [];
  529.     }
  530.     return true;
  531.     }
  532.  
  533.  
  534.     /**
  535.     * Returns a list of virtual devices(target) that are already defined in the disk overview table
  536.     * @param list<map<string,any> > disk configuartion
  537.     * @return list<string> of virtual device names
  538.     */
  539.     global define list<string> getConfiguredDiskTargets(list<map<string,any> > disks_list) {
  540.     list<string> used_devices = [];
  541.     foreach (map<string,any> m, disks_list, ``{
  542.         if (m["target"]:nil != nil && m["target"]:"" != "")
  543.             used_devices = add(used_devices, m["target"]:"");
  544.     });
  545.     return used_devices;
  546.     }
  547.  
  548.     global define string getDiskTarget(list<map<string,any> > disks_list, string source)  {
  549.     y2milestone("getDiskTarget(%1, %2)", disks_list, source);
  550.     string target = nil;
  551.     foreach(map<string,any> m, disks_list, ``{
  552.         string s = m["source"]:"";
  553.         if (m["prefix"]:nil != nil && m["prefix"]:"" != "") {
  554.             string prefix = m["prefix"]:img_prefix;
  555.             if (findlastof(prefix, "/") < size(prefix)-1) { // no ending /
  556.                 prefix = sformat("%1/%2/", m["prefix"]:img_prefix, VM_Common::config_name);
  557.             }
  558.             else {
  559.                 prefix = sformat("%1%2/", m["prefix"]:img_prefix, VM_Common::config_name);
  560.             }
  561.             s = prefix + m["source"]:"";
  562.         }
  563.         if (s == source) {
  564.             target = m["target"]:"";
  565.             break;
  566.         }
  567.     });
  568.     y2milestone("getDiskTarget returned: %1", target);
  569.     return target;
  570.     }
  571.  
  572.     global define string getDiskSource(list<map<string,any> > disks_list, string target)  {
  573.     y2milestone("getDiskSource(%1, %2)", disks_list, target);
  574.     string source = nil;
  575.     foreach(map<string,any> m, disks_list, ``{
  576.         if (m["target"]:"" == target) {
  577.             string s = m["source"]:"";
  578.             if (m["prefix"]:nil != nil && m["prefix"]:"" != "") {
  579.                 string prefix = m["prefix"]:img_prefix;
  580.                 if (findlastof(prefix, "/") < size(prefix)-1) { // no ending /
  581.                     prefix = sformat("%1/%2/", m["prefix"]:img_prefix, VM_Common::config_name);
  582.                 }
  583.                 else {
  584.                     prefix = sformat("%1%2/", m["prefix"]:img_prefix, VM_Common::config_name);
  585.                 }
  586.                 s = prefix + m["source"]:"";
  587.             }
  588.             source = s;
  589.         }
  590.     });
  591.     y2milestone("getDiskSource returned: %1", source);
  592.     return source;
  593.     }
  594.  
  595.     /**
  596.     * Returns a list of disk sources that are already defined in the disk overview table
  597.     * @param list<map<string,any> > disk configuartion
  598.     * @return list<string> of physical disk sources (i.e. file path or device)
  599.     */
  600.     global define list<string> getConfiguredDiskSources(list<map<string,any> > disks_list) {
  601.     list<string> used_devices = [];
  602.     foreach (map<string,any> m, disks_list, ``{
  603.         if (m["source"]:nil != nil && m["source"]:"" != "")
  604.             used_devices = add(used_devices, m["source"]:"");
  605.     });
  606.     return used_devices;
  607.     }
  608.  
  609.  
  610.     /**
  611.     * Returns a list of supported virtual devices depending to the virtualization mode (full or para)
  612.     * @param list<string> used_devices (devices to omit from returned list)
  613.     * @return list<string> of virtual device names
  614.     */
  615.     define list<string> getValidVirtualDevices(list<string> used_devices) {
  616.     // define the set of virtual disk devices
  617.     list<string> valid_virtual_devices = ["hda", "hdb", "hdd"]; // supported devices for full virtualization (hda, hdb, hdd)
  618.     if (VM_Common::GetVirtualizationType() == "para") {
  619.         // add the devices supported in para virtualization (hda-hdt)
  620.         list<string> postfix = ["c", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t"]; // linux seems to only define up to 'hdt'
  621.         postfix = maplist(string postchar, postfix, { return "hd" + postchar; });
  622.         valid_virtual_devices = (list<string>) union(valid_virtual_devices, postfix);
  623.     }
  624.     
  625.     valid_virtual_devices = toset(valid_virtual_devices); //sort list and remove duplicates
  626.     valid_virtual_devices = (list<string>) filter(string dev, valid_virtual_devices, { return (!contains(used_devices, dev)); }); // remove devices that have already been used.
  627.     return valid_virtual_devices;
  628.     }
  629.  
  630.  
  631.     define list <map <string,string> > create_default_network_config()
  632.     {
  633.     return [ $[ "mac" : VM_Common::Propose_MAC_address(""), "bridge": ""] ];
  634.     }
  635.  
  636.  
  637.     global define boolean setNetworkConfig(list<map<string,string> > net)
  638.     {
  639.     VM_Common::SetModified(net != network);
  640.     network = net;
  641.     return true;
  642.     }
  643.  
  644.     global define list<map<string,string> > getNetworkConfig() {
  645.     return network;
  646.     }
  647.  
  648.     global define boolean resetNetworkConfig() {
  649.  
  650.     // create default network config (requires proposed config name)
  651.     default_network = create_default_network_config(); // re-create the mac addresses. See bugzilla (#175955)
  652.  
  653.     network = default_network;
  654.  
  655.     VM_Common::use_dhcp = VM_Common::default_use_dhcp;
  656.     VM_Common::use_static = VM_Common::default_use_static;
  657.  
  658.     return true;
  659.     }
  660.  
  661.     global define list<string> getDiskProposal() {
  662.     list<string> ret = [];
  663.  
  664.     integer i = 1;
  665.     foreach (map<string,any> d, VM_XEN::disks, ``{
  666.  
  667.         string option = "";
  668.  
  669.         if (d["sparse"]:false == true)
  670.         {
  671.         // proposal time
  672.         option = _("Sparse File");
  673.         }
  674.  
  675.         if (d["ro"]:false == true)
  676.         {
  677.         // proposal item
  678.         string ro_option = _("Read-Only");
  679.  
  680.         if (option != "")
  681.         {
  682.             option = sformat("%1, %2", option, ro_option);
  683.         }
  684.         else
  685.         {
  686.             option = ro_option;
  687.         }
  688.         }
  689.  
  690.         if (option != "")
  691.         {
  692.         // %1 are options, e.g. Read-only
  693.         option = sformat(_("(%1)"), option);
  694.         }
  695.  
  696.         string descr = "";
  697.  
  698.         if (d["type"]:"" == "phys")
  699.         {
  700.         // %1 = disk, e.g. /dev/hda4
  701.         descr = sformat(_("Use Disk %1"), d["source"]:"");
  702.         }
  703.         else if (d["type"]:"" == "loop-create")
  704.         {
  705.         // proposal item
  706.         // %1 = integer value representing the proposed disk size in MB
  707.         descr = sformat(_("Create %1 MB Image"), tostring(d["size"]:0));
  708.         }
  709.         else if (d["type"]:"" == "loop-use")
  710.         {
  711.         // proposal item
  712.         // %1 = absolute pathname to a disk image file.
  713.         descr = sformat(_("Use Image %1"), d["source"]:"");
  714.         }
  715.  
  716.         // Disk name for installation proposal
  717.         // %1 is a number, %2 size of disk, %3 is "(sparse image)" if it's set
  718.         ret = add (ret, sformat (_("Disk %1: %2 %3"), d["target"]:"", descr, option));
  719.         i = i + 1;
  720.     });
  721.  
  722.     return ret;
  723.     }
  724.  
  725.     global define map<string,any> getDiskProposalWarning() {
  726.     map<string,any> ret = $[];
  727.     list<string> errors = [];
  728.  
  729.     if (VM_Common::GetVirtualizationType() == "full") {
  730.         boolean hdc_defined = false;
  731.         // check wheter there is defined a non-IDE virtual device
  732.         foreach(map<string,any> d, disks, {
  733.             string target = d["target"]:"";
  734.  
  735.             if (!regexpmatch(target, "^hd[a-d]$")) {
  736.             // warning text in proposal dialog
  737.             // %1 = device name (e.g. hda, sda...)
  738.             errors = add(errors, sformat(_("Disk <tt>%1</tt> cannot be used"), target));
  739.             }
  740.  
  741.             if (target == "hdc") {
  742.             hdc_defined = true;
  743.             }
  744.         }
  745.         );
  746.  
  747.         // device conflict
  748.         if (hdc_defined && boot_device == "d") {
  749.         // warning text in proposal dialog
  750.         errors = add(errors, _("Disk <tt>hdc</tt> cannot be used with CD-ROM emulation"));
  751.         }
  752.     }
  753.  
  754.     // Make sure at least on disk has been defined.
  755.     if (size(disks) <= 0) {
  756.         // warning text in proposal dialog
  757.         errors = add(errors, _("No disk has been selected."));
  758.     }
  759.  
  760.     // Make sure new disk images (loopback-create) don't already exist
  761.     foreach(map<string,any> d, disks, {
  762.         if (d["type"]:"" == "loop-create") {
  763.             string prefix = d["prefix"]:img_prefix;
  764.             if (findlastof(prefix, "/") < size(prefix)-1) { // no ending /
  765.                 prefix = sformat("%1/%2/", d["prefix"]:img_prefix, VM_Common::config_name);
  766.             }
  767.             else {
  768.                 prefix = sformat("%1%2/", d["prefix"]:img_prefix, VM_Common::config_name);
  769.             }
  770.             list<string> existing_disks = (list<string>)SCR::Read(.target.dir, prefix); // list of image dir names
  771. //            if (contains(existing_disks, d["source"]:"hda")) {
  772.             if (false) {
  773.                 // warning text in proposal dialog
  774.                 // %1 = absolute filename of the new disk image
  775.                 errors = add(errors, sformat(_("New disk image <tt>%1</tt> already exists."), sformat("%1%2", prefix, d["source"]:"hda")));
  776.             }
  777.         }
  778.     });
  779.  
  780.     if (size(errors) > 0) {
  781.         ret = add(ret, "warning_level", `blocker);
  782.         ret = add(ret, "warning", mergestring(errors, "<BR>"));
  783.     }
  784.  
  785.     return ret;
  786.     }
  787.  
  788.     global define list<string> getSourceProposal() {
  789.  
  790.     list<string> ret = [];
  791.  
  792.     if (VM_Common::GetVirtualizationType() == "full")
  793.     {
  794.         // proposal item
  795.         ret = add(ret, _("Boot Device: ") + (boot_device == "c" ? _("Hard Disk") : _("CD/DVD")) );
  796.  
  797.         if (boot_device == "d" && cdrom_image != nil && cdrom_image != "")
  798.         {
  799.         // proposal item
  800.         ret = add(ret, _("CD/DVD Image: ") + cdrom_image);
  801.         }
  802.     }
  803.     else
  804.     {
  805.         if (VM_Common::proposal_type == "install") {
  806.         y2milestone("source configuration: %1, %2, %3", VM_Common::inst_type, VM_Common::source_id, VM_Common::custom_source);
  807.         ret = VM_Common::CreateSourceProposal(VM_Common::inst_type, VM_Common::source_id, VM_Common::custom_source);
  808.         if (VM_Common::extra_args != nil && VM_Common::extra_args != "") {
  809.             // proposal item
  810.             ret = add(ret, _("Installation Options: ") + VM_Common::extra_args);
  811.         }
  812.         }
  813.         else
  814.         {
  815.         // proposal item
  816.         ret = add(ret, _("Partition Containing Boot Files: ") + VM_Common::root_device);
  817.         // proposal item
  818.         ret = add(ret, _("Xen-Enabled Kernel: ") + VM_Common::GetKernelImage());
  819.         if (VM_Common::GetInitrdImage() != nil && VM_Common::GetInitrdImage() != "") {
  820.             // proposal item
  821.             ret = add(ret, _("Boot File (initrd): ") + VM_Common::GetInitrdImage());
  822.         }
  823.         if (VM_Common::extra_args != nil && VM_Common::extra_args != "") {
  824.             // proposal item
  825.             ret = add(ret, _("Boot Options: ") + VM_Common::extra_args);
  826.         }
  827.         }
  828.         VM_Common::SetHiddenArgs(VM_Common::GetKernelImage());
  829.     }
  830.  
  831.     y2milestone("proposal: %1", ret);
  832.  
  833.     return ret;
  834.     }
  835.  
  836.     global define map getSourceProposalWarning() {
  837.     if (VM_Common::proposal_type == "install") {
  838.         return VM_Common::CreateSourceProposalWarning(VM_Common::inst_type, VM_Common::source_id, VM_Common::custom_source);
  839.     }
  840.     else if (VM_Common::GetVirtualizationType() == "para") {
  841.         map<string,any> ret = $[];
  842.         if (VM_Common::root_device == nil || VM_Common::root_device == "") {
  843.             // error in the installation proposal - do not allow to continue
  844.             ret = add(ret, "warning", _("Partition Containing Boot Files not specified."));
  845.             ret = add(ret, "warning_level", `blocker);
  846.         }
  847.         else if (VM_Common::GetKernelImage() == nil || VM_Common::GetKernelImage() == "") {
  848.             // error in the installation proposal - do not allow to continue
  849.             ret = add(ret, "warning", _("Xen-Enabled Kernel not specified."));
  850.             ret = add(ret, "warning_level", `blocker);
  851.         }
  852.         return ret;
  853.     }
  854.     }
  855.  
  856.    // reset full virtualization options
  857.     global define boolean ResetFullOptions() {
  858.  
  859.     if (VM_Common::proposal_type == "install") {
  860.  
  861.         boot_device = "d";
  862.  
  863.         //default to the first cdrom device...
  864.         list<map> cd_hwinfo = (list<map>)SCR::Read(.probe.cdrom);
  865.         if (cd_hwinfo != nil) {
  866.             map dev = cd_hwinfo[0]:$[];
  867.             cdrom_image = dev["dev_name"]:"/dev/hdc";
  868.             cdrom_image_type = "phy";
  869.         }
  870.         else {
  871.             cdrom_image = default_cdrom_image;
  872.             cdrom_image_type = default_cdrom_image_type;
  873.         }
  874.  
  875.     }
  876.     else {
  877.         boot_device = "c";
  878.         if (VM_Common::proposal_type != "boot") {// allow the cdrom_image setting to persist when moving from proposal_type 'install' to proposal_type 'boot'. See bugzilla #174616.
  879.             cdrom_image = default_cdrom_image;
  880.             cdrom_image_type = default_cdrom_image_type;
  881.         }
  882.     }
  883.  
  884.     VM_Common::SetKernelImage("/usr/lib/xen/boot/hvmloader");
  885.     VM_Common::SetCustomKernel(true);
  886.     VM_Common::SetInitrdImage("");
  887.  
  888.     return true;
  889.     }
  890.  
  891.     global define boolean SetFullOptions(map<string,string> opts)
  892.     {
  893.     cdrom_image = opts["cdrom_image"]:"";
  894.  
  895.     if (cdrom_image == nil)
  896.     {
  897.         cdrom_image = default_cdrom_image;
  898.     }
  899.  
  900.     cdrom_image_type = opts["cdrom_image_type"]:"phy";
  901.     if (cdrom_image_type == nil || cdrom_image_type == "")
  902.     {
  903.         cdrom_image_type = default_cdrom_image_type;
  904.     }
  905.  
  906.     string bd = opts["boot_device"]:"c";
  907.  
  908.     if (bd == "c" || bd == "d")
  909.     {
  910.         boot_device = bd;
  911.     }
  912.     else
  913.     {
  914.         y2error("Wrong boot device '%1', only \"c\" or \"d\" are valid boot devices", bd);
  915.         return false;
  916.     }
  917.  
  918.     return true;
  919.     }
  920.  
  921.     global define map<string,string> GetFullOptions()
  922.     {
  923.     return $["cdrom_image":cdrom_image, "cdrom_image_type":cdrom_image_type, "boot_device":boot_device];
  924.     }
  925.  
  926.     global define boolean isPAEKernel() {
  927.     // check is we're running on 32 bit pae.
  928.     y2milestone("Checking for PAE kernel...");
  929.     boolean isPAE = false;
  930.     string cmd = "uname -r";
  931.     y2milestone("Executing: %1", cmd);
  932.     map retmap = (map) SCR::Execute(.target.bash_output, cmd);
  933.     retmap["stdout"] = deletechars(retmap["stdout"]:"", "\n\t "); // remove whitespace
  934.     y2milestone("retmap=%1", retmap);
  935.     if (retmap["stdout"]:"" != nil && retmap["stdout"]:"" != "") {
  936.         if (regexpmatch(retmap["stdout"]:"", ".*xenpae$")) // check for kernel-xenpae
  937.             isPAE = true;
  938.         else if (regexpmatch(retmap["stdout"]:"", ".*bigsmp$")) // check for kernel-bigsmp
  939.             isPAE = true;
  940.         else
  941.             isPAE = false;
  942.     }
  943.     y2milestone("isPAE=%1", isPAE);
  944.     return isPAE;
  945.     }
  946.  
  947.  
  948.     define list<string> PartitionsInfo(string image) {
  949.     string cmd = sformat("sfdisk --force -d -uS -- '%1'", image);
  950.     map outputmap = (map)SCR::Execute(.target.bash_output, cmd);
  951.  
  952.     string outputstring = outputmap["stdout"]:"";
  953.  
  954.     list<string> ret = [];
  955.  
  956.     if (outputmap["exit"]:-1 == 0 && outputstring != nil && outputstring != "")
  957.     {
  958.         ret = splitstring(outputstring, "\n");
  959.         // remove empty lines
  960.         ret = filter(string f, ret, {return f != nil && f != "";});
  961.     }
  962.  
  963.     y2milestone("PartitionsInfo (%1): %2", image, ret);
  964.  
  965.     return ret;
  966.     }
  967.  
  968.     define list<map<string,string> > ParsePartitionInfo(list<string> info) {
  969.     list<map<string,string> > ret = [];
  970.     y2milestone("Parse partition: %1", info);
  971.  
  972.     if (info != nil)
  973.     {
  974.         foreach(string line, info, {
  975.             if (regexpmatch(line, " : start=.*, size=.*, Id="))
  976.             {
  977.             // line contains partition description
  978.  
  979.             string expr = "(.*)[ \\t]*:[ \\t]*start=[ \\t]*([1234567890]*)[ \\t]*, size=[ \\t]*([1234567890]*)[ \\t]*, Id=[ \\t]*([1234567890abcdefABCDEF]*)";
  980.  
  981.             string pname = regexpsub(line, expr, "\\1");
  982.             string pstart = regexpsub(line, expr, "\\2");
  983.             string psize = regexpsub(line, expr, "\\3");
  984.             string pid = regexpsub(line, expr, "\\4");
  985.  
  986.             if (pstart != nil && psize != nil && pid != nil)
  987.             {
  988.                 ret = add(ret, $["name" : pname, "start" : pstart, "size" : psize, "id" : pid]);
  989.             }
  990.             }
  991.         }
  992.         );
  993.     }
  994.  
  995.     y2milestone("Parsed output: %1", ret);
  996.  
  997.     return ret;
  998.     }
  999.  
  1000.     define map<string,list<string> > SearchFiles(map<string,list<string> > search_map, string prefix) {
  1001.     map<string,list<string> >result = $[];
  1002.  
  1003.     // check files
  1004.     foreach(string file, list<string> dirs, search_map, {
  1005.         boolean found = false;
  1006.  
  1007.         foreach(string dir, dirs, {
  1008.             if (!found)
  1009.             {
  1010.                 list<string> foundfiles = VM_Common::SearchFile(prefix + "/" + dir, file);
  1011.  
  1012.                 if (size(foundfiles) > 0)
  1013.                 {
  1014.                 // directory prefix
  1015.                 foundfiles = maplist(string f, foundfiles, {return dir + f;});
  1016.                 result[file] = foundfiles;
  1017.                 found = true;
  1018.                 }
  1019.             }
  1020.             }
  1021.         );
  1022.  
  1023.  
  1024.         }
  1025.     );
  1026.  
  1027.     y2milestone("result: %1", result);
  1028.  
  1029.     return result;
  1030.     }
  1031.  
  1032.     define void ProcessFoundFile(map<string,list<string> > found, string dir) {
  1033.     if (found != nil && size(found) > 0)
  1034.     {
  1035.         foreach(string file, list<string> location, found, {
  1036.  
  1037.             if (size(location) > 1)
  1038.             {
  1039.             y2warning("Using the first location from list: %1", location);
  1040.             }
  1041.  
  1042.             string filename = dir + "/" + location[0]:"";
  1043.             string target_dir = img_prefix + VM_Common::config_name;
  1044.  
  1045. /*            if (file == "fstab")
  1046.             {
  1047.             // parse fstab file and set root device name
  1048.             VM_Common::root_device = VM_Common::ParseFstab(filename);
  1049.             }
  1050.             else */if (file == "vmlinuz-*-xen")
  1051.             {
  1052.             // copy kernel
  1053.             VM_Common::CopyFile(filename, target_dir);
  1054.             // set kernel name
  1055.             kernel_path = target_dir + "/" + VM_Common::GetFileNameFromPath(filename);
  1056.             }
  1057.             else if (file == "initrd-*-xen")
  1058.             {
  1059.             // copy initrd image
  1060.             VM_Common::CopyFile(filename, target_dir);
  1061.             // set initrd name
  1062.             initrd_path = target_dir + "/" + VM_Common::GetFileNameFromPath(filename);
  1063.             }
  1064.             else
  1065.             {
  1066.             y2warning("Unknown file: %1", file);
  1067.             }
  1068.         }
  1069.         );
  1070.     }
  1071.     }
  1072.  
  1073.     define boolean ReadDiskImage(string diskimage)
  1074.     {
  1075.     boolean ret = false;
  1076.     y2milestone("ReadDiskImage(%1)", diskimage);
  1077.  
  1078.     list<string> pinfo = PartitionsInfo(diskimage);
  1079.     list<map<string,string> > partitions = ParsePartitionInfo(pinfo);
  1080.  
  1081.     // leave only Linux native partitions or FAT16 (NetWare) partitions
  1082.     partitions = filter(map<string,string> partition, partitions, { return ( (partition["id"]:"" == "83") || (partition["id"]:"" == "6") ); });
  1083.     y2milestone("Partitions: %1", partitions);
  1084.  
  1085.  
  1086.     // create mountpoint directory
  1087.     string tmp = VM_Common::GetTmpDir();
  1088.  
  1089.     string mountpoint = tmp + "/mountpoint";
  1090.  
  1091.     // create mount point directory
  1092.     boolean mcreated = (boolean)SCR::Execute(.target.mkdir, mountpoint);
  1093.     y2milestone("mountpoint created: %1", mcreated);
  1094.  
  1095.     foreach(map<string,string> partition, partitions, {
  1096.  
  1097.         integer offset = tointeger(partition["start"]:"") * 512;
  1098.  
  1099.         if (offset != nil)
  1100.         {
  1101.         boolean mounted = VM_Common::TryMount(diskimage, offset, mountpoint);
  1102.  
  1103.         if (mounted)
  1104.         {
  1105.             // search for the kernel/initrd contained in the proposal.
  1106.  
  1107.             // search for files
  1108.             map<string,list<string> > srch = $[
  1109.             "initrd-xen"        : [ "/boot/", "/" ],
  1110.             "initrd-xenpae"        : [ "/boot/", "/" ],
  1111.             "vmlinuz-xen"        : [ "/boot/", "/" ],
  1112.             "vmlinuz-xenpae"    : [ "/boot/", "/" ],
  1113.             "xnloader.sys"        : [ "/nwserver/" ],
  1114.             ];
  1115.  
  1116.             map<string,list<string> > found = SearchFiles(srch, mountpoint);
  1117.             y2milestone("Search result: %1", found);
  1118.  
  1119.             //ProcessFoundFile(found, mountpoint); // FIXME: is this needed anymore?
  1120.  
  1121.  
  1122.             if (found != nil && size(found) > 0) {
  1123.  
  1124.             // see if we are running on a PAE kernel or if the user seleceted a PAE kernel
  1125.             string kernel_str = deletechars(VM_Common::GetKernelImage(), "\n\t "); // remove whitespace
  1126.             string kernel_ext = "xen";
  1127.             if (isPAEKernel() || regexpmatch(kernel_str, ".*xenpae$")) {
  1128.                 y2milestone("Found PAE kernel");
  1129.                 kernel_ext = "xenpae";
  1130.             }
  1131.  
  1132.             foreach(string file, list<string> locations, found, {
  1133.                 if (regexpmatch(file, "initrd-.*")) {
  1134.                     // set the default initrd
  1135.                     initrd_path = locations[0]:sformat("/boot/initrd-%1", kernel_ext);
  1136.                     VM_Common::SetInitrdImage(initrd_path);
  1137.                 }
  1138.                 else { // assume we found a kernel
  1139.                     // set the default kernel
  1140.                     kernel_path = locations[0]:sformat("/boot/vmlinuz-%1", kernel_ext);
  1141.                     VM_Common::SetKernelImage(kernel_path);
  1142.                     ret = true;
  1143.                 }
  1144.             });
  1145.  
  1146.             y2milestone("kernel='%1'", VM_Common::GetKernelImage());
  1147.             y2milestone("initrd='%1'", VM_Common::GetInitrdImage());
  1148.  
  1149.  
  1150.             string partition_name = String::CutBlanks(partition["name"]:"");
  1151.             y2milestone("partition_name='%1'", partition_name);
  1152.             y2milestone("diskimage='%1'", diskimage);
  1153.             string partition_num = regexpsub(partition_name, ".*([[0123456789]]*$)", "\\1"); // save the partition number
  1154.             y2milestone("partition_num='%1'", partition_num);
  1155.             string new_target = getDiskTarget(disks, diskimage);
  1156.             if (new_target != nil && new_target != "") {
  1157.                 // set the root device to the partition that contains the sepecified kernel (i.e. /dev/hda2)
  1158.                 VM_Common::root_device = new_target + partition_num;
  1159.                 y2milestone("root_device='%1'", VM_Common::root_device);
  1160.             }
  1161.             }
  1162.  
  1163.             // unmount the image
  1164.             SCR::Execute(.target.umount, mountpoint);
  1165.         }
  1166.         }
  1167.  
  1168.     });
  1169.     return ret;
  1170.     }
  1171.  
  1172.  
  1173.     define boolean ReadDiskImages() {
  1174.     boolean ret = false;
  1175.  
  1176.     foreach(map<string,any> disk, disks, {
  1177.         string source = getDiskSource(disks, disk["target"]:"");
  1178.         if (source != nil && source != "") {
  1179.             // if a physical device, make sure string source contains the full pathname to the device.
  1180.             if (disk["type"]:"" == "phys" && regexpmatch(source, "^/dev.*") == false) {
  1181.                 source = "/dev/" + source;
  1182.             }
  1183.             // read the disk image
  1184.             ret = ret || ReadDiskImage(source);
  1185.         }
  1186.         }
  1187.     );
  1188.  
  1189.     // don't default VM_Common::root_device if the disk search doesn't find a kernel
  1190.     if (ret == false) {
  1191.         VM_Common::root_device = "";
  1192.     }
  1193.  
  1194.     // remove the initrd default if we defaulted to the NetWare kernel
  1195.     if (VM_Common::IsNetWareKernel(VM_Common::GetKernelImage())) {
  1196.         initrd_path = "";
  1197.         VM_Common::SetInitrdImage(initrd_path);
  1198.     }
  1199.  
  1200.     return ret;
  1201.     }
  1202.  
  1203.  
  1204.     global define string GetBootDevice()
  1205.     {
  1206.     return boot_device;
  1207.     }
  1208.  
  1209.  
  1210.     list<map<string,any> > parseDiskConfig(string diskstr) {
  1211.     y2milestone("parseDiskConfig(%1)", diskstr);
  1212.  
  1213.     list<map<string,any> > ret = [];
  1214.  
  1215. //    diskstr = String::CutBlanks(diskstr);
  1216. //    diskstr = regexpsub(diskstr, "\[(.*)\]", "\\1"); // remove square brackets '[' ']'
  1217.     diskstr = deletechars(diskstr, "[]"); // remove square brackets '[' ']'
  1218.     diskstr = String::CutBlanks(diskstr);
  1219.     y2milestone("diskstr=%1", diskstr);
  1220.  
  1221.     // parse string to create the list<map<string, any> > of disks
  1222.     list<string> disklist = String::ParseOptions(diskstr, $["separator" : "'"]);
  1223.     y2milestone("disklist=%1", disklist);
  1224.     disklist = filter(string tmpstr, disklist, { return (tmpstr != nil && tmpstr != "" && tmpstr != ","); } );
  1225.     y2milestone("disklist=%1", disklist);
  1226.     
  1227.     foreach(string tmpstr, disklist, {
  1228.         map<string,any> disk_element = $[];
  1229.         list<string> tmplist = splitstring(tmpstr, ",");
  1230.         list<string> source = splitstring(tmplist[0]:"", ":");
  1231.         list<string> target = splitstring(tmplist[1]:"", ":");
  1232.  
  1233.         if (source[0]:"phys" == "file") // type loop-use
  1234.             disk_element["type"] = "loop-use";
  1235.         else // type phys
  1236.             disk_element["type"] = "phys";
  1237.         disk_element["source"] = source[1]:"";
  1238.         if (size(target) > 1) // target[0] is ioemu option
  1239.             disk_element["target"] = target[1]:""; 
  1240.         else
  1241.             disk_element["target"] = target[0]:"";
  1242.         disk_element["ro"] = (tmplist[2]:"r" == "r");
  1243.  
  1244.         ret = add(ret, disk_element);
  1245.     });
  1246.  
  1247.     y2milestone("parseDiskConfig() returned: %1", ret);
  1248.     return ret;
  1249.     }
  1250.  
  1251.  
  1252.     global define boolean updateDiskConfig(string old_source, string new_source, string type) {
  1253.     boolean success = true;
  1254.  
  1255.     // remove the old disk entry (old_source), if it exists in the disks configuration
  1256.     string old_disk = old_source;//regexpsub(old_source, "/dev/(.*)", "\\1"); // remove /dev from the front of the string
  1257.     if (old_disk == nil || old_disk == "") {
  1258.         old_disk = old_source; // fall back to old_source in case the regexp fails
  1259.     }
  1260.     if (old_disk != nil && old_disk != "") {
  1261.         y2milestone("Removing old disk source: %1", old_disk);
  1262.         list<map<string,any> > new_disks = [];
  1263.         foreach(map<string,any> m, getDiskConfig(), ``{
  1264.             if (m["source"]:"" != old_disk)
  1265.                 new_disks = add(new_disks, m);
  1266.         });
  1267.         y2milestone("old disks=%1", getDiskConfig());
  1268.         y2milestone("new disks=%1", new_disks);
  1269.         setDiskConfig(new_disks);
  1270.     }
  1271.  
  1272.     // add the new_source (i.e. cdrom/iso) to the set of virtual disks
  1273.     string source = new_source;//regexpsub(new_source, "/dev/(.*)", "\\1");// remove /dev from the front of the string
  1274.     if (source == nil || source == "") {
  1275.         source = new_source; // fall back to new_source in case the regexp fails
  1276.     }
  1277.     if (source != nil && source != "") {
  1278.         list<string> valid_targets = getValidVirtualDevices(getConfiguredDiskTargets(getDiskConfig()));
  1279.         y2milestone("vaild_targets=%1", valid_targets);
  1280.         if (valid_targets != nil && size(valid_targets) > 0) {
  1281.             string target = valid_targets[0]:"hdc";
  1282.             y2milestone("disks=%1", getDiskConfig());
  1283.             map<string,any> new_disk = nil;
  1284.             new_disk = $[ "source" : source, "target" : target, "ro" : true, "type" : type ];
  1285.             if (new_disk == nil) {
  1286.                 y2error("new_disk is empty");
  1287.                 success = false;
  1288.             }
  1289.             y2milestone("adding: %1", new_disk);
  1290.             setDiskConfig(add(disks, new_disk));
  1291.         }
  1292.         else {
  1293.             // popup error message
  1294.             Report::Error(_("Cannot add a new virtual disk target."));
  1295.             y2error("WARNING: Cannot set the virtual target for the CD / DVD device.  All valid virtual targets are used!!!");
  1296.             success = false;
  1297.         }
  1298.     }
  1299.     return success;
  1300.     }
  1301.  
  1302.     string formatDiskConfig(list<map<string,any> > conf, boolean ioemu) {
  1303.     string ret = "";
  1304.  
  1305.     string ioemu_option = (ioemu) ? "ioemu:" : "";
  1306.  
  1307.     foreach(map<string,any> d, conf, {
  1308.         if (size(ret) > 0)
  1309.         {
  1310.             ret = ret + ", ";
  1311.         }
  1312.  
  1313.         string rw_mode = (d["ro"]:true) ? "r" : "w";
  1314.  
  1315.         if (d["type"]:"" == "phys")
  1316.         {
  1317.             ret = ret + sformat("'phy:%1,%2%3,%4'", d["source"]:"", ioemu_option, d["target"]:"", rw_mode);
  1318.         }
  1319.         else if (d["type"]:"" == "loop-create")
  1320.         {
  1321.             string source = d["prefix"]:img_prefix;
  1322.             if (findlastof(source, "/") < size(source)-1) { // no ending /
  1323.             source = sformat("%1/%2/%3", d["prefix"]:img_prefix, VM_Common::config_name, d["source"]:"");
  1324.             }
  1325.             else {
  1326.             source = sformat("%1%2/%3", d["prefix"]:img_prefix, VM_Common::config_name, d["source"]:"");
  1327.             }
  1328.             ret = ret + sformat("'file:%1,%2%3,%4'", source, ioemu_option, d["target"]:"", rw_mode);
  1329.         }
  1330.         else if (d["type"]:"" == "loop-use")
  1331.         {
  1332.             ret = ret + sformat("'file:%1,%2%3,%4'", d["source"]:"", ioemu_option, d["target"]:"", rw_mode);
  1333.         }
  1334.         }
  1335.     );
  1336.  
  1337.     if (ioemu) { // fully virtualized guest
  1338.         if ( VM_Common::proposal_type != "existing" ) {
  1339.         if (size(ret) > 0)
  1340.         {
  1341.             ret = ret + ", ";
  1342.         }
  1343.         // Replace the 'cdrom=' line in config files for hvm guests with a disk line entry for the cdrom
  1344.         ret = ret + sformat("'%1:%2,hdc:cdrom,r'", cdrom_image_type, cdrom_image);
  1345.         }
  1346.     }
  1347.  
  1348.     ret = "[ " + ret + " ]";
  1349.  
  1350.     y2milestone("Disk configuration: %1", ret);
  1351.  
  1352.     return ret;
  1353.     }
  1354.  
  1355.     global define boolean resetSourceConfig() {
  1356.     if (VM_Common::GetVirtualizationType() == "full") {
  1357.         return ResetFullOptions();
  1358.     }
  1359.     else { // para
  1360.         if (VM_Common::proposal_type == "install") {
  1361.             // look for a valid network inst source
  1362.             VM_Common::inst_type = `network_configured;
  1363.             VM_Common::source_id = VM_Common::ProposeSelection();
  1364.             if (VM_Common::source_id == nil || VM_Common::source_id < 0) { // if no valid network inst source is found
  1365.                 VM_Common::inst_type = `cdrom;
  1366.                 // set the custom_source to the first probed cd device.
  1367.                 string old_custom_source = nil;
  1368.                 list<map> cd_hwinfo = (list<map>)SCR::Read(.probe.cdrom);
  1369.                 if (cd_hwinfo != nil) {
  1370.                     old_custom_source = VM_Common::custom_source; // remove the old source from the disk config
  1371.                     map first_dev = cd_hwinfo[0]:$[];
  1372.                     VM_Common::custom_source = first_dev["dev_name"]:"";
  1373.                 }
  1374.                 updateDiskConfig(old_custom_source, VM_Common::custom_source, "phys"); // add the cddev to the disk config
  1375.             }
  1376.             // reset custom kernel and initrd image setting
  1377.             VM_Common::SetKernelImage("");
  1378.             VM_Common::SetInitrdImage("");
  1379.             VM_Common::SetCustomKernel(false);
  1380.         }
  1381.         else {
  1382.             if (VM_Common::IsNetWareKernel(VM_Common::GetKernelImage())) {
  1383.                 y2milestone("Found NetWare kernel");
  1384.                 VM_Common::SetKernelImage("/nwserver/xnloader.sys");
  1385.                 VM_Common::SetInitrdImage("");
  1386.             }
  1387.             else {
  1388.                 y2milestone("Assuming Linux kernel");
  1389.                 // see if we are running on a PAE kernel or if the user seleceted a PAE kernel
  1390.                 string kernel_str = deletechars(VM_Common::GetKernelImage(), "\n\t "); // remove whitespace
  1391.                 string kernel_ext = "xen";
  1392.                 if (isPAEKernel() || regexpmatch(kernel_str, ".*xenpae$")) {
  1393.                     y2milestone("Found PAE kernel");
  1394.                     kernel_ext = "xenpae";
  1395.                 }
  1396.                 VM_Common::SetKernelImage("/boot/vmlinuz-" + kernel_ext);
  1397.                 VM_Common::SetInitrdImage("/boot/initrd-" + kernel_ext);
  1398.             }
  1399.  
  1400.             // Search each disk for the existance of the Xen kernel (Linux or NetWare)
  1401.             // If one is found then set VM_Common::root_device to that disk partition.
  1402.             if (!Mode::config()) {
  1403.                 ReadDiskImages();
  1404.             }
  1405.  
  1406.             y2milestone("KernelImage: %1", VM_Common::GetKernelImage());
  1407.             y2milestone("InitrdImage: %1", VM_Common::GetInitrdImage());
  1408.             VM_Common::SetCustomKernel(true);
  1409.         }
  1410.     }
  1411.     return true;
  1412.     }
  1413.  
  1414.     global define map<string,any> getSourceConfig() {
  1415.     return $[ "source_id" : VM_Common::source_id, "inst_type" : VM_Common::inst_type, "custom_source" : VM_Common::custom_source ];
  1416.     }
  1417.  
  1418.     global define list<string> getNetworkProposal() {
  1419.     list<string> proposal = [
  1420.         // Proposal item - %1 is number of virtual network card the virtual machine
  1421.         sformat (_("Number of Virtual Network Cards: %1"), size(network)),
  1422.     ];
  1423.  
  1424.     if (VM_Common::GetVirtualizationType() == "para" && VM_Common::proposal_type == "install") {
  1425.         if ( VM_Common::use_dhcp && !VM_Common::use_static ) {
  1426.             // proposal item - %1 = translated string 'DHCP'
  1427.             proposal = add(proposal, sformat(_("Network Installation Settings: %1"), _("DHCP")));
  1428.         }
  1429.         else if ( !VM_Common::use_dhcp && VM_Common::use_static ) {
  1430.             // proposal item - %1 = translated string 'Static IP'
  1431.             proposal = add(proposal, sformat(_("Network Installation Settings: %1"), _("Static IP")));
  1432.             // proposal item - %1 = IP address
  1433.             proposal = add(proposal, sformat(_("IP: %1"), VM_Common::ip));
  1434.             // proposal item - %1 = netmask
  1435.             proposal = add(proposal, sformat(_("Netmask: %1"), VM_Common::netmask));
  1436.             // proposal item - %1 = gateway
  1437.             proposal = add(proposal, sformat(_("Gateway: %1"), VM_Common::gateway));
  1438.         }
  1439. //        else {
  1440. //            // proposal item - %1 = translated string 'None'
  1441. //            proposal = add(proposal, sformat(_("Network Installation Settings: %1"), _("None")));
  1442. //        }
  1443.     }
  1444.     else if (VM_Common::GetVirtualizationType() == "full") {
  1445.         // proposal item - %1 = translated string 'NE2000' or 'AMD PCnet'
  1446.         proposal = add (proposal, sformat (_("Virtual Network Card: %1"),
  1447.              VM_Common::ne2000_names[getNE2000()]:_("Unknown")));
  1448.     }
  1449.     
  1450.     return proposal;
  1451.     }
  1452.  
  1453.     global define map getNetworkProposalWarning() {
  1454.     map<string,any> ret = $[];
  1455.  
  1456.     if (VM_Common::random_MAC == false && (VM_Common::MAC_address == nil || VM_Common::MAC_address == ""))
  1457.     {
  1458.         // error in the installation proposal - do not allow to continue
  1459.         ret = add(ret, "warning", _("Network configuration is not valid."));
  1460.         ret = add(ret, "warning_level", `blocker);
  1461.     }
  1462.     else if (VM_Common::GetVirtualizationType() != "full" && VM_Common::proposal_type == "install"
  1463.         && !VM_Common::use_dhcp && VM_Common::use_static) {
  1464.             if (VM_Common::ip == nil || VM_Common::ip == "") {
  1465.                 // error in the installation proposal - do not allow to continue
  1466.                 ret = add(ret, "warning", _("IP not specified."));
  1467.                 ret = add(ret, "warning_level", `blocker);
  1468.             }
  1469.             else if (VM_Common::netmask == nil || VM_Common::netmask == "") {
  1470.                 // error in the installation proposal - do not allow to continue
  1471.                 ret = add(ret, "warning", _("Netmask not specified."));
  1472.                 ret = add(ret, "warning_level", `blocker);
  1473.             }
  1474.             else if (VM_Common::gateway == nil || VM_Common::gateway == "") {
  1475.                 // error in the installation proposal - do not allow to continue
  1476.                 ret = add(ret, "warning", _("Gateway not specified."));
  1477.                 ret = add(ret, "warning_level", `blocker);
  1478.             }
  1479.     }
  1480.  
  1481.     return ret;
  1482.     }
  1483.  
  1484.  
  1485.     global define boolean setSourceConfig(integer sid, symbol type, string custom) {
  1486.  
  1487.     VM_Common::SetModified(sid != VM_Common::source_id || type != VM_Common::inst_type || custom != VM_Common::custom_source);
  1488.  
  1489.     VM_Common::source_id = sid;
  1490.     VM_Common::inst_type = type;
  1491.     VM_Common::custom_source = custom;
  1492.  
  1493.     return true;
  1494.     }
  1495.  
  1496.     global string getConfigName() {
  1497.     return VM_Common::config_name;
  1498.     }
  1499.  
  1500.     global boolean setConfigName(string cname) {
  1501.     // remove invalid characters
  1502.     cname = filterchars(cname, String::CAlnum() + "_-.:+");
  1503.  
  1504.     VM_Common::SetModified(cname != VM_Common::config_name);
  1505.     VM_Common::config_name = cname;
  1506.     return true;
  1507.     }
  1508.  
  1509.     boolean WriteOption(path configpath, string optname, string optvalue) {
  1510.     return (boolean)SCR::Write(configpath + topath(optname), optvalue);
  1511.     }
  1512.  
  1513.     boolean WriteStringOption(path configpath, string optname, string optvalue) {
  1514.     y2debug("old optvalue: %1", optvalue);
  1515.     // escape all \ chars found in the string.
  1516.     list<string> optvalueList = splitstring(optvalue, "\\");
  1517.     optvalue = mergestring(optvalueList, "\\\\");
  1518.     // escape all ' chars found in the string.
  1519.     optvalueList = splitstring(optvalue, "'");
  1520.     optvalue = mergestring(optvalueList, "\\'");
  1521.     y2debug("new optvalue: %1", optvalue);
  1522.     return WriteOption(configpath, optname, "\'" + optvalue + "\'");
  1523.     }
  1524.  
  1525.  
  1526.     string ReadOption(path configpath, string optname) {
  1527.     
  1528.     string optvalue = (string)SCR::Read(configpath + topath(optname));
  1529.  
  1530.     if (regexpmatch(optvalue, "'.*'")) {
  1531.         // remove the single quotes
  1532.         string tmpoptvalue = regexpsub(optvalue, "'(.*)'", "\\1");
  1533.         if (optvalue != nil || optvalue != "")
  1534.             optvalue = tmpoptvalue;
  1535.     }
  1536.     else if (regexpmatch(optvalue, "\".*\"")) {
  1537.                 // remove the double quotes
  1538.                 string tmpoptvalue = regexpsub(optvalue, "\"(.*)\"", "\\1");
  1539.                 if (optvalue != nil || optvalue != "")
  1540.                         optvalue = tmpoptvalue;
  1541.         }
  1542.  
  1543.     return optvalue;
  1544.     }
  1545.  
  1546.  
  1547.     global map ReadConfigFileSettings(string cfg_file) {
  1548.  
  1549.     y2milestone("ReadConfigFileSettings(%1)", cfg_file);
  1550.     if (cfg_file == nil || cfg_file == "") {
  1551.         y2error("cfg_file paramater empty!");
  1552.         return nil;
  1553.     }
  1554.  
  1555.     // FIXME: must remove from code below any duplicate ReadSettings() for a specified key!
  1556.     map new_settings = $[];
  1557.     path configpath = .etc.xen.value + topath(getConfigFilePath() + cfg_file);
  1558.     y2debug("configpath=%1", configpath);
  1559.     new_settings["name"] = ReadOption(configpath, "name");
  1560.     if (new_settings["name"]:"" == nil || new_settings["name"]:"" == "") {
  1561.         y2error("cfg_file value 'name' is empty!");
  1562.         return nil; // ignore cfg files that do not contain a machine name.
  1563.     }
  1564.     new_settings["builder"] = ReadOption(configpath, "builder");
  1565.     new_settings["memory"] = ReadOption(configpath, "memory");
  1566.     new_settings["kernel"] = ReadOption(configpath, "kernel");
  1567.     new_settings["bootentry"] = ReadOption(configpath, "bootentry");
  1568.     if (new_settings["kernel"]:"" == nil || new_settings["kernel"]:"" == "") {
  1569.         list<string> tmplist = splitstring(new_settings["bootentry"]:"", ":,");
  1570.         new_settings["kernel"] = tmplist[1]:"";
  1571.     }
  1572.     new_settings["disks"] = parseDiskConfig(ReadOption(configpath, "disk"));
  1573.     new_settings["on_poweroff"] = ReadOption(configpath, "on_poweroff");
  1574.     new_settings["on_reboot"] = ReadOption(configpath, "on_reboot");
  1575.     new_settings["on_crash"] = ReadOption(configpath, "on_crash");
  1576.     new_settings["vcpus"] = ReadOption(configpath, "vcpus");
  1577.     // new_settings["vif"] = parseVifConfig(ReadOption(configpath, "vif")); // FIXME: must write a method for parsing the vif list<string>
  1578.     new_settings["stdvga"] = ReadOption(configpath, "stdvga");
  1579.     new_settings["sdl"] = ReadOption(configpath, "sdl");
  1580.     new_settings["vnc"] = ReadOption(configpath, "vnc");
  1581.     new_settings["vncviewer"] = ReadOption(configpath, "vncviewer");
  1582.     new_settings["ne2000"] = ReadOption(configpath, "ne2000");
  1583.     new_settings["dhcp"] = ReadOption(configpath, "dhcp");
  1584.     new_settings["ip"] = ReadOption(configpath, "ip");
  1585.     new_settings["netmask"] = ReadOption(configpath, "netmask");
  1586.     new_settings["interface"] = ReadOption(configpath, "interface");
  1587.     new_settings["gateway"] = ReadOption(configpath, "gateway");
  1588.     new_settings["extra"] = ReadOption(configpath, "extra");
  1589.     new_settings["bootloader"] = ReadOption(configpath, "bootloader");
  1590.     new_settings["cdrom"] = ReadOption(configpath, "cdrom");
  1591.     new_settings["boot"] = ReadOption(configpath, "boot");
  1592.     new_settings["localtime"] = ReadOption(configpath, "localtime");
  1593.  
  1594.     new_settings["cfg_file"] = cfg_file;
  1595.     
  1596.     y2milestone("ReadConfigFileSettings returned: %1", new_settings);
  1597.     return new_settings;
  1598.     }
  1599.  
  1600.  
  1601.     global list<map> ReadAllConfigFileSettings() {
  1602.  
  1603.     y2milestone("ReadAllConfigFileSettings()");
  1604.     
  1605.     list<map> new_settings_list = [];
  1606.  
  1607.     list<string> file_list = (list<string>) SCR::Read(.target.dir, getConfigFilePath());
  1608.     y2milestone("file_list=%1", file_list);
  1609.     if (file_list != nil && size(file_list) > 0) {
  1610.         foreach(string cfg_file, file_list, {
  1611.             string first_char = substring(cfg_file, 0, 1);
  1612.             string last_char = substring(cfg_file, size(cfg_file)-1, size(cfg_file));
  1613.             if (first_char == "." || last_char == "~") {
  1614.                 // ignore all files that start with '.' or end with '~'
  1615.                 continue;
  1616.             }
  1617.             else {
  1618.                 map new_settings = ReadConfigFileSettings(cfg_file);
  1619.                 if (new_settings != nil && size(new_settings) > 0) {
  1620.                     new_settings_list = add(new_settings_list, new_settings);
  1621.                 }
  1622.             }
  1623.         });
  1624.     }
  1625.     y2milestone("ReadAllConfigFileSettings returned: %1", new_settings_list);
  1626.     return new_settings_list;
  1627.     }
  1628.  
  1629.     global define boolean ValidateConfigName(string name) {
  1630.  
  1631.     // check for a conflicting config file name (/etc/xen/vm/*)
  1632.     list<string> configs = (list<string>)SCR::Read(.target.dir, conf_path); // list of config file names
  1633.     if (contains(configs, name)) {
  1634.         // a config file name conflicts
  1635.         return false;
  1636.     }
  1637.  
  1638.     // check for a conflicting vm name settings inside each config file (/etc/xen/vm/*)
  1639.     list<map> config_settings = ReadAllConfigFileSettings(); // list<map> of settings inside of the config files
  1640.     boolean conflict = false;
  1641.     foreach (map tmpmap, config_settings, {
  1642.         if (tmpmap != nil) {
  1643.             if (tmpmap["name"]:"" == name) {
  1644.                 conflict = true;
  1645.                 break;
  1646.             }
  1647.         }
  1648.     });
  1649.     // a vm name inside a config file conflicts
  1650.     if (conflict) {
  1651.         return false;
  1652.     }
  1653.  
  1654.     // check for conflicting image directory name (/var/lib/xen/images/*)
  1655.     list<string> images = (list<string>)SCR::Read(.target.dir, img_prefix); // list of image dir names
  1656.     if (contains(images, name)) {
  1657.         // try to remove the vm image directory (if it is not empty, it should not be deleted).
  1658.         string img_dir = img_prefix + name;
  1659.         string cmd = sformat("rmdir %1", img_dir);
  1660.         y2milestone("Executing: %1", cmd);
  1661.         map retmap = (map)SCR::Execute(.target.bash_output, cmd);
  1662.         y2milestone("retmap=%1", retmap);
  1663.         images = (list<string>)SCR::Read(.target.dir, img_prefix); // re-create list of image dir names
  1664.  
  1665.         if (contains(images, name)) {
  1666.             // vm image directory is not empty.
  1667.             // An image directory name conflicts
  1668.             return false;
  1669.         }
  1670.     }
  1671.  
  1672.     // no conflicts (a valid config name)
  1673.     return true;
  1674.     }
  1675.  
  1676.  
  1677.     global define string ProposeConfigName()
  1678.     {
  1679.     integer domain = 1;
  1680.  
  1681.     while ( ValidateConfigName(conf_prefix + tostring(domain)) == false )
  1682.     {
  1683.         domain = domain + 1;
  1684.     }
  1685.  
  1686.     string conf_name = conf_prefix + tostring(domain);
  1687.     y2milestone("Proposed name: %1", conf_name);
  1688.     //SCR::Execute (.target.bash, sformat("/usr/bin/touch %1%2", conf_path, conf_name));
  1689.  
  1690.     return conf_name;
  1691.     }
  1692.  
  1693.     global define boolean resetConfigName()
  1694.     {
  1695.     VM_Common::config_name = ProposeConfigName();
  1696.     return true;
  1697.     }
  1698.  
  1699.     string GetVIF(list<map<string,string> > conf)
  1700.     {
  1701.     string ret = "";
  1702.  
  1703.     if (conf == nil || size(conf) == 0)
  1704.     {
  1705.         return nil;
  1706.     }
  1707.  
  1708.     boolean first = true;
  1709.     boolean all_default = true;
  1710.  
  1711.     string type = (VM_Common::GetVirtualizationType() == "full") ? "type=ioemu" : "";
  1712.     foreach(map<string,string> c, conf, {
  1713.         string iface = type;
  1714.  
  1715.         string mac = c["mac"]:"";
  1716.         string bridge = c["bridge"]:"";
  1717.  
  1718.         if (mac != "")
  1719.         {
  1720.             if (iface != "")
  1721.             {
  1722.             iface = iface + ",";
  1723.             }
  1724.  
  1725.             iface = iface + "mac=" + mac;
  1726.         }
  1727.  
  1728.         if (bridge != "")
  1729.         {
  1730.             if (iface != "")
  1731.             {
  1732.             iface = iface + ",";
  1733.             }
  1734.  
  1735.             iface = iface + "bridge=" + bridge;
  1736.         }
  1737.  
  1738.         iface = "'" + iface + "'";
  1739.  
  1740.         if (first)
  1741.         {
  1742.             first = false;
  1743.         }
  1744.         else
  1745.         {
  1746.             ret = ret + ", ";
  1747.         }
  1748.  
  1749.         ret = ret + iface;
  1750.         }
  1751.     );
  1752.  
  1753.     ret = "[ " + ret + " ]";
  1754.  
  1755.     return ret;
  1756.     }
  1757.  
  1758.  
  1759.     global define boolean Write() {
  1760.     y2milestone("Writing the config to file %1", conf_path + VM_Common::config_name);
  1761.  
  1762.     //check whether the config file already exists, if so remove it.
  1763.     string configfilename = sformat("%1%2", conf_path, VM_Common::config_name);
  1764.     if (SCR::Read(.target.size, configfilename) >= 0) {
  1765.         y2milestone("Removing old config file: %1", configfilename);
  1766.         SCR::Execute(.target.remove, configfilename);
  1767.     }
  1768.  
  1769.     SCR::UnmountAgent(.etc.xen);
  1770.     path configpath = .etc.xen.value + topath(conf_path + VM_Common::config_name);
  1771.  
  1772.     boolean ret = WriteOption(configpath, "disk", formatDiskConfig(disks, VM_Common::GetVirtualizationType() == "full"));
  1773.     ret = ret && WriteOption(configpath, "memory", tostring(VM_Common::memory_size));
  1774.     ret = ret && WriteOption(configpath, "vcpus", tostring(VM_Common::number_of_cpus));
  1775.  
  1776.     if (VM_Common::GetVirtualizationType() == "full")
  1777.     {
  1778.         // use hvm builder for full virtualized hosts
  1779.         ret = ret && WriteStringOption(configpath, "builder", "hvm");
  1780.  
  1781.         // set pae=1, if dom0 is 64bit, domU is full virtualization, and domU mem >= 3.5 GB (#180361)
  1782.         if (Arch::x86_64() && VM_Common::memory_size >= 3584) { // (3.5 GB * 1024) = 3584 MB
  1783.         ret = ret && WriteOption(configpath, "pae", "1");
  1784.         }
  1785.  
  1786.         // set device model
  1787.         ret = ret && WriteStringOption(configpath, "device_model", "/usr/lib/xen/bin/qemu-dm");
  1788.         ret = ret && WriteStringOption(configpath, "kernel", "/usr/lib/xen/boot/hvmloader");
  1789.     }
  1790.     else {
  1791.         ret = ret && WriteStringOption(configpath, "builder", "linux");
  1792.         if (VM_Common::proposal_type == "install") {
  1793.         ret = ret && WriteStringOption(configpath, "kernel", kernel_path);
  1794.         ret = ret && WriteStringOption(configpath, "ramdisk", initrd_path);
  1795.         }
  1796.         else {
  1797.         ret = ret && WriteOption(configpath, "kernel", nil);
  1798.         ret = ret && WriteOption(configpath, "ramdisk", nil);
  1799.  
  1800.         }
  1801.     }
  1802.  
  1803.     ret = ret && WriteStringOption(configpath, "name", VM_Common::config_name);
  1804.  
  1805.     if (VM_Common::GetVirtualizationType() == "para" && VM_Common::proposal_type == "install") {
  1806.         if ( VM_Common::use_dhcp && !VM_Common::use_static ) {
  1807.             ret = ret && WriteStringOption(configpath, "dhcp", "dhcp");
  1808.             ret = ret && WriteStringOption(configpath, "interface", "eth0");
  1809.         }
  1810.         else if ( !VM_Common::use_dhcp && VM_Common::use_static ) {
  1811.             ret = ret && WriteStringOption(configpath, "ip", VM_Common::ip);
  1812.             ret = ret && WriteStringOption(configpath, "netmask", VM_Common::netmask);
  1813.             ret = ret && WriteStringOption(configpath, "gateway", VM_Common::gateway);
  1814.             ret = ret && WriteStringOption(configpath, "interface", "eth0");
  1815.         }
  1816.     }
  1817.     else if (VM_Common::GetVirtualizationType() == "para" && VM_Common::proposal_type == "boot") {
  1818.         // remove all the install network config file options
  1819.         ret = ret && WriteOption(configpath, "dhcp", nil);
  1820.         ret = ret && WriteOption(configpath, "interface", nil);
  1821.         ret = ret && WriteOption(configpath, "ip", nil);
  1822.         ret = ret && WriteOption(configpath, "netmask", nil);
  1823.         ret = ret && WriteOption(configpath, "gateway", nil);
  1824.     }
  1825.  
  1826.     string vif = GetVIF(network);
  1827.  
  1828.     if (vif != nil)
  1829.     {
  1830.         ret = ret && WriteOption(configpath, "vif", vif);
  1831.     }
  1832.  
  1833.     if (VM_Common::GetVirtualizationType() == "full") {
  1834.         ret = ret && WriteOption(configpath, "stdvga", tostring(VM_Common::stdvga));
  1835.         ret = ret && WriteOption(configpath, "sdl", tostring(VM_Common::sdl));
  1836.         ret = ret && WriteOption(configpath, "vnc", tostring((VM_Common::sdl == 1) ? 0 : 1));
  1837.         ret = ret && WriteOption(configpath, "vncviewer", tostring((VM_Common::sdl == 1) ? 0 : 1));
  1838.         ret = ret && WriteOption(configpath, "ne2000", tostring(VM_Common::ne2000));
  1839.     }
  1840.     else {
  1841.         if (VM_Common::GetCustomKernel() == false) { // kernel extracted from SUSE install source
  1842.         string kernel_ver = regexpsub(kernel_path, ".*vmlinuz-(.*)-xen", "\\1");
  1843.         y2milestone("Kernel version is: %1", kernel_ver);
  1844.         list<string> kernel_ver_list = splitstring(kernel_ver, ".-");
  1845.         if (tointeger(kernel_ver_list[0]:"0") >= 2 && tointeger(kernel_ver_list[1]:"0") >= 6 && tointeger(kernel_ver_list[2]:"0") >= 18) { // if kernel version is >= 2.6.18, add "sdl=1" to the vm config file
  1846.             ret = ret && WriteOption(configpath, "sdl", "1");
  1847.         }
  1848.         }
  1849.     }
  1850.  
  1851.     ret = ret && WriteOption(configpath, "localtime", tostring(VM_Common::localtime));
  1852.  
  1853. //    ret = ret && WriteStringOption(configpath, "restart", "never");  //FIXME: config file option 'restart' is depreciated!!!
  1854.     ret = ret && WriteStringOption(configpath, "on_poweroff", "destroy");
  1855.     ret = ret && WriteStringOption(configpath, "on_reboot", "destroy");
  1856.     ret = ret && WriteStringOption(configpath, "on_crash", "destroy");
  1857.  
  1858.     if (VM_Common::GetVirtualizationType() == "full")
  1859.     {
  1860.         // write boot device option
  1861.         ret = ret && WriteStringOption(configpath, "boot", boot_device);
  1862.     }
  1863.  
  1864.     if (VM_Common::GetVirtualizationType() != "full")
  1865.     {
  1866.         string url = "";
  1867.  
  1868.         // set installation source
  1869.  
  1870.         if (VM_Common::inst_type == `network_configured)
  1871.         {
  1872.         map general_data = Pkg::SourceGeneralData (VM_Common::source_id);
  1873.         url = general_data["url"]:"";
  1874.         }
  1875.         else if (VM_Common::inst_type == `network_custom) {
  1876.         url = VM_Common::custom_source;
  1877.         }
  1878.         else if (VM_Common::inst_type == `cdrom || VM_Common::inst_type == `iso)
  1879.         {
  1880.         // find the virtaul disk device that matches this source
  1881.         string virt_source = VM_Common::custom_source;
  1882.         string virt_target = "";
  1883.  
  1884.         foreach(map<string,any> m, disks, ``{
  1885.             if (m["source"]:"" == virt_source)
  1886.                 virt_target = m["target"]:"";
  1887.         });
  1888.  
  1889.         if (virt_target != nil && virt_target != "") {
  1890.             url = sformat("hd:/dev/%1", virt_target);
  1891.         }
  1892.         else { // fall back the orig. source (not configured as a disk)
  1893.             url = VM_Common::custom_source;
  1894.         }
  1895.         }
  1896.         else if (VM_Common::inst_type == `slp)
  1897.         {
  1898.         url = "slp://";
  1899.         }
  1900.         // Strip off any query string before writing the "install=" setting (#169829)
  1901.         string old_url = url;
  1902.         url = regexpsub(url, "^(.*)\\?.*", "\\1");
  1903.         if (url == nil || url == "") {
  1904.         url = old_url; // fall back to the old url incase the regexpsub fails.
  1905.         }
  1906.  
  1907.         VM_Common::SetHiddenArgs(kernel_path);
  1908.         string extra_arg = "";
  1909.         extra_arg = VM_Common::hidden_args + " " + VM_Common::extra_args;
  1910.  
  1911.         boolean isNetWare = false;
  1912.         if (VM_Common::GetCustomKernel()) {
  1913.             isNetWare = VM_Common::IsNetWareKernel(VM_Common::GetKernelImage());
  1914.             }
  1915.  
  1916.         // installation of paravirtualzed Linux using static IP
  1917.         // write extra network config for linuxrc
  1918.         if (VM_Common::GetVirtualizationType() == "para" && VM_Common::proposal_type == "install"
  1919.         && !VM_Common::use_dhcp && VM_Common::use_static && !isNetWare)
  1920.         {
  1921.         // write network options
  1922.         if (extra_arg != "")
  1923.         {
  1924.             extra_arg = extra_arg + " ";
  1925.         }
  1926.  
  1927.         extra_arg = extra_arg + sformat("hostip=%1 netmask=%2 gateway=%3 netdevice=%4",
  1928.             VM_Common::ip, VM_Common::netmask, VM_Common::gateway, "eth0");
  1929.         }
  1930.  
  1931.         // add installation boot options
  1932.         if (extra_arg != "" && url != "")
  1933.         {
  1934.         // replace $URL_INSTALL variable
  1935.         string new_arg = regexpsub(extra_arg, "^(.*)\\$URL_INSTALL(.*)", sformat("\\1%1\\2", url));
  1936.  
  1937.         if (new_arg != nil && new_arg != "") {
  1938.             extra_arg = new_arg;
  1939.         }
  1940.         }
  1941.  
  1942.         // set autoyast option
  1943.         string extra_autoyast = "";
  1944.         if (VM_Common::autoyast_profile != nil && VM_Common::autoyast_profile != "")
  1945.         {
  1946.         // get the filename
  1947.         list<string> names = splitstring(VM_Common::autoyast_profile, "/");
  1948.         string name = names[size(names) - 1]:"";
  1949.         // add autoyast extra option
  1950.         extra_autoyast = " autoyast=device://hdt63/" + name;
  1951.         }
  1952.  
  1953.         ret = ret && WriteStringOption(configpath, "extra", extra_arg + extra_autoyast);
  1954.     }
  1955.  
  1956.     // flush the changes
  1957.     ret = ret && SCR::Write(.etc.xen, nil);
  1958.  
  1959.     if (VM_Common::start_mode == "onboot")
  1960.     {
  1961.         // create 'auto' link if the VM should be started at boot time
  1962.         string cmd = "cd /etc/xen/auto && /bin/ln -s ../vm/" + VM_Common::config_name;
  1963.         integer link_result = (integer)SCR::Execute(.target.bash, cmd);
  1964.  
  1965.         if (link_result != 0)
  1966.         {
  1967.         y2warning("Cannot set automatic start link (exit code: %1)", link_result);
  1968.         }
  1969.     }
  1970.     else {
  1971.             // remove 'auto' link if the VM should be started at manually
  1972.             string cmd = "rm -f /etc/xen/auto/" + VM_Common::config_name;
  1973.             integer link_result = (integer)SCR::Execute(.target.bash, cmd);
  1974.  
  1975.             if (link_result != 0)
  1976.             {
  1977.                 y2warning("Cannot remove the automatic start link (exit code: %1)", link_result);
  1978.             }
  1979.     }
  1980.  
  1981.     return ret;
  1982.     }
  1983.  
  1984.  
  1985.     global define string getExtraArgs() {
  1986.     return VM_Common::extra_args;
  1987.     }
  1988.  
  1989.     global define boolean setExtraArgs(string args) {
  1990.     VM_Common::SetModified(args != VM_Common::extra_args);
  1991.     VM_Common::extra_args = args;
  1992.     return true;
  1993.     }
  1994.  
  1995.     global define boolean resetExtraArgs() {
  1996.     string arg = (VM_Common::proposal_type == "install") ? "TERM=xterm textmode=1 vnc=0" : "TERM=xterm";
  1997.     VM_Common::extra_args = arg;
  1998.     return true;
  1999.     }
  2000.  
  2001.     global define void resetHiddenArgs() {
  2002.         VM_Common::hidden_args = "";
  2003.     }
  2004.  
  2005.  
  2006.     /*global define boolean UpdateRoot(string root)
  2007.     {
  2008.     SCR::UnmountAgent(.etc.xen);
  2009.  
  2010.     path configpath = .etc.xen.value + topath(conf_path + VM_Common::config_name);
  2011.     boolean ret = WriteStringOption(configpath, "root", root);
  2012.  
  2013.     // flush the changes
  2014.     SCR::Write(.etc.xen, nil);
  2015.  
  2016.     return ret;
  2017.     }
  2018. */
  2019.     define boolean CreateDiskImages() {
  2020.     boolean ret = true;
  2021.     foreach(map<string,any> disk, disks, {
  2022.         if (disk["type"]:"" == "loop-create" && ret)
  2023.         {
  2024.             integer imgsize = disk["size"]:4096;
  2025.             boolean sparse = disk["sparse"]:true;
  2026.             string target_dir = disk["prefix"]:img_prefix;
  2027.             if (findlastof(target_dir, "/") < size(target_dir)-1) { // no ending /
  2028.             target_dir = sformat("%1/%2/", disk["prefix"]:img_prefix, VM_Common::config_name);
  2029.             }
  2030.             else {
  2031.             target_dir = sformat("%1%2/", disk["prefix"]:img_prefix, VM_Common::config_name);
  2032.             }
  2033.  
  2034.             string cmd = "/bin/mkdir -p " + target_dir;
  2035.             map out = (map)SCR::Execute(.target.bash_output, cmd);
  2036.             y2debug("mkdir output: %1", out);
  2037.  
  2038.             ret = ret && VM_Common::CreateDiskImage(target_dir + disk["source"]:"hda", imgsize, sparse);
  2039.         }
  2040.         if (ret == false) break;
  2041.         }
  2042.     );
  2043.  
  2044.     return ret;
  2045.     }
  2046.  
  2047.     define integer dom0Mem()
  2048.     {
  2049.     isXendRunning();
  2050.  
  2051.     // get dom0 memory size
  2052.     string cmd = sformat("%1 list --long 0 | /usr/bin/grep -E \"[[:space:]]\(memory[[:space:]]\"", xm);
  2053.     map out = (map)SCR::Execute(.target.bash_output, cmd);
  2054.     y2debug("xm list output: %1", out);
  2055.  
  2056.     list<string> output = splitstring(out["stdout"]:"", "\n");
  2057.     string mem_line = output[0]:"";
  2058.     string msize = regexpsub(mem_line, "\\(memory (.*)\\)", "\\1");
  2059.  
  2060.     if (msize == nil)
  2061.     {
  2062.         return 0;
  2063.     }
  2064.  
  2065.     integer ret = tointeger(msize);
  2066.  
  2067.     if (ret == nil)
  2068.     {
  2069.         ret = 0;
  2070.     }
  2071.  
  2072.     y2milestone("dom0_memory size: %1", ret);
  2073.     return ret;
  2074.     }
  2075.  
  2076.  
  2077.     global define boolean Prepare2() {
  2078.     boolean ret = true;
  2079.  
  2080.     kernel_path = VM_Common::GetKernelImage();
  2081.     initrd_path = VM_Common::GetInitrdImage();
  2082.  
  2083.     SCR::UnmountAgent(.etc.xen);
  2084.     path configpath = .etc.xen.value + topath(conf_path + VM_Common::config_name);
  2085.  
  2086.     // remove the disk with autoyast profile
  2087.     if (VM_Common::GetVirtualizationType() != "full" && VM_Common::autoyast_profile != nil && VM_Common::autoyast_profile != "")
  2088.     {
  2089.         // remove the last disk (image with autoyast profile)
  2090.         disks = remove(disks, size(disks) - 1);
  2091.  
  2092.         string command = "/bin/rm " + img_prefix + VM_Common::config_name + "/autoyast.img";
  2093.         integer out = (integer)SCR::Execute(.target.bash, command);
  2094.         if (out != 0)
  2095.         {
  2096.         y2warning("Cannot remove autoyast image, command: %1 failed", command);
  2097.         }
  2098.     }
  2099.  
  2100.     if (VM_Common::IsNetWareKernel(kernel_path) && VM_Common::proposal_type == "boot") {
  2101.         // remove the NetWare installation source
  2102.         updateDiskConfig(VM_Common::custom_source, "", "");
  2103.     }
  2104.  
  2105.     ret = ret && WriteOption(configpath, "disk", formatDiskConfig(disks, VM_Common::GetVirtualizationType() == "full"));
  2106.  
  2107.     if (VM_Common::proposal_type != "boot") { // do not recreate the disks (i.e. dd) when proposal_type is boot (bugzilla #192135
  2108.         // create disk image file(s)
  2109.         y2milestone("Creating disk images...");
  2110.         ret = ret && CreateDiskImages();
  2111.     }
  2112.  
  2113.     // all following action are needed only in paravirtualization mode
  2114.     if (VM_Common::GetVirtualizationType() == "full")
  2115.     {
  2116.         // update boot configuration if the VM booted from a CD
  2117.         if (boot_device == "d")
  2118.         {
  2119.         // set boot from hard disk
  2120.         ret = ret && WriteStringOption(configpath, "boot", "c");
  2121.  
  2122.         // flush the changes
  2123.         ret = ret && SCR::Write(.etc.xen, nil);
  2124.         }
  2125.     }
  2126.     else { // para virtualized
  2127.  
  2128.         ret = ret && WriteStringOption(configpath, "bootloader", "/usr/lib/xen/boot/domUloader.py");
  2129.  
  2130.         if (VM_Common::root_device == nil || VM_Common::root_device == "") {
  2131.             ReadDiskImages();
  2132.         }
  2133.  
  2134.         // upadate config - root device, set default runlevel, remove install= option
  2135. //        ret = ret && SCR::Write(configpath + "restart", nil);
  2136.  
  2137.         VM_Common::SetHiddenArgs(kernel_path);
  2138.         string extra = VM_Common::hidden_args + " " + VM_Common::extra_args;
  2139.         ret = ret && WriteStringOption(configpath, "extra", extra);
  2140.     
  2141.         string bootentry = sformat("%1:%2", VM_Common::root_device, kernel_path);
  2142.         if (initrd_path != "") {
  2143.             bootentry = bootentry + "," + initrd_path;
  2144.         }
  2145.         ret = ret && WriteStringOption(configpath, "bootentry", bootentry);
  2146.     }
  2147.  
  2148.     ret = ret && WriteOption(configpath, "memory", tostring(VM_Common::memory_size));
  2149.     ret = ret && WriteOption(configpath, "vcpus", tostring(VM_Common::number_of_cpus));
  2150.  
  2151.     ret = ret && WriteStringOption(configpath, "on_poweroff", VM_Common::on_poweroff);
  2152.     ret = ret && WriteStringOption(configpath, "on_reboot", VM_Common::on_reboot);
  2153.     ret = ret && WriteStringOption(configpath, "on_crash", VM_Common::on_crash);
  2154.  
  2155.     // flush the changes
  2156.     ret = ret && SCR::Write(.etc.xen, nil);
  2157.  
  2158.     return ret;
  2159.     }
  2160.  
  2161.     global define boolean Prepare() {
  2162.     // build/extract xen kernel and installation initrd, copy them to a temp directory.
  2163.     integer new_src = -1;
  2164.     map<integer,boolean> src_status = $[];
  2165.  
  2166.     // extract kernel and initrd image
  2167.     if (VM_Common::GetCustomKernel() == false)
  2168.     {
  2169.         // remember inst source config
  2170.         src_status = VM_Common::InstSourceStatus();
  2171.         y2milestone("src_status: %1", src_status);
  2172.  
  2173.         integer enabled_src = VM_Common::source_id;
  2174.  
  2175.         // check whether the custom installation source is already defined
  2176.         if (VM_Common::inst_type == `network_custom || VM_Common::inst_type == `cdrom || VM_Common::inst_type == `iso)
  2177.         {
  2178.         string url = VM_Common::custom_source;
  2179.         if (VM_Common::inst_type == `cdrom) {
  2180.             url = sformat("cd:///?devices=%1", VM_Common::custom_source);
  2181.         }
  2182.         else if (VM_Common::inst_type == `iso) {
  2183.             url = sformat("iso:///?iso=%1", VM_Common::custom_source);
  2184.         }
  2185.  
  2186.         integer src_defined = -1; // always call Pkg::SourceCreate
  2187.  
  2188.         if (src_defined < 0)
  2189.         {
  2190.             // Add a new installation source
  2191.             new_src = Pkg::SourceCreate(url, "");
  2192.  
  2193.             // FIXME: this 'if' statement and the containing code must be removed when the correct URL for `cdrom inst_types is fixed.
  2194.             if ((new_src == nil || new_src < 0) && VM_Common::inst_type == `cdrom) {
  2195.             url = sformat("dvd:///?devices=%1", VM_Common::custom_source); // try dvd:/// if cd:/// fails...
  2196.             new_src = Pkg::SourceCreate(url, "");
  2197.             }
  2198.  
  2199.             y2milestone("Adding new installation source: %1 = %2", url, new_src);
  2200.             enabled_src = new_src;
  2201.             VM_Common::source_id = new_src;
  2202.             y2milestone("src_status: %1", VM_Common::InstSourceStatus());
  2203.         }
  2204.         }
  2205.  
  2206.         // disable all sources
  2207.         VM_Common::DisableAllSources();
  2208.  
  2209.         if (enabled_src == nil || enabled_src < 0)
  2210.         {
  2211.         y2error("Configured source ID (VM_Common::source_id) is nil!");
  2212.         // popup error message
  2213.         Report::Error(_("Failed to extract the kernel
  2214. from the installation source.
  2215.  
  2216. Please check that your installation
  2217. source is accessible."));
  2218.         return false;
  2219.         }
  2220.         y2milestone("src_status: %1", VM_Common::InstSourceStatus());
  2221.  
  2222.         // enable the only one (selected) source
  2223.         Pkg::SourceSetEnabled(enabled_src, true);
  2224.         y2milestone("enabled src %1: %2", enabled_src, VM_Common::InstSourceStatus());
  2225.  
  2226.         // restart sources - use the only one enabled source
  2227. //        list sources = Pkg::SourceStartCache(true);
  2228. //        y2milestone("Source init: %1", sources);
  2229.  
  2230.         // check whether required packages are provided by the installation source
  2231.         string kernel_ext = "xen";
  2232.         if (isPAEKernel())
  2233.         kernel_ext = "xenpae";
  2234.  
  2235.         if (!Pkg::IsAvailable("kernel-" + kernel_ext))
  2236.         {
  2237.         y2error("%1%2 package is not available", "kernel-", kernel_ext);
  2238.         // popup error message
  2239.         Report::Error(_("Failed to extract the kernel
  2240. from the installation source.
  2241.  
  2242. Please check that your installation
  2243. source is accessible."));
  2244.         return false;
  2245.         }
  2246.  
  2247.         if (!Pkg::IsAvailable("install-initrd"))
  2248.         {
  2249.         y2error("install-initrd package is not available");
  2250.         // popup error message
  2251.         Report::Error(_("Failed to create the installation RAM disk."));
  2252.         return false;
  2253.         }
  2254.  
  2255.  
  2256.         y2milestone("Extracting %1%2 from the installation source...", "kernel-", kernel_ext);
  2257.  
  2258.         string kpkg = VM_Common::GetPackage("kernel-" + kernel_ext);
  2259.         string tmpdir = VM_Common::GetTmpDir();
  2260.  
  2261.  
  2262.         kernel_path = VM_Common::ExtractKernelImage(kpkg, tmpdir, "./boot/vmlinuz-*-" + kernel_ext, "vmlinuz-*-" + kernel_ext);
  2263.  
  2264.         if (kernel_path != "")
  2265.         {
  2266.         kernel_path = tmpdir + "/" + kernel_path;
  2267.         }
  2268.         else
  2269.         {
  2270.         // popup error message
  2271.         Report::Error(_("Failed to extract the kernel
  2272. from the installation source.
  2273.  
  2274. Please check that your installation
  2275. source is accessible."));
  2276.         return false;
  2277.         }
  2278.  
  2279.  
  2280.         y2milestone("Creating installation ramdisk (initrd)...");
  2281.         if (VM_Common::CreateInstallationImage(kpkg, tmpdir + "/inst-initrd") == false)
  2282.         {
  2283.         // popup error message
  2284.         Report::Error(_("Failed to create the installation RAM disk."));
  2285.         return false;
  2286.         }
  2287.         initrd_path = tmpdir + "/inst-initrd";
  2288.  
  2289.         y2milestone("kernel: %1, initrd: %2", kernel_path, initrd_path);
  2290.  
  2291.         VM_Common::GetPackage("kernel-" + kernel_ext); // ask for the kernel pkg again.  This ensures CD1 is in the drive when the VM starts. See bugzilla #175111
  2292.  
  2293.     }
  2294.     else
  2295.     {
  2296.         kernel_path = VM_Common::GetKernelImage();
  2297.         initrd_path = VM_Common::GetInitrdImage();
  2298.     }
  2299.  
  2300.     string target_dir = img_prefix + VM_Common::config_name;
  2301.     string cmd = "/bin/mkdir -p " + target_dir;
  2302.     map out = (map)SCR::Execute(.target.bash_output, cmd);
  2303.     y2debug("mkdir output: %1", out);
  2304.  
  2305.     // create disk image file(s)
  2306.     y2milestone("Creating disk images...");
  2307.     if (CreateDiskImages() == false) {
  2308.         return false;
  2309.     }
  2310.  
  2311.     if (new_src >= 0)
  2312.     {
  2313.         Pkg::SourceDelete(new_src);
  2314.     }
  2315.  
  2316.     // set source statuses back
  2317.     VM_Common::SetSourceState(src_status);
  2318.  
  2319.     // create disk image file with autoyast profile
  2320.     if (VM_Common::autoyast_profile != nil && VM_Common::autoyast_profile != "" && VM_Common::GetVirtualizationType() != "full")
  2321.     {
  2322.         string autoyast_image = target_dir + "/autoyast.img";
  2323.         if (! VM_Common::CreateImageWithProfile(autoyast_image, VM_Common::autoyast_profile)) {
  2324.         return false;
  2325.         }
  2326.  
  2327.         // remove any old image
  2328.         string old_autoyast_image = getDiskSource(disks, "hdt63");
  2329.         if (old_autoyast_image != nil && old_autoyast_image != "") {
  2330.         updateDiskConfig(old_autoyast_image, "", "");
  2331.         }
  2332.  
  2333.         // add the disk image to the list
  2334.         disks = add(disks, $[ "target" : "hdt63", "type" : "loop-use", "source" : autoyast_image, "ro" : true ] );
  2335.     }
  2336.  
  2337.     integer freemem = FreeMemory();
  2338.  
  2339.     // check available free memory size
  2340.     if (VM_Common::memory_size > freemem)
  2341.     {
  2342.         integer maxmem = MaxFreeMemory();
  2343.  
  2344.         if (VM_Common::memory_size > maxmem)
  2345.         {
  2346.         y2error("Required memory size %1, max. available %2", VM_Common::memory_size, maxmem);
  2347.         return false;
  2348.         }
  2349. /*
  2350.         // get current memory size
  2351.         integer dom0 = dom0Mem();
  2352.         // compute the new size
  2353.         integer new_mem = dom0 - (VM_Common::memory_size - freemem);
  2354.         y2milestone("Resizing dom0 memory size from %1 to %2...", dom0, new_mem);
  2355.  
  2356.         // resize dom0 memory
  2357.         string command = sformat("%1 mem-set 0 %2", xm, new_mem);
  2358.         integer out = (integer)SCR::Execute(.target.bash, command);
  2359.         if (out != 0)
  2360.         {
  2361.         y2error("Cannot resize dom0 memory, command '%1' failed", command);
  2362.         return false;
  2363.         }
  2364. */
  2365.  
  2366.     }
  2367.  
  2368.     return true;
  2369.     }
  2370.  
  2371.     global define symbol GetVirtualMachineState(string state) {
  2372.     symbol ret = `unknown;
  2373.  
  2374.     if (state != nil && state != "") {
  2375.         if (issubstring(tolower(state), "c") || issubstring(tolower(state), "d"))
  2376.             ret = `crashed;
  2377.         else
  2378.             ret = `running;
  2379.     }
  2380.     else 
  2381.         ret = `stopped;
  2382.  
  2383.     return ret;
  2384.     }
  2385.  
  2386.  
  2387.     global define boolean ViewVirtualMachineConsole(string DomName, boolean isFullVirtualization, boolean isNetWare, boolean background, boolean displayError) {
  2388.     isXendRunning();
  2389.     y2milestone("ViewVirtualMachineConsole(%1, %2, %3, %4, %5)", DomName, isFullVirtualization, isNetWare, background, displayError);
  2390.     if (DomName != nil && DomName != "") {
  2391.         string cmd = sformat("/usr/bin/xterm -geometry 80x%3 -T \"Xen - %2\" -e %1 console %2",
  2392.                     xm, DomName, isNetWare ? 25 : 24);
  2393.         if ( isFullVirtualization ) { // start VNC viewer
  2394.             cmd = sformat("vncviewer localhost:%1", DomName);
  2395.         }
  2396.  
  2397.         y2milestone("Executing: %1", cmd);
  2398.  
  2399.         if (background) {
  2400.             integer ret = (integer) SCR::Execute(.target.bash_background, cmd);
  2401.             if (displayError && ret != 0) {
  2402.                 // popup error message
  2403.                 Report::Error(_("Cannot open the virtual machine console."));
  2404.             }
  2405.             return (ret == 0);
  2406.         }
  2407.         else {
  2408.             map ret = (map)SCR::Execute(.target.bash_output, cmd);
  2409.             if (displayError && ret["exit"]:-1 != 0) {
  2410.                 // popup error message with 'Details...' button
  2411.                 VM_Common::PopupErrorDetails(_("Cannot open the virtual machine console."), ret, cmd);
  2412.             }
  2413.             return (ret["exit"]:-1 == 0);
  2414.         }
  2415.     }
  2416.     return false;
  2417.     }
  2418.  
  2419.     global define boolean ShutdownVirtualMachine(string DomName, boolean displayError) {
  2420.     isXendRunning();
  2421.     if (DomName != nil && DomName != "") {
  2422.         string cmd = sformat("%1 shutdown '%2' -w", xm, DomName);
  2423.         y2milestone("Executing: %1", cmd);
  2424.         map ret = (map)SCR::Execute(.target.bash_output, cmd);
  2425.         if (ret["exit"]:-1 != 0 && displayError) {
  2426.             // popup error message with 'Details...' button
  2427.             VM_Common::PopupErrorDetails(_("Cannot shutdown the virtual machine."), ret, cmd);
  2428.         }
  2429.         return (ret["exit"]:-1 == 0);
  2430.     }
  2431.     return false;
  2432.     }
  2433.  
  2434.     global define boolean TerminateVirtualMachine(string DomName, boolean displayError) {
  2435.     isXendRunning();
  2436.     if (DomName != nil && DomName != "") {
  2437.         string cmd = sformat("%1 destroy '%2'", xm, DomName);
  2438.         y2milestone("Executing: %1", cmd);
  2439.         map ret = (map)SCR::Execute(.target.bash_output, cmd);
  2440.         if (ret["exit"]:-1 != 0 && displayError) {
  2441.             // popup error message with 'Details...' button
  2442.             VM_Common::PopupErrorDetails(_("Cannot terminate the virtual machine."), ret, cmd);
  2443.         }
  2444.         return (ret["exit"]:-1 == 0);
  2445.     }
  2446.     return false;
  2447.     }
  2448.  
  2449.     global define boolean StartVirtualMachine(string DomName, boolean displayError) {
  2450.     isXendRunning();
  2451.     y2milestone("StartVirtualMachine(%1, %2)", DomName, displayError);
  2452.     if (DomName != nil && DomName != "") {
  2453.         string cmd = sformat("%1 create %2%3", xm, conf_path, DomName);
  2454.         y2milestone("xm create command: %1", cmd);
  2455.     
  2456.         boolean success = false;
  2457.         map ret = (map)SCR::Execute(.target.bash_output, cmd);
  2458.         if (ret["exit"]:-1 != 0 && displayError) {
  2459.             // popup error message
  2460.             string abortmsg = _("Cannot start the virtual machine.");
  2461. //            if (VM_Common::proposal_type == "install") {
  2462. //                // popup error message
  2463. //                abortmsg = abortmsg + "\n" + _("The installation will be aborted.");
  2464. //            }
  2465.             VM_Common::PopupErrorDetails(abortmsg, ret, cmd);
  2466.         }
  2467.         success = (ret["exit"]:-1 == 0);
  2468.  
  2469.         if (! success) {
  2470.             // It is possible for "xm create" to claim failure, yet leave a zombie VM.
  2471.             TerminateVirtualMachine(DomName, false);
  2472.         }
  2473.  
  2474.         return success;
  2475.     }
  2476.     return false;
  2477.     }
  2478.  
  2479.  
  2480.     global define boolean InstallPackages() {
  2481.     return VM_Common::InstallPackages(["xterm", "xorg-x11", "xen-tools"]);
  2482.     }
  2483.  
  2484.     global boolean GetModified() {
  2485.     return VM_Common::GetModified();
  2486.     }
  2487.  
  2488.     global void SetModified(boolean modif) {
  2489.     VM_Common::SetModified(modif);
  2490.     }
  2491.  
  2492.     global define string GetImgPrefix()
  2493.     {
  2494.     return img_prefix;
  2495.     }
  2496.  
  2497.     global define boolean SetImgPrefix(string prefix)
  2498.     {
  2499.     if (prefix != nil && prefix != "")
  2500.     {
  2501.         if (substring(prefix, 0, 1) != "/")
  2502.         {
  2503.         prefix = "/" + prefix;
  2504.         }
  2505.  
  2506.         if (substring(prefix, size(prefix) - 1, 1) != "/")
  2507.         {
  2508.         prefix = prefix + "/";
  2509.         }
  2510.  
  2511.         y2milestone("Setting image prefix to: %1", prefix);
  2512.         img_prefix = prefix;
  2513.         return true;
  2514.     }
  2515.  
  2516.     return false;
  2517.     }
  2518.  
  2519.     global define map GetFunctions()
  2520.     {
  2521.     return $[
  2522.         "getConfigFilePath" : VM_XEN::getConfigFilePath,
  2523.  
  2524.         "setMemorySize" : VM_XEN::setMemorySize,
  2525.         "getMemorySize" : VM_XEN::getMemorySize,
  2526.         "resetMemorySize" : VM_XEN::resetMemorySize,
  2527.  
  2528.         "isXendRunning" : VM_XEN::isXendRunning,
  2529.         "getXMInfo" : VM_XEN::XMInfo,
  2530.  
  2531.         "getMaxFreeMemory" : VM_XEN::MaxFreeMemory,
  2532.         "getMaxParaMemory" : VM_XEN::MaxParaMemory,
  2533.         "getMaxHVMMemory" : VM_XEN::MaxHVMMemory,
  2534.  
  2535.         "setNumberOfCpus" : VM_XEN::setNumberOfCpus,
  2536.         "getNumberOfCpus" : VM_XEN::getNumberOfCpus,
  2537.         "resetNumberOfCpus" : VM_XEN::resetNumberOfCpus,
  2538.  
  2539.         "setNE2000" : VM_XEN::setNE2000,
  2540.         "getNE2000" : VM_XEN::getNE2000,
  2541.         "resetNE2000" : VM_XEN::resetNE2000,
  2542.  
  2543.         "setStdVga" : VM_XEN::setStdVga,
  2544.         "getStdVga" : VM_XEN::getStdVga,
  2545.         "resetStdVga" : VM_XEN::resetStdVga,
  2546.  
  2547.         "setSdl" : VM_XEN::setSdl,
  2548.         "getSdl" : VM_XEN::getSdl,
  2549.         "resetSdl" : VM_XEN::resetSdl,
  2550.  
  2551.         "setLocaltime" : VM_XEN::setLocaltime,
  2552.         "getLocaltime" : VM_XEN::getLocaltime,
  2553.         "resetLocaltime" : VM_XEN::resetLocaltime,
  2554.  
  2555.         "setStartMode" : VM_XEN::setStartMode,
  2556.         "getStartMode" : VM_XEN::getStartMode,
  2557.         "resetStartMode" : VM_XEN::resetStartMode,
  2558.  
  2559.         "setOnPowerOff" : VM_XEN::setOnPowerOff,
  2560.         "getOnPowerOff" : VM_XEN::getOnPowerOff,
  2561.  
  2562.         "setOnReboot" : VM_XEN::setOnReboot,
  2563.         "getOnReboot" : VM_XEN::getOnReboot,
  2564.  
  2565.         "setOnCrash" : VM_XEN::setOnCrash,
  2566.         "getOnCrash" : VM_XEN::getOnCrash,
  2567.  
  2568.         "setRestart" : VM_XEN::setRestart,
  2569.         "getRestart" : VM_XEN::getRestart,
  2570.         "resetRestart" : VM_XEN::resetRestart,
  2571.  
  2572.         "setConfigName" : VM_XEN::setConfigName,
  2573.         "getConfigName" : VM_XEN::getConfigName,
  2574.         "resetConfigName" : VM_XEN::resetConfigName,
  2575.         "ValidateConfigName" : VM_XEN::ValidateConfigName,
  2576.  
  2577.         "getOptionsProposal" : VM_XEN::getOptionsProposal,
  2578.  
  2579.         "getHardwareProposal" : VM_XEN::getHardwareProposal,
  2580.  
  2581.         "setDiskConfig" : VM_XEN::setDiskConfig,
  2582.         "getDiskConfig" : VM_XEN::getDiskConfig,
  2583.         "resetDiskConfig" : VM_XEN::resetDiskConfig,
  2584.         "getDiskProposal" : VM_XEN::getDiskProposal,
  2585.         "getDiskProposalWarning" : VM_XEN::getDiskProposalWarning,
  2586.  
  2587.         "getDiskSource" : VM_XEN::getDiskSource,
  2588.         "getDiskTarget" : VM_XEN::getDiskTarget,
  2589.         "getConfiguredDiskTargets" : VM_XEN::getConfiguredDiskTargets,
  2590.         "getConfiguredDiskSources" : VM_XEN::getConfiguredDiskSources,
  2591.         "getValidVirtualDevices" : VM_XEN::getValidVirtualDevices,
  2592.  
  2593.         "getSourceConfig" : VM_XEN::getSourceConfig,
  2594.         "setSourceConfig" : VM_XEN::setSourceConfig,
  2595.         "getSourceProposal" : VM_XEN::getSourceProposal,
  2596.         "getSourceProposalWarning" : VM_XEN::getSourceProposalWarning,
  2597.         "resetSourceConfig" : VM_XEN::resetSourceConfig,
  2598.  
  2599.         "getExtraArgs"    : VM_XEN::getExtraArgs,
  2600.         "setExtraArgs"    : VM_XEN::setExtraArgs,
  2601.         "resetExtraArgs"    : VM_XEN::resetExtraArgs,
  2602.         "resetHiddenArgs"    : VM_XEN::resetHiddenArgs,
  2603. //        "updateRoot"    : VM_XEN::UpdateRoot,
  2604.  
  2605.         "getKernelImage"    : VM_Common::GetKernelImage,
  2606.         "setKernelImage"    : VM_Common::SetKernelImage,
  2607.  
  2608.         "getInitrdImage"    : VM_Common::GetInitrdImage,
  2609.         "setInitrdImage"    : VM_Common::SetInitrdImage,
  2610.  
  2611.         "getCustomKernel"    : VM_Common::GetCustomKernel,
  2612.         "setCustomKernel"    : VM_Common::SetCustomKernel,
  2613.  
  2614.         "getVirtualizationType" : VM_Common::GetVirtualizationType,
  2615.         "setVirtualizationType" : VM_Common::SetVirtualizationType,
  2616.         "resetVirtualizationType" : VM_Common::ResetVirtualizationType,
  2617.         "virtualizationTypeProposal" : VM_Common::GetVirtualizationProposal,
  2618.  
  2619.         "setNetworkConfig" : VM_XEN::setNetworkConfig,
  2620.         "getNetworkConfig" : VM_XEN::getNetworkConfig,
  2621.         "resetNetworkConfig" : VM_XEN::resetNetworkConfig,
  2622.         "getNetworkProposal" : VM_XEN::getNetworkProposal,
  2623.         "getNetworkProposalWarning" : VM_XEN::getNetworkProposalWarning,
  2624.  
  2625.         "getBootDevice"    : VM_XEN::GetBootDevice,
  2626.  
  2627.         "getImgPrefix"    : VM_XEN::GetImgPrefix,
  2628.         "setImgPrefix"    : VM_XEN::SetImgPrefix,
  2629.  
  2630.         "import"    : VM_XEN::Import,
  2631.         "export"    : VM_XEN::Export,
  2632.         "subexport"    : VM_XEN::SubExport,
  2633.  
  2634.  
  2635.         "parseDiskConfig" : VM_XEN::parseDiskConfig,
  2636.         "updateDiskConfig" : VM_XEN::updateDiskConfig,
  2637.         "ReadConfigFileSettings" : VM_XEN::ReadConfigFileSettings,
  2638.         "ReadAllConfigFileSettings" : VM_XEN::ReadAllConfigFileSettings,
  2639.  
  2640.         "Write" : VM_XEN::Write,
  2641.         "Prepare" : VM_XEN::Prepare,
  2642.         "Prepare2" : VM_XEN::Prepare2,
  2643.         "GetVirtualMachineState" : VM_XEN::GetVirtualMachineState,
  2644.         "ViewVirtualMachineConsole" : VM_XEN::ViewVirtualMachineConsole,
  2645.         "ShutdownVirtualMachine" : VM_XEN::ShutdownVirtualMachine,
  2646.         "TerminateVirtualMachine" : VM_XEN::TerminateVirtualMachine,
  2647.         "StartVirtualMachine" : VM_XEN::StartVirtualMachine,
  2648.         "InstallPackages" : VM_XEN::InstallPackages
  2649.     ];
  2650.     }
  2651.  
  2652.     global void VM_XEN() ``{
  2653.     // propose selection
  2654.     resetDiskConfig(); // resetDiskConfig() must be called first to ensure it's settings are not overrun by the source config settings. (#172714)
  2655.     resetSourceConfig();
  2656.  
  2657.     // propose configuration (domain) name
  2658.     resetConfigName();
  2659.  
  2660.     // create default network config (requires proposed config name)
  2661.     default_network = create_default_network_config();
  2662.     // set the default network config
  2663.     network = default_network;
  2664.  
  2665.     resetExtraArgs();
  2666.     resetHiddenArgs();
  2667.  
  2668.     SetModified(false);
  2669.     }
  2670. }
  2671.