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 / clients / inst_vm_source.ycp < prev    next >
Text File  |  2006-11-29  |  34KB  |  1,134 lines

  1. /**
  2.  * Module:    inst_vm_source.ycp
  3.  *
  4.  * Authors:    Ladislav Slezak <lslezak@suse.cz>
  5.  *        Michael G. Fritch <mgfritch@novell.com>
  6.  *
  7.  * Purpose:    Ask the user for installation source for the virtual machine.
  8.  *
  9.  * $Id: inst_vm_source.ycp 32678 2006-09-01 22:23:11Z mgfritch $
  10.  *
  11.  */
  12. {
  13.     textdomain "vm";
  14.  
  15.     import "VM";
  16.     import "VM_Common";
  17.     import "VM_XEN";
  18.     import "URL";
  19.     import "Label";
  20.     import "Popup";
  21.     import "Wizard";
  22.     import "Report";
  23.     import "Sequencer";
  24.     import "String";
  25.  
  26.     // screen title - installation source configuration
  27.     string title = _("Installation Source");
  28.  
  29.  
  30.     list<integer> sources = Pkg::SourceGetCurrent (false);
  31.  
  32.     map<string,any> sconfig = VM::GetSourceConfig();
  33.  
  34.     define term create_item (integer index, integer id) ``{
  35.         map product_data = Pkg::SourceProductData (id);
  36.         map general_data = Pkg::SourceGeneralData (id);
  37.     string srcurl = general_data["url"]:"";
  38.     map parsed_url = URL::Parse(srcurl);
  39.     if (!URL::Check(srcurl) || parsed_url["host"]:"" == "")    {
  40.         return nil;
  41.     }
  42.     else {
  43.         return `item (`id (index),
  44.               product_data["label"]:"unknown",
  45.               general_data["url"]:"");
  46.     }
  47.     }
  48.  
  49.  
  50.     define void fill_table () ``{
  51.  
  52.     integer i = 0;
  53.         list items = [];
  54.     integer j = -1;
  55.  
  56.         while (i < size (sources))
  57.     {
  58.         term new_item = create_item (i, sources[i]:0);
  59.         if (new_item != nil) items = add (items, new_item);
  60.         if (sources[i]:0 == sconfig["source_id"]:0)
  61.         j = i;
  62.         i = i + 1;
  63.         }
  64.  
  65.         UI::ChangeWidget (`id (`sources), `Items, items);
  66.     if (j > -1)
  67.         UI::ChangeWidget (`id(`sources), `CurrentItem, j);
  68.     }
  69.  
  70.  
  71.     define void updateConfig(map<string,any> conf) {
  72.     y2debug("updateConfig(%1)", conf);
  73.     VM::SetSourceConfig(conf["source_id"]:0, conf["inst_type"]:`cdrom, conf["custom_source"]:"");
  74.     }
  75.  
  76.     define void Refresh_SourceDialog() {
  77.     any rb = UI::QueryWidget (`id(`rbg), `CurrentButton);
  78.  
  79.     UI::ChangeWidget(`id(`kernel), `Enabled, (rb == `specify));
  80.     UI::ChangeWidget(`id(`select_kernel), `Enabled, (rb == `specify));
  81.     UI::ChangeWidget(`id(`initrd), `Enabled, (rb == `specify));
  82.     UI::ChangeWidget(`id(`select_initrd), `Enabled, (rb == `specify));
  83.  
  84.     }
  85.  
  86.  
  87.     /**
  88.     * Popup dialog - source configuration
  89.     * return symbol
  90.     */
  91.     define symbol SourceTypeDialog() {
  92.  
  93.     // screen title
  94.     string caption = _("Operating System Installation");
  95.  
  96.     term contents =
  97.     `MarginBox(1.5, 0.2, `VBox(
  98.         `RadioButtonGroup(`id(`rbg),
  99.             // frame label
  100.             `Frame(_("Install Using"),
  101.                 `MarginBox(1.5, 0.2, `VBox(
  102.                     // radio button
  103.                     `Left(`RadioButton(`id(`network_configured), `opt(`notify), _("Network Installation &Source"))),
  104.                     `VSpacing(0.5),
  105.                     // radio button
  106.                     `Left(`RadioButton(`id(`cdrom), `opt(`notify), _("&CD / DVD Device"))),
  107.                     `VSpacing(0.5),
  108.                     // radio button
  109.                     `Left(`RadioButton(`id(`iso), `opt(`notify), _("&ISO Image File")))
  110.                 ))
  111.             )
  112.         ),
  113.         `VSpacing(2),
  114.         // frame label
  115.         `Frame(_("Installation Options"),
  116.             `MarginBox(1.5, 0.2,
  117.                 `TextEntry(`id(`bootopts), `opt(`hstretch), "", VM::GetExtraArgs())))
  118.     ));
  119.  
  120.     // Operating System Installation - help text 1/4
  121.     string help_text = sformat(_("<p><b><big>%1</big></b></p>"), caption);
  122.     // Operating System Installation - help text 2/4
  123.     help_text = help_text + _("<p>The VM's operating system can be installed from a YaST Network Installation Source, a CD / DVD device, or an ISO image file.</p>");
  124.     // Operating System Installation - help text 3/4
  125.     help_text = help_text + _("<p>Any of these methods can be used to install SUSE operating systems.  Non-SUSE operating systems must be installed from a CD / DVD device or an ISO image file.</p>");
  126.     // Operating System Installation - help text 4/4
  127.     help_text = help_text + _("<p><b>Installation Options</b> are optional arguments passed to the kernel during installation.</p>");
  128.  
  129.  
  130.     Wizard::SetContents(caption, contents, help_text, true, true);
  131.  
  132.     symbol s = `dummy;
  133.  
  134.     // set the default state for the radio buttons
  135.     if (sconfig["inst_type"]:`cdrom == `network_configured || sconfig["inst_type"]:`cdrom == `network_custom)
  136.         UI::ChangeWidget(`id(`rbg), `CurrentButton, `network_configured);
  137.     else if (sconfig["inst_type"]:`cdrom == `iso)
  138.         UI::ChangeWidget(`id(`rbg), `CurrentButton, `iso);
  139.     else
  140.         UI::ChangeWidget(`id(`rbg), `CurrentButton, `cdrom);
  141.  
  142.  
  143.     while(!contains([`next, `back, `abort, `cancel], s))
  144.     {
  145.         s = (symbol) UI::UserInput();
  146.         y2milestone("s=%1", s);
  147.  
  148. //FIXME: popup confirmation for abort???
  149.         if (s == `next) {
  150.         symbol type = (symbol) UI::QueryWidget (`id(`rbg), `CurrentButton);
  151.  
  152.         if (type == `network_configured) {
  153.             if (sconfig["inst_type"]:`cdrom == `network_custom)
  154.                 type = `network_custom;
  155.             VM::SetCustomKernel(false);
  156.         }
  157.  
  158.         y2milestone("old sconfig: %1", sconfig);
  159.         sconfig["inst_type"] = type;
  160.         updateConfig(sconfig);
  161.         y2milestone("new sconfig: %1", sconfig);
  162.  
  163.         string boot = (string) UI::QueryWidget (`id(`bootopts), `Value);
  164.         VM::SetExtraArgs(boot);
  165.  
  166.         s = type;
  167.         break;
  168.         }
  169. // FIXME: add catch for any unknown return values???
  170.     }
  171.  
  172.     return s;
  173.     }
  174.  
  175.  
  176.  
  177.  
  178.     define symbol CD_SourceDialog() {
  179.  
  180.     // dialog title
  181.     string caption = _("Install Using a CD / DVD Device");
  182.  
  183.         list<term> cd_items = [];
  184.         list<map> cd_hwinfo = (list<map>)SCR::Read(.probe.cdrom);
  185.  
  186.         if (cd_hwinfo != nil) {
  187.             foreach(map dev, cd_hwinfo, {
  188.             string device = dev["dev_name"]:"";
  189.             string model = dev["model"]:"";
  190.  
  191.             y2milestone("CD-ROM model: %1, device: %2", model, device);
  192.  
  193.             if (device != nil && device != "") {
  194.             // format CD device name: %1 is model name (e.g. "TOSHIBA DVD-ROM SD-M1402"), %2 is device name (e.g. /dev/hdc)
  195.             cd_items = add(cd_items, `item(`id(device), sformat(_("%1 (%2)"), model, device)/*, device == cd*/));
  196.             }
  197.         });
  198.         }
  199.  
  200.     term contents =
  201.         `MarginBox(1.5, 0.2, `VBox(
  202.             `HBox(
  203. //                `HSpacing(3),
  204.                 // combobox label
  205.                 `ComboBox(`id(`cddev), _("&CD / DVD Device"), cd_items),
  206.                 `HStretch()
  207.             ),
  208.             `VSpacing(2),
  209.             `RadioButtonGroup(`id(`rbg),
  210.                 // frame label
  211.                 `Frame(_("CD / DVD Media Type"),
  212.                     `MarginBox(1.5, 1, `VBox(
  213.                         // radio button
  214.                         `Left(`RadioButton(`id(`extract), `opt(`notify), _("&SUSE Installation Source"))),
  215.                         `VSpacing(0.5),
  216.                         // radio button
  217.                         `Left(`RadioButton(`id(`specify), `opt(`notify), _("&Other Installation Source"))),
  218.                         `HBox(
  219.                             `HSpacing(3),
  220.                             // textbox label
  221.                             `TextEntry(`id(`kernel), `opt(`hstretch), _("&Xen-Enabled Kernel"), VM::GetKernelImage()),
  222.                             `HSpacing(1),
  223.                             `VBox(
  224.                                 `Label(""),
  225.                                 // button label
  226.                                 `PushButton(`id(`select_kernel), _("Browse..."))
  227.                             )
  228.                         ),
  229.                         `HBox(
  230.                             `HSpacing(3),
  231.                             // textbox label
  232.                             `TextEntry(`id(`initrd), `opt(`hstretch), _("&Installation File (initrd)"), VM::GetInitrdImage()),
  233.                             `HSpacing(1),
  234.                             `VBox(
  235.                                 `Label(""),
  236.                                 // button label
  237.                                 `PushButton(`id(`select_initrd), _("Browse..."))
  238.                             )
  239.                         )
  240.                     ))
  241.                 )
  242.             )
  243.         ));
  244.  
  245.     // Install Using a CD / DVD Device help text 1/3
  246.     string help_text = sformat(_("<p><b><big>%1</big></b></p>"), caption);
  247.     // Install Using a CD / DVD Device help text 2/3
  248.     help_text = help_text + _("<p>The VM's operating system will be installed from the selected <b>CD / DVD device</b>.</p>");
  249.     // Install Using a CD / DVD Device help text 3/3
  250.     help_text = help_text + _("<p>Specify whether the <b>CD / DVD media type</b> is a SUSE installation source, or some other type.  Using installation media other than SUSE requires you to designate the locations of the Xen-enabled kernel and, optionally, the initial installation program (initrd).  These files must be accessible on the VM Server's file system.</p>");
  251.  
  252.     Wizard::SetContents(caption, contents, help_text, true, true);
  253.  
  254.     symbol s = `dummy;
  255.  
  256.     if (VM::GetCustomKernel()) {
  257.         UI::ChangeWidget(`id(`rbg), `CurrentButton, `specify);
  258.     }
  259.     else {
  260.         UI::ChangeWidget(`id(`rbg), `CurrentButton, `extract);
  261.     }
  262.  
  263.     string old_cddev = sconfig["custom_source"]:""; // remember the old source, just in case it needs to be removed from the disks config
  264.     UI::ChangeWidget(`id(`cddev), `Value, old_cddev);
  265.  
  266.     // initialize the widgets
  267.     Refresh_SourceDialog();
  268.  
  269.     while(!contains([`next, `back, `abort, `cancel], s))
  270.     {
  271.  
  272.         s = (symbol) UI::UserInput();
  273.         y2milestone("s=%1", s);
  274.  
  275.         Refresh_SourceDialog();
  276.  
  277. //FIXME: popup confirmation for abort???
  278.         if (s == `next) {
  279.         symbol type = (symbol) UI::QueryWidget (`id(`rbg), `CurrentButton);
  280.         string cddev = (string) UI::QueryWidget (`id(`cddev), `Value);
  281.         string kernel = "";
  282.         string initrd = "";
  283.  
  284.         if (cddev == nil || cddev == "") {
  285.             // popup error message
  286.             Report::Error(_("A CD / DVD device name must be selected."));
  287.             s = `again;
  288.             continue;
  289.         }
  290.         // FIXME: check whether the file exists
  291. /*        if ((integer)SCR::Read(.target.size, cddev) < 0) {
  292.             // popup error message
  293.             // %1 is file name
  294.             Report::Error(_("The specified CD / DVD device does not exist, or
  295. there is no media in the CD / DVD device.
  296.  
  297. Please ensure that the desired media is in the selected CD / DVD device.
  298. "));
  299.             s = `again;
  300.             continue;
  301.         }
  302. */
  303.  
  304.         if (type == `specify) {
  305.             kernel = (string) UI::QueryWidget (`id(`kernel), `Value);
  306.             initrd = (string) UI::QueryWidget (`id(`initrd), `Value);
  307.  
  308.             if (kernel == nil || kernel == "") {
  309.             // popup error message
  310.             Report::Error(_("The kernel file name cannot be empty."));
  311.             s = `again;
  312.             continue;
  313.             }
  314.  
  315.             VM::SetCustomKernel(true);
  316.             VM::SetKernelImage(kernel);
  317.             VM::SetInitrdImage(initrd);
  318.  
  319.             // if NetWare always set localtime=1 in para virtualization
  320.             if (VM_Common::GetVirtualizationType() == "para" && VM_Common::IsNetWareKernel(kernel)) {
  321.             VM::SetLocaltime(1);
  322.             if (VM::GetMemorySize() < 512) {
  323.                 VM::SetMemorySize(512); // if NetWare increase the memory_size=512
  324.             }
  325.             }
  326.         }
  327.         else {
  328.             VM::SetCustomKernel(false);
  329.         }
  330.  
  331.         // set custom installation source
  332.         y2milestone("old sconfig: %1", sconfig);
  333.         sconfig["custom_source"] = cddev;
  334.         updateConfig(sconfig);
  335.         y2milestone("new sconfig: %1", sconfig);
  336.  
  337.         VM::UpdateDiskConfig(old_cddev, cddev, "phys");
  338.  
  339.         }
  340.         else if (s == `select_kernel) {
  341.         string new_kernel = (string)UI::QueryWidget(`id(`kernel), `Value);
  342.         // popup title
  343.         new_kernel = UI::AskForExistingFile(new_kernel, "*", _("Select Xen-Enabled Kernel"));
  344.  
  345.         if (new_kernel != nil)
  346.         {
  347.             UI::ChangeWidget(`id(`kernel), `Value, new_kernel);
  348.         }
  349.         }
  350.         else if (s == `select_initrd) {
  351.         string new_initrd = (string)UI::QueryWidget(`id(`initrd), `Value);
  352.         // popup title
  353.         new_initrd = UI::AskForExistingFile(new_initrd, "*", _("Select Initial RAM Disk"));
  354.  
  355.         if (new_initrd != nil)
  356.         {
  357.             UI::ChangeWidget(`id(`initrd), `Value, new_initrd);
  358.         }
  359.         }
  360. // FIXME: add catch for any unknown return values???
  361.     }
  362.  
  363.     return s;
  364.     }
  365.  
  366.  
  367.     define symbol ISO_SourceDialog() {
  368.  
  369.     // dialog title
  370.     string caption = _("Install Using an ISO Image");
  371.  
  372.     term contents =
  373.     `MarginBox(1.5, 0.2, `VBox(
  374.         `HBox(
  375. //            `HSpacing(3),
  376.             // textbox label
  377.             `TextEntry(`id(`cdromimage), `opt(`hstretch), _("&ISO Image File")),
  378.             `HSpacing(1),
  379.             `VBox(
  380.                 `Label(""),
  381.                 // button label
  382.                 `PushButton(`id(`select_cdromimage), _("Browse..."))
  383.             )
  384.         ),
  385.         `VSpacing(2),
  386.         `RadioButtonGroup(`id(`rbg),
  387.             // heading in a popup dialog
  388.             `Frame(_("ISO Type"),
  389.                 `MarginBox(1.5, 1, `VBox(
  390.                     // radio button label
  391.                     `Left(`RadioButton(`id(`extract), `opt(`notify), _("&SUSE Installation Source"))),
  392.                     `VSpacing(0.5),
  393.                     // radio button label
  394.                     `Left(`RadioButton(`id(`specify), `opt(`notify), _("&Other Installation Source"))),
  395.                     `HBox(
  396.                         `HSpacing(3),
  397.                         // textbox label
  398.                         `TextEntry(`id(`kernel), `opt(`hstretch), _("&Xen-Enabled Kernel"), VM::GetKernelImage()),
  399.                         `HSpacing(1),
  400.                         `VBox(
  401.                             `Label(""),
  402.                             // button label
  403.                             `PushButton(`id(`select_kernel), _("Browse..."))
  404.                         )
  405.                     ),
  406.                     `HBox(
  407.                         `HSpacing(3),
  408.                         // textbox label
  409.                         `TextEntry(`id(`initrd), `opt(`hstretch), _("&Installation File (initrd)"), VM::GetInitrdImage()),
  410.                         `HSpacing(1),
  411.                         `VBox(
  412.                             `Label(""),
  413.                             // button label
  414.                             `PushButton(`id(`select_initrd), _("Browse..."))
  415.                         )
  416.                     )
  417.                 ))
  418.             )
  419.         )
  420.     ));
  421.  
  422.     // Install Using an ISO Image - help text 1/3
  423.     string help_text = sformat(_("<p><b><big>%1</big></b></p>"), caption);
  424.     // Install Using an ISO Image - help text 2/3
  425.     help_text = help_text + _("If the installation source files are stored in an .ISO image file, you can specify its location on the VM Server's file system.</p>");
  426.     // Install Using an ISO Image - help text 3/3
  427.     help_text = help_text + _("<p>Specify whether the <b>ISO image file</b> is a SUSE installation source, or some other type. Using installation media other than SUSE requires you to designate the locations of the Xen-enabled kernel and, optionally, the initial installation program (initrd). These files must be accessible on the VM Server's file system.</p>");
  428.  
  429.     Wizard::SetContents(caption, contents, help_text, true, true);
  430.  
  431.     symbol s = `dummy;
  432.  
  433.     if (VM::GetCustomKernel()) {
  434.         UI::ChangeWidget(`id(`rbg), `CurrentButton, `specify);
  435.     }
  436.     else {
  437.         UI::ChangeWidget(`id(`rbg), `CurrentButton, `extract);
  438.     }
  439.     
  440.     string old_cdromimage = sconfig["custom_source"]:""; // remember the old source, just in case it needs to be removed from the disks config
  441.     UI::ChangeWidget(`id(`cdromimage), `Value, (regexpmatch(old_cdromimage, ".*iso")) ? old_cdromimage : "");
  442.  
  443.     // initialize the widgets
  444.     Refresh_SourceDialog();
  445.  
  446.     while(!contains([`next, `back, `abort, `cancel], s))
  447.     {
  448.         s = (symbol) UI::UserInput();
  449.         y2milestone("s=%1", s);
  450.  
  451.         Refresh_SourceDialog();
  452.  
  453. //FIXME: popup confirmation for abort???
  454.         if (s == `next) {
  455.         symbol type = (symbol) UI::QueryWidget (`id(`rbg), `CurrentButton);
  456.         string cdromimage = "";
  457.         string kernel = "";
  458.         string initrd = "";
  459.  
  460.         cdromimage = (string) UI::QueryWidget (`id(`cdromimage), `Value);
  461.         if (cdromimage == nil || cdromimage == "") {
  462.             // popup error message
  463.             Report::Error(_("ISO file name cannot be empty."));
  464.             s = `again;
  465.             continue;
  466.         }
  467.  
  468.         if (type == `specify) { // kernel and initrd specified by user
  469.             kernel = (string) UI::QueryWidget (`id(`kernel), `Value);
  470.             initrd = (string) UI::QueryWidget (`id(`initrd), `Value);
  471.  
  472.             if (kernel == nil || kernel == "") {
  473.                 // popup error message
  474.                 Report::Error(_("The kernel file name cannot be empty."));
  475.                 s = `again;
  476.                 continue;
  477.             }
  478.     
  479.             VM::SetCustomKernel(true);
  480.             VM::SetKernelImage(kernel);
  481.             VM::SetInitrdImage(initrd);
  482.     
  483.             // if NetWare always set localtime=1 in para virtualization
  484.             if (VM_Common::GetVirtualizationType() == "para" && VM_Common::IsNetWareKernel(kernel)) {
  485.                 VM::SetLocaltime(1);
  486.                 if (VM::GetMemorySize() < 512) {
  487.                     VM::SetMemorySize(512); // if NetWare increase the memory_size=512
  488.                 }
  489.             }
  490.  
  491.         }
  492.         else { // extract the kernel and initrd from a SUSE inst source
  493.             VM::SetCustomKernel(false);
  494.         }
  495.  
  496.         // set custom installation source
  497.         y2milestone("old sconfig: %1", sconfig);
  498.         sconfig["custom_source"] = cdromimage;
  499.         updateConfig(sconfig);
  500.         y2milestone("new sconfig: %1", sconfig);
  501.  
  502.         VM::UpdateDiskConfig(old_cdromimage, cdromimage, "loop-use");
  503.  
  504.         }
  505.         else if (s == `select_kernel) {
  506.         string new_kernel = (string)UI::QueryWidget(`id(`kernel), `Value);
  507.         // popup title
  508.         new_kernel = UI::AskForExistingFile(new_kernel, "*", _("Select Xen-Enabled Kernel"));
  509.  
  510.         if (new_kernel != nil)
  511.         {
  512.             UI::ChangeWidget(`id(`kernel), `Value, new_kernel);
  513.         }
  514.         }
  515.         else if (s == `select_initrd) {
  516.         string new_initrd = (string)UI::QueryWidget(`id(`initrd), `Value);
  517.         // popup title
  518.         new_initrd = UI::AskForExistingFile(new_initrd, "*", _("Select Initial RAM Disk"));
  519.  
  520.         if (new_initrd != nil)
  521.         {
  522.             UI::ChangeWidget(`id(`initrd), `Value, new_initrd);
  523.         }
  524.         }
  525.         else if (s == `select_cdromimage) {
  526.         string cdimg = (string)(UI::QueryWidget(`id(`cdromimage), `Value));
  527.         // popup title
  528.         string new_img = UI::AskForExistingFile(cdimg, "*.iso", _("Select ISO Image"));
  529.     
  530.         if (new_img != nil)
  531.         {
  532.             UI::ChangeWidget(`id(`cdromimage), `Value, new_img);
  533.         }
  534.         }
  535. // FIXME: add catch for any unknown return values???
  536.     }
  537.  
  538.     return s;
  539.     }
  540.  
  541.  
  542.  
  543. define symbol Network_SourceDialog() {
  544.     // build and show dialog
  545.     integer indent = 3;
  546.     // dialog title
  547.     string caption = _("Install Using a Network Installation Source");
  548.  
  549.     string old_custom_source = sconfig["custom_source"]:""; // remember the old source, just in case it needs to be removed from the disks config
  550.     string default_custom_src = "";
  551.     if (! regexpmatch(sconfig["custom_source"]:"", ".*iso") && ! regexpmatch(sconfig["custom_source"]:"", "/dev.*")) {
  552.     default_custom_src = sconfig["custom_source"]:"";
  553.     }
  554.     boolean inst_type_configured = true;
  555.     if (sconfig["inst_type"]:`unknown != `network_configured && default_custom_src != "") {
  556.     inst_type_configured = false;
  557.     }
  558.  
  559.     term contents = `VBox(
  560.             `RadioButtonGroup(`id(`source), `opt(`notify),
  561.                 `VBox(
  562.                 `VSpacing(0.3),
  563.                 // radio button label
  564.                 `Left(`RadioButton(`id(`network_configured),  `opt(`notify), _("&Configured Installation Source"),  inst_type_configured)),
  565.                 `VSpacing(0.3),
  566.                 `HBox(
  567.                     `HSpacing(indent),
  568.                     `Table(`id(`sources),
  569.                     // table column heading
  570.                     `header(_("Name"), _("URL")), [ ])
  571.                 ),
  572.                 // push button label
  573.                 // installation source configuration module
  574.                 // is started when it's pressed
  575.                 `PushButton(`id(`inst_src), _("C&onfigure...")),
  576.                 `VSpacing(1),
  577.                 // radio button label
  578.                 `Left(`RadioButton(`id(`network_custom),  `opt(`notify), _("Custom &Installation Source"), inst_type_configured == false)),
  579.                 `HBox(
  580.                     `HSpacing(indent),
  581.                     // textbox label
  582.                     `TextEntry(`id(`custom_source), _("&URL of Installation Source"), default_custom_src)
  583.                 ),
  584.                 `VSpacing(1)
  585.  
  586. // TODO: disabled, we need kernel package before starting VM, we MUST know the URL
  587. //                // textbox label
  588. //                `Left(`RadioButton(`id(`slp),  `opt(`notify), _("&SLP Installation Source"), sconfig["inst_type"]:`unknown == `slp)),
  589. //                `VSpacing(1)
  590.                 )
  591.             )
  592.             );
  593.  
  594.     // Install Using a Network Installation Source - help text 1/4
  595.     string help_text = sformat(_("<P><B><big>%1</big></B></P>"), caption);
  596.     // Install Using a Network Installation Source - help text 2/4
  597.     help_text = help_text + _("<p>YaST provides a library for storing <b>SUSE installation source</b> files with their associated kernel and initial install programs (initrd).</p>");
  598.     // Install Using a Network Installation Source - help text 3/4
  599.     help_text = help_text + _("<p>Make sure to select an installation source that includes a Xen-enabled kernel.</p>");
  600.     // Install Using a Network Installation Source - help text 4/4
  601.     help_text = help_text + _("<P>Only network installation sources, such as FTP or NFS, are supported.</P>");
  602.  
  603.     Wizard::SetContents(caption, contents, help_text, true, true);
  604.  
  605.     fill_table();
  606.  
  607.     symbol ret = nil;
  608.  
  609.     while (true)
  610.     {
  611.     // refresh status of the widgets
  612.     symbol selected = (symbol)(UI::QueryWidget(`id(`source), `CurrentButton));
  613.     UI::ChangeWidget(`id(`sources), `Enabled, selected == `network_configured);
  614.     UI::ChangeWidget(`id(`inst_src), `Enabled, selected == `network_configured);
  615.     UI::ChangeWidget(`id(`custom_source), `Enabled, selected == `network_custom);
  616.  
  617.     ret = (symbol) Wizard::UserInput ();
  618.  
  619.     if (ret == `abort || ret == `cancel) {
  620.         if (Popup::ReallyAbort(VM_Common::GetModified()))
  621.             break;
  622.     }
  623.     else if (ret == `back) {
  624.         break;
  625.     }
  626.     else if (ret == `next) {
  627.         // check if selected installation source is valid
  628.         integer current = (integer) UI::QueryWidget (`id(`sources), `CurrentItem);
  629.  
  630.         y2milestone("sources: %1", sources);
  631.         integer current_srcid = -1;
  632.         if (size(sources) > 0)
  633.         {
  634.         current_srcid = sources[current]:0;
  635.         }
  636.  
  637.         y2milestone("current_srcid: %1", current_srcid);
  638.  
  639.         symbol selected_type = (symbol)UI::QueryWidget(`id(`source), `CurrentButton);
  640.         string selected_custom_source = (string)UI::QueryWidget(`id(`custom_source), `Value);
  641.         string srcurl = "";
  642.  
  643.         if (selected_type == `network_configured)
  644.         {
  645.         if (current_srcid >= 0)
  646.         {
  647.             map general_data = Pkg::SourceGeneralData(current_srcid);
  648.             srcurl = general_data["url"]:"";
  649.         }
  650.         }
  651.         else
  652.         {
  653.         srcurl = selected_custom_source;
  654.         }
  655.  
  656.         map parsed_url = URL::Parse(srcurl);
  657.  
  658.         if (!URL::Check(srcurl) || parsed_url["host"]:"" == "")
  659.         {
  660.         // popup error message
  661.         Report::Error(_("Entered URL value is not valid."));
  662.         }
  663.         else
  664.         {
  665.         y2debug("Selected source: %1", srcurl);
  666.         sconfig["inst_type"] = selected_type;
  667.  
  668.         if (selected_type == `network_configured)
  669.         {
  670.             sconfig["source_id"] = current_srcid;
  671.         }
  672.         else if (selected_type == `network_custom)
  673.         {
  674.             sconfig["custom_source"] = selected_custom_source;
  675.         }
  676.         else
  677.         {
  678.             y2error("Unknown installation type");
  679.         }
  680.  
  681.         updateConfig(sconfig);
  682.         VM::SetCustomKernel(false);
  683.         VM::UpdateDiskConfig(old_custom_source, "", ""); // remove any old custom sources that were added as disks
  684.         break;
  685.         }
  686. /*        else
  687.         {
  688.         // popup error message
  689.         Report::Error(_("Only network installation sources
  690. are supported in the installation."));
  691.         }*/
  692.     }
  693.     else if (ret == `inst_src) {
  694.         integer current = (integer) UI::QueryWidget (`id(`sources), `CurrentItem);
  695.  
  696.         integer current_srcid = -1;
  697.         if (size(sources) > 0)
  698.         {
  699.         current_srcid = sources[current]:-1;
  700.         }
  701.  
  702.         y2milestone("Selected source: %1", current_srcid);
  703.  
  704.         // remember the sources
  705.         list<integer> sources_old = sources;
  706.  
  707.  
  708.         // start installation source configuration module
  709.         WFM::CallFunction("inst_source", []);
  710.  
  711.  
  712.         // refresh table content
  713.         sources = Pkg::SourceGetCurrent(false);
  714.         y2milestone("Configured sources: %1", sources);
  715.  
  716.  
  717.         // recreate the new sources to load the resolvables
  718.         list<map> new_sources = [];
  719.  
  720.         foreach(integer src, sources,
  721.         {
  722.             if (!contains(sources_old, src))
  723.             {
  724.             map general_data = Pkg::SourceGeneralData(src);
  725.             string srcurl = general_data["url"]:"";
  726.             string product_dir = general_data["product_dir"]:"/";
  727.  
  728.             new_sources = add(new_sources, $[ "id" : src, "url" : srcurl, "product_dir" : product_dir ]);
  729.             }
  730.         }
  731.         );
  732.  
  733.         y2milestone("New sources: %1", new_sources);
  734.  
  735.         // the recreated sources, inst_source doesn't call Pkg::SourceCreate(),
  736.         // the new sources are not fully initialized
  737.         list<integer> new_ids = [];
  738.  
  739.         if (size(new_sources) > 0)
  740.         {
  741.         // initialize the new sources
  742.         foreach(map s, new_sources,
  743.             {
  744.             Pkg::SourceDelete(s["id"]:-1);
  745.  
  746.             integer new_id = Pkg::SourceCreate(s["url"]:"", s["product_dir"]:"/");
  747.  
  748.             if (new_id != nil && new_id > 0)
  749.             {
  750.                 y2milestone("Created new source %1: %2", new_id, s["url"]:"");
  751.                 new_ids = add(new_ids, new_id);
  752.             }
  753.             }
  754.  
  755.         );
  756.  
  757.         sources = Pkg::SourceGetCurrent(false);
  758.         }
  759.  
  760.         // the current selected source is missing
  761.         if (!contains(sources, current_srcid))
  762.         {
  763.         y2milestone("Previously selected source %1 is not available (%2)", current_srcid, sources);
  764.  
  765.         // exactly one new source, suppose the ID has changed
  766.         if (size(new_ids) == 1)
  767.         {
  768.             integer src = new_ids[0]:0;
  769.             y2milestone("Using new source ID %1 instead of %2", src , current_srcid);
  770.  
  771.             // select the source
  772.             sconfig["source_id"] = src;
  773.             // refresh list
  774.             sources = Pkg::SourceGetCurrent(false);
  775.         }
  776.         else
  777.         {
  778.             // reset config, the current source is not valid
  779.             // TODO: display a warning popup - "The installation source is not available."
  780.             VM::ResetSource();
  781.             sconfig = VM::GetSourceConfig();
  782.         }
  783.         }
  784.  
  785.         fill_table();
  786.     }
  787.     }
  788.  
  789.     return ret;
  790. }
  791.  
  792. define void RefreshFullOptionsDialog()
  793. {
  794.     symbol enabled = (symbol) UI::QueryWidget (`id(`rb_group), `CurrentButton);
  795.  
  796.     UI::ChangeWidget(`id(`cdromimage), `Enabled, enabled == `iso);
  797.     UI::ChangeWidget(`id(`select_file), `Enabled, enabled == `iso);
  798.  
  799.     UI::ChangeWidget(`id(`cddev), `Enabled, enabled == `cdrom);
  800. }
  801.  
  802. define symbol FullOptionsDialog()
  803. {
  804.     // dialog title
  805.     string caption = _("Operating System Installation");
  806.  
  807.     map<string,string> fulloption = VM_XEN::GetFullOptions();
  808.     string cd = fulloption["cdrom_image"]:"";
  809.     string cd_type = fulloption["cdrom_image_type"]:"phy";
  810.     string boot = fulloption["boot_device"]:"c";
  811.  
  812.     y2milestone("VTx config: cdrom_image: %1, cdrom_image_type: %2, boot_device: %3", cd, cd_type, boot);
  813.  
  814.     list<string> cd_devs = [];
  815.     list<term> cd_items = [];
  816.  
  817.     list<map> cd_hwinfo = (list<map>)SCR::Read(.probe.cdrom);
  818.  
  819.     if (cd_hwinfo != nil) {
  820.     foreach(map dev, cd_hwinfo,
  821.     {
  822.         string device = dev["dev_name"]:"";
  823.         string model = dev["model"]:"";
  824.  
  825.         y2milestone("CD-ROM model: %1, device: %2", model, device);
  826.  
  827.         if (device != nil && device != "")
  828.         {
  829.         cd_devs = add(cd_devs, device);
  830.         // format CD device name: %1 is model name (e.g. "TOSHIBA DVD-ROM SD-M1402"), %2 is device name (e.g. /dev/hdc)
  831.         cd_items = add(cd_items, `item(`id(device), sformat(_("%1 (%2)"), model, device), device == cd));
  832.         }
  833.     }
  834.     );
  835.     }
  836.  
  837.     term contents =
  838.     `MarginBox(1.5, 0.2,
  839.         // frame label
  840.         `Frame(_("Install Using"),
  841.             `MarginBox(0.5, 0.5,
  842.                 `RadioButtonGroup(`id(`rb_group),
  843.                     `VBox(
  844.                         // radio button label
  845.                         `Left(`RadioButton(`id(`cdrom), `opt(`notify), _("&CD / DVD Device"), boot == "d" && cd_type != "file")),
  846.                         `HBox(
  847.                             `HSpacing(3),
  848.                             // combo box label
  849.                             `ComboBox(`id(`cddev), _("&Device Name"), cd_items),
  850.                             `HStretch()
  851.                         ),
  852.                         `VSpacing(1),
  853.                         // radio button label
  854.                         `Left(`RadioButton(`id(`iso), `opt(`notify), _("&ISO Image File"), boot == "d" && cd_type == "file")),
  855.                         `HBox(
  856.                             `HSpacing(3),
  857.                             // textbox label
  858.                             `TextEntry(`id(`cdromimage), `opt(`hstretch), _("&File Name"), (boot == "d" && cd_type == "file" && !contains(cd_devs, cd)) ? cd : ""),
  859.                             `HSpacing(1),
  860.                             `VBox(
  861.                                 `Label(""),
  862.                                 // button label
  863.                                 `PushButton(`id(`select_file), _("Br&owse..."))
  864.                             ),
  865.                             `HSpacing(1)
  866.                         )
  867.                     )
  868.                 )
  869.             )
  870.         )
  871.     );
  872.  
  873.  
  874.     // help text for OS selection in full virtualization mode (1/2)
  875.     string help_text = sformat(_("<p><b><big>%1</big></b></p>"), caption);
  876.     // help text for OS selection in full virtualization mode (2/2)
  877.     help_text = help_text + _("<p>The installation of the operating system can be started from a physical CD / DVD or an ISO image file.</p>");
  878.  
  879.     Wizard::SetContents (caption, contents, help_text, true, true);
  880.  
  881.     if (cd_type != "file")
  882.     UI::ChangeWidget(`id(`rb_group), `CurrentButton, `cdrom);
  883.     else
  884.     UI::ChangeWidget(`id(`rb_group), `CurrentButton, `iso);
  885.  
  886.     symbol ret = nil;
  887.  
  888.     while (true) {
  889.     RefreshFullOptionsDialog();
  890.  
  891.     ret = (symbol) Wizard::UserInput();
  892.  
  893.     if (ret == `abort || ret == `cancel) {
  894.         if (Popup::ReallyAbort(VM_Common::GetModified()))
  895.             break;
  896.     }
  897.     else if (ret == `back) {
  898.         break;
  899.     }
  900.     else if (ret == `next) {
  901.         symbol bootdev_symbol = (symbol)(UI::QueryWidget(`id(`rb_group), `CurrentButton));
  902.         string bootdev = (VM_Common::proposal_type == "install") ? "d" : "c";
  903.  
  904.         y2milestone("bootdev_symbol: %1",  bootdev_symbol);
  905.         y2milestone("bootdev: %1", bootdev);
  906.  
  907.         string cdimg = "";
  908.  
  909.         if (bootdev_symbol == `cdrom)
  910.         {
  911.         cdimg = (string)(UI::QueryWidget(`id(`cddev), `Value));
  912.         }
  913.         else
  914.         {
  915.         cdimg = (string)(UI::QueryWidget(`id(`cdromimage), `Value));
  916.         }
  917.  
  918.         if (bootdev_symbol == `iso && cdimg == "")
  919.         {
  920.         // error - entered empty ISO image file name
  921.         Report::Error(_("Select an ISO image file for CD-ROM emulation."));
  922.         }
  923.         else
  924.         {
  925.         map<string,string> opts = $["boot_device":bootdev, "cdrom_image":cdimg, "cdrom_image_type": ((bootdev_symbol == `cdrom) ? "phy" : "file")];
  926.         y2milestone("Full virtualization options: %1", opts);
  927.         VM_XEN::SetFullOptions( opts );
  928.         break;
  929.         }
  930.     }
  931.     else if (ret == `select_file) {
  932.         string cdimg = (string)(UI::QueryWidget(`id(`cdromimage), `Value));
  933.         string new_img = UI::AskForExistingFile(cdimg, "*.iso", _("Select ISO Image"));
  934.  
  935.         if (new_img != nil)
  936.         {
  937.         UI::ChangeWidget(`id(`cdromimage), `Value, new_img);
  938.         }
  939.     }
  940.     else {
  941.         y2error("unexpected retcode: %1", ret);
  942.         continue;
  943.     }
  944.     }
  945.  
  946.     return ret;
  947. }
  948.  
  949.  
  950. /**
  951.  * dialog - boot options configuration
  952.  * @return symbol dialog result
  953.  */
  954. define symbol BootOptionsDialog() {
  955.     // figure out what disks are configured.
  956.     list<string> used_targets = VM::GetConfiguredDiskTargets(VM::GetDiskConfig());
  957.     // propose some partions based on the configured disks.
  958.     list<string> valid_partitions = [];
  959.     foreach (string target, used_targets, {
  960.         if (target != nil && target != "") {
  961.             list<string> postfix = [];
  962.             if (findfirstof(target, String::CDigit()) != nil) {// already contains partition.
  963.                 postfix = [ target ];
  964.             }
  965.             else {
  966.                 postfix = ["1", "2", "3", "4", "5", "6"];
  967.                 postfix = maplist(string postchar, postfix, { return target + postchar; });
  968.             }
  969.             valid_partitions = (list<string>) union(valid_partitions, postfix);
  970.         }
  971.     });
  972.     valid_partitions = toset(valid_partitions); //sort list and remove duplicates
  973.  
  974.     // dialog title
  975.     string caption = _("Operating System Boot Files");
  976.     
  977.     term contents =
  978.         `MarginBox(1.5, 0.2, `VBox(
  979.             // frame label
  980.             `Frame(_("Boot Using"),
  981.                 `MarginBox(1.5, 0.2, `VBox(
  982.                     // combobox label
  983.                     `ComboBox(`id(`device), `opt(`editable,`hstretch), _("&Partition Containing Boot Files"), valid_partitions),
  984.                     `VSpacing(0.5),
  985.                     // textbox label
  986.                     `TextEntry(`id(`kernel), `opt(`hstretch), _("&Xen-Enabled Kernel"), VM::GetKernelImage()),
  987.                     `VSpacing(0.5),
  988.                     // textbox label
  989.                     `TextEntry(`id(`initrd), `opt(`hstretch), _("Boot &File (initrd)"), VM::GetInitrdImage())
  990.                 ))
  991.             ),
  992.             `VSpacing(2),
  993.             // frame label
  994.             `Frame(_("Boot Options"),
  995.                 `MarginBox(1.5, 0.2,
  996.                 `TextEntry(`id(`bootopts), `opt(`hstretch), "", VM::GetExtraArgs()))
  997.             )
  998.         ));
  999.  
  1000.     // boot options - help text 1/3
  1001.     string help_text = sformat(_("<p><b><big>%1</big></b></p>"), caption);
  1002.     // boot options - help text 2/3
  1003.     help_text = help_text + _("<p>The VM boots its operating system using the <b>kernel</b> and <b>boot file</b> stored on a virtual disk. Specify the partition that holds these files and the location of each. For example, partition: <tt>hda1</tt>; location of <b>kernel</b>: <tt>/boot/vmlinuz-xen</tt>; and location of <b>boot file</b>: <tt>/boot/initrd-xen.</tt></p>");
  1004.     // boot options - help text 3/3
  1005.     help_text = help_text + _("<p><b>Boot options</b> are optional arguments passed to the kernel each time it boots.</p>");
  1006.  
  1007.     Wizard::SetContents(caption, contents, help_text, true, true);
  1008.  
  1009.     UI::ChangeWidget (`id(`device), `Value, VM_Common::root_device);
  1010.  
  1011.     symbol ui = `dummy;
  1012.     while(!contains([`next, `back, `abort, `cancel], ui)) {
  1013.  
  1014.         ui = (symbol) UI::UserInput();
  1015.         y2milestone("ui=%1", ui);
  1016.  
  1017.         if (ui == `abort || ui == `cancel) {
  1018.             if (!Popup::ReallyAbort(VM_Common::GetModified()))
  1019.                 ui = `again;
  1020.                 continue;
  1021.         }
  1022.         else if (ui == `next) {
  1023.             string device = (string) UI::QueryWidget (`id(`device), `Value);
  1024.             string kernel = (string) UI::QueryWidget (`id(`kernel), `Value);
  1025.             string initrd = (string) UI::QueryWidget (`id(`initrd), `Value);
  1026.             string bootopts = (string) UI::QueryWidget (`id(`bootopts), `Value);
  1027.     
  1028.             if (device == nil || device == "") {
  1029.                 // popup error message
  1030.                 Report::Error(_("Partition Containing Kernel and RAM Disk cannot be empty."));
  1031.                 ui = `again;
  1032.                 continue;
  1033.             }
  1034.         // make sure the device is a defined virtual disk...
  1035.         boolean success = false;
  1036.         foreach(string target, used_targets, {
  1037.             if (issubstring(device, target)) success = true;
  1038.         });
  1039.         if (!success) {
  1040.             // popup error message with continue/cancel buttons
  1041.             if (!Popup::ContinueCancelHeadline(_("Warning"), _("The Partition Containing Kernel and RAM Disk,
  1042. does not match any configued disks."))) {
  1043.                 ui = `again;
  1044.                 continue;
  1045.             }
  1046.         }
  1047.  
  1048.             if (kernel == nil || kernel == "") {
  1049.                 // popup error message
  1050.                 Report::Error(_("Xen-Enabled Kernel cannot be empty."));
  1051.                 ui = `again;
  1052.                 continue;
  1053.             }
  1054.  
  1055. /*            if (initrd == nil || initrd == "") {
  1056.                 // popup error message
  1057.                 Report::Error(_("RAM Disk cannot be empty."));
  1058.                 s = `again;
  1059.                 continue;
  1060.             }*/
  1061.     
  1062.             VM::SetCustomKernel(true);
  1063.     
  1064.             VM::SetKernelImage(kernel);
  1065.             VM::SetInitrdImage(initrd);
  1066.             VM_Common::root_device = device;
  1067.     
  1068.             VM::SetExtraArgs(bootopts);
  1069.         }
  1070.         // FIXME: add catch for any unknown return values???
  1071.     }
  1072.     return ui;
  1073. }
  1074.  
  1075.  
  1076.  
  1077.     Wizard::OpenNextBackDialog();
  1078.  
  1079.     map aliases = $[
  1080.         "SourceTypeDialog"        : ``(SourceTypeDialog()),
  1081.         "Network_SourceDialog"    : ``(Network_SourceDialog()),
  1082.         "CD_SourceDialog"        : ``(CD_SourceDialog()),
  1083.         "ISO_SourceDialog"        : ``(ISO_SourceDialog()),
  1084.         "FullOptionsDialog"        : ``(FullOptionsDialog()),
  1085.         "BootOptionsDialog"        : ``(BootOptionsDialog())
  1086.     ];
  1087.  
  1088.     map sequence = $[
  1089.         // start differnt workflow for full virtualization mode
  1090.         "ws_start"    : (VM::GetVirtualizationType() == "full") ? "FullOptionsDialog" : ((VM_Common::proposal_type == "install") ? "SourceTypeDialog" : "BootOptionsDialog"),
  1091.         "SourceTypeDialog"    :
  1092.         $[
  1093.             `network_configured        :   "Network_SourceDialog",
  1094.             `network_custom        :   "Network_SourceDialog",
  1095.             `cdrom        :   "CD_SourceDialog",
  1096.             `iso        :   "ISO_SourceDialog",
  1097.             `abort        :   `abort,
  1098.             `next        :   `next
  1099.         ],
  1100.         "Network_SourceDialog"    :
  1101.         $[
  1102.             `abort        :   `abort,
  1103.             `next        :   `next
  1104.         ],
  1105.         "CD_SourceDialog"    :
  1106.         $[
  1107.             `abort        :   `abort,
  1108.             `next        :   `next
  1109.         ],
  1110.         "ISO_SourceDialog"    :
  1111.         $[
  1112.             `abort        :   `abort,
  1113.             `next        :   `next
  1114.         ],
  1115.         "FullOptionsDialog"    :
  1116.         $[
  1117.             `abort        :   `abort,
  1118.             `next        :   `next
  1119.         ],
  1120.         "BootOptionsDialog" :
  1121.         $[
  1122.             `abort        :   `abort,
  1123.             `next        :   `next
  1124.         ]
  1125.         ];
  1126.  
  1127.     symbol ret = Sequencer::Run(aliases, sequence);
  1128.  
  1129.     Wizard::CloseDialog();
  1130.  
  1131.     return ret;
  1132.  
  1133. }
  1134.