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_network.ycp < prev    next >
Text File  |  2006-11-29  |  12KB  |  472 lines

  1. /**
  2.  * Module:    inst_vm_network.ycp
  3.  *
  4.  * Authors:    Ladislav Slezak <lslezak@suse.cz>
  5.  *        Michael G. Fritch <mgfritch@novell.com>
  6.  *
  7.  * Purpose:    Ask user for network settings.
  8.  *
  9.  * $Id: inst_vm_network.ycp 30722 2006-05-05 22:59:43Z mgfritch $
  10.  *
  11.  */
  12.  
  13. {
  14.  
  15. textdomain "vm";
  16.  
  17. import "VM";
  18. import "VM_Common";
  19. import "Wizard";
  20. import "Popup";
  21. import "Report";
  22. import "Label";
  23. import "IP";
  24. import "Sequencer";
  25.  
  26.  
  27. list<map<string, string> > network_conf = VM::GetNetworkConfig();
  28. integer selected_interface = nil;
  29.  
  30.  
  31. define boolean Check_MAC(string mac) ``{
  32.     return regexpmatch(mac, "^[0-9a-fA-F][0-9a-fA-F](:[0-9a-fA-F][0-9a-fA-F]){5}$");
  33. }
  34.  
  35.  
  36. define list<term> CreateInterfaceList(list<map<string, string> > network) {
  37.     list<term> ret = [];
  38.  
  39.     if (network != nil)
  40.     {
  41.         integer num = 0;
  42.  
  43.         foreach(map interface, network, {
  44.             string mac = interface["mac"]:"";
  45.             string bridge = interface["bridge"]:"";
  46.  
  47.             if (mac == "")
  48.             {
  49.             mac = _("Random Address");
  50.             }
  51.  
  52.             if (bridge == "")
  53.             {
  54.             bridge = _("Default Bridge");
  55.             }
  56.  
  57.             ret = add(ret, `item(`id(num), num, mac, bridge));
  58.  
  59.             num = num + 1;
  60.         }
  61.         );
  62.     }
  63.  
  64.     return ret;
  65. }
  66.  
  67.  
  68.  
  69. define map<string,string> InterfaceDialog(string mac, string bridge) ``{
  70.  
  71.     string caption = _("Configure Virtual Network Card");
  72.  
  73.     term contents =
  74.         `MarginBox(1.5, 0.2, 
  75.             `Frame( caption,
  76.                 `MarginBox(1.5, 0.2,
  77.                     `VBox(
  78.                         `TextEntry(`id(`MAC_address), _("&MAC Address"), mac),
  79.                         `VSpacing(1),
  80.                         `TextEntry(`id(`bridge), _("&Bridge Name"), bridge)
  81.                     )
  82.                 )
  83.             )
  84.         );
  85.  
  86.     string help_text = sformat(_("<p><b><big>%1</big></b></p>"), caption);
  87.     help_text = help_text + _("<p>The virtual network card configuration describes how the network card appears to the virtual machine.</p>");
  88.     help_text = help_text + _("<p>By default, a <b>MAC address</b> has been randomly generated for use with this virtual machine when it boots.  A valid <b>MAC address</b> consists of six 2-digit hex numbers, separated by colons.</p>");
  89.     help_text = help_text + _("<p>A virtual network interface can be connected to a bridge configured in the VM Server. If the <b>Bridge Name</b> is left blank, the default bridge will be used.</p>");
  90.  
  91.  
  92.     Wizard::SetContents(caption, contents, help_text, true, true);
  93.  
  94.     // allow only valid characters
  95.     UI::ChangeWidget (`id (`MAC_address), `ValidChars, "0123456789:abcdefABCDEF");
  96.  
  97.     string new_mac = "";
  98.     string new_bridge = "";
  99.  
  100.     symbol ret = nil;
  101.     while (true) {
  102.  
  103.         ret = (symbol)UI::UserInput();
  104.  
  105.         if (ret == `back) {
  106.         break;
  107.         }
  108.         if (ret == `cancel || ret == `abort) {
  109.         if (Popup::ReallyAbort(VM_Common::GetModified())) {
  110.             ret = `abort;
  111.             break;
  112.         }
  113.         }
  114.         else if (ret == `next || ret == `accept || ret == `ok) {
  115.         new_mac = (string) UI::QueryWidget (`id(`MAC_address), `Value);
  116.         new_bridge = (string) UI::QueryWidget (`id(`bridge), `Value);
  117.  
  118.         if (!Check_MAC(new_mac)) {
  119.             // error message
  120.             Report::Error(_("The MAC address entered is not valid."));
  121.             UI::SetFocus(`id(`MAC_address));
  122.             ret = `again;
  123.         }
  124.         ret = `next;
  125.         break;
  126.         }
  127.             else {
  128.         y2error("unexpected retcode: %1", ret);
  129.         continue;
  130.             }
  131.     }
  132.  
  133.     map<string,string> result = $[ "mac" : new_mac, "bridge" : new_bridge, "ui" : tostring(ret) ];
  134.  
  135.     y2debug("result: %1", result);
  136.     return result;
  137. }
  138.  
  139.  
  140.  
  141.  
  142. symbol AddInterface() {
  143.     // generate random MAC for the new interface
  144.     map<string,string> ifc = InterfaceDialog(VM_Common::Propose_MAC_address(sformat("%1", size(network_conf))), "");
  145.     y2milestone("InterfaceDialog: %1", ifc);
  146.     symbol ret = `back;
  147.  
  148.     if (ifc != nil) {
  149.         string retstr = (string)ifc["ui"]:"`back";
  150.         ifc = remove(ifc, "ui");
  151.         if (retstr == "`next" || retstr == "`accept" || retstr == "`ok") {
  152.             network_conf = add(network_conf, ifc);
  153.             y2milestone("added virtual network card %1", ifc);
  154.             ret = `next;
  155.         }
  156.         else if (retstr == "`cancel" || retstr == "`abort") {
  157.             ret = `abort;
  158.         }
  159.     }
  160.  
  161.     return ret;
  162. }
  163.  
  164.  
  165.  
  166. symbol EditInterface() {
  167.  
  168.     map<string,string> ifc = network_conf[selected_interface]:$[];
  169.     ifc = InterfaceDialog(ifc["mac"]:"", ifc["bridge"]:"");
  170.     y2milestone("InterfaceDialog: %1", ifc);
  171.     symbol ret = `back;
  172.  
  173.     if (ifc != nil) {
  174.         string retstr = (string)ifc["ui"]:"`back";
  175.         ifc = remove(ifc, "ui");
  176.         if (retstr == "`next" || retstr == "`accept" || retstr == "`ok") {
  177.             network_conf[selected_interface] = ifc;
  178.             y2milestone("changed virtual network card %1: %2", selected_interface, ifc);
  179.             ret = `next;
  180.         }
  181.         else if (retstr == "`cancel" || retstr == "`abort") {
  182.             ret = `abort;
  183.         }
  184.     }
  185.  
  186.     return ret;
  187.  
  188. }
  189.  
  190.  
  191.  
  192. define void refresh_table(list<map<string, string> > cont) {
  193.     list<term> content = CreateInterfaceList(cont);
  194.     UI::ChangeWidget (`id(`network), `Items, content);
  195. }
  196.  
  197.  
  198.  
  199. define symbol NetworkOverview() {
  200.     // screen title for network options
  201.     string caption = _("Network");
  202.  
  203.     term contents =
  204.     `VBox(
  205.         `VWeight(50, `MarginBox(1.5, 0.5,
  206.             `VBox(
  207.                 `Table(`id(`network), `header(`Right(_("No.")), _("MAC Address"), _("Bridge")), []),
  208.                 `HBox(
  209.                     `PushButton (`id (`add), Label::AddButton()),
  210.                     `PushButton (`id (`edit), Label::EditButton()),
  211.                     `PushButton (`id (`delete), Label::DeleteButton())
  212.                 )
  213.             )
  214.         ))
  215.     );
  216.  
  217.  
  218.     if (VM::GetVirtualizationType() == "para" && VM_Common::proposal_type == "install") {
  219.     contents = add(contents,
  220.         `VWeight(60, `MarginBox(1.5, 0.5,
  221.             `Frame( _("OS Installation Network Settings"),
  222.                 `MarginBox(0.5, 0.5, `VBox(
  223.                     `RadioButtonGroup(`id(`rb_group),
  224.                         `VBox(
  225.                             `Left(`RadioButton(`id(`none), `opt(`notify), _("None"), (!VM_Common::use_dhcp && !VM_Common::use_static))),
  226.                             `Left(`RadioButton(`id(`dhcp), `opt(`notify), _("DHCP"), (VM_Common::use_dhcp))),
  227.                             `Left(`RadioButton(`id(`static), `opt(`notify), _("Static IP"), (!VM_Common::use_dhcp && VM_Common::use_static)))
  228.                         )
  229.                     ),
  230.                     `HBox(
  231.                         `HSpacing(4),
  232.                         `VBox(
  233.                             `TextEntry(`id(`ip), `opt(`hstretch), _("IP"), VM_Common::ip),
  234.                             `TextEntry(`id(`netmask), `opt(`hstretch), _("Netmask"), VM_Common::netmask),
  235.                             `TextEntry(`id(`gateway), `opt(`hstretch), _("Gateway"), VM_Common::gateway)
  236.                         )
  237.                     )
  238.                 ))
  239.             )
  240.         ))
  241.     );
  242.     }
  243.     else if (VM::GetVirtualizationType() == "full") {
  244.     contents = add(contents, 
  245.         `VWeight(20,`VBox(
  246.             `VStretch(),
  247.             `MarginBox(1.5, 0.2,
  248.                 `Frame( _("Virtual Network Card"), `HBox(
  249.                     `MarginBox(1.5, 0.2,
  250.                         `ComboBox(`id(`ne2000), `opt(`hstretch),
  251.                             // combobox label
  252.                             "",/*_("Virtual Network Card"),*/
  253.                             [
  254.                                 // combobox item
  255.                                 `item(`id(0), _("AMD PCnet")),
  256.                                 // combobox item
  257.                                 `item(`id(1), _("NE2000")),
  258.                             ]
  259.                         )
  260.                     )
  261.                 ))
  262.             ),
  263.             `VStretch()
  264.         ))
  265.     );
  266.     }
  267.  
  268.     // help text for network settings (1/2)
  269.     string help_text = sformat(_("<p><b><big>%1</big></b></p>"), caption);
  270.     // help text for network settings (2/2)
  271.     help_text = help_text + _("<p>A virtual machine can have zero or more virtual ethernet network cards. The MAC address is a unique identification of the virtual ethernet network card.</p>");
  272.     if (VM::GetVirtualizationType() == "para" && VM_Common::proposal_type == "install") {
  273.         help_text = help_text + _("<p>The <b>network installation settings</b> are used only during the installation. They are useful when installing from a network installation source.</p>");
  274.     }
  275.     else if (VM::GetVirtualizationType() == "full") {
  276.         help_text = help_text + _("<p>By default, Xen will emulate an <b>AMD PCnet</b> network card for fully virtualized guests. If your operating system does not support that, select <b>NE2000.</b></p>");
  277.     }
  278.  
  279.  
  280.     Wizard::SetContents (caption, contents, help_text, true, true);
  281.     Wizard::SetNextButton(`next, Label::AcceptButton());
  282.     Wizard::SetAbortButton(`abort, Label::CancelButton());
  283.     Wizard::HideBackButton();
  284.  
  285.     refresh_table(network_conf);
  286.  
  287.     if (VM::GetVirtualizationType() == "para" && VM_Common::proposal_type == "install") {
  288.     any rb = UI::QueryWidget(`id(`rb_group), `CurrentButton);
  289.     if (rb == `static) {
  290.         UI::ChangeWidget(`id(`ip), `Enabled, true);
  291.         UI::ChangeWidget(`id(`netmask), `Enabled, true);
  292.         UI::ChangeWidget(`id(`gateway), `Enabled, true);
  293.     }
  294.     else if (rb == `none || rb == `dhcp) {
  295.         UI::ChangeWidget(`id(`ip), `Enabled, false);
  296.         UI::ChangeWidget(`id(`netmask), `Enabled, false);
  297.         UI::ChangeWidget(`id(`gateway), `Enabled, false);
  298.     }
  299.  
  300.     }
  301.  
  302.     if (VM::GetVirtualizationType() == "full") {
  303.     UI::ChangeWidget(`id(`ne2000), `Value, VM::GetNE2000());
  304.     }
  305.  
  306.     symbol ret = nil;
  307.     while (true) {
  308.  
  309.     ret = (symbol) Wizard::UserInput ();
  310.  
  311.     y2milestone("ret=%1", ret);
  312.  
  313.     if (ret == `abort || ret == `cancel) {
  314.         if (Popup::ReallyAbort(VM_Common::GetModified()))
  315.             break;
  316.     }
  317.     else if (ret == `back) {
  318.         break;
  319.     }
  320.     else if (ret == `add) {
  321.         break;
  322.     }
  323.     else if (ret == `edit) {
  324.         selected_interface = (integer) UI::QueryWidget (`id(`network), `CurrentItem);
  325.         if (selected_interface != nil)
  326.         break;
  327.         else {
  328.         y2error("edit: invalid interface selected");
  329.         continue;
  330.         }
  331.     }
  332.     else if (ret == `delete) {
  333.         integer id = (integer) UI::QueryWidget (`id(`network), `CurrentItem);
  334.         if (id != nil) {
  335.         network_conf = remove(network_conf, id);
  336.         refresh_table(network_conf);
  337.         y2milestone("removed virtual network card %1", id);
  338.  
  339.         if (size(network_conf) > id) {
  340.             UI::ChangeWidget(`id(`network), `CurrentItem, id);
  341.         }
  342.         }
  343.         else {
  344.         y2error("delete: invalid interface selected");
  345.         continue;
  346.         }
  347.     }
  348.     else if (ret == `next) {
  349.         VM::SetNetworkConfig(network_conf);
  350.         if (VM::GetVirtualizationType() == "para" && VM_Common::proposal_type == "install") {
  351.         any rb = UI::QueryWidget(`id(`rb_group), `CurrentButton);
  352.         if (rb == `dhcp) {
  353.             VM_Common::use_dhcp = true;
  354.             VM_Common::use_static = false;
  355.         }
  356.         else if (rb == `static) {
  357.             string ip = (string) UI::QueryWidget(`id(`ip), `Value);
  358.             string netmask = (string) UI::QueryWidget(`id(`netmask), `Value);
  359.             string gateway = (string) UI::QueryWidget(`id(`gateway), `Value);
  360.  
  361.             if (ip == nil || ip == "") {
  362.                 Report::Error(_("IP cannot be left empty.
  363. Please, specify an IP."));
  364.                 continue;
  365.             }
  366.             if (netmask == nil || netmask == "") {
  367.                 Report::Error(_("Netmask cannot be left empty.
  368. Please, specify a netmask."));
  369.                 continue;
  370.             }
  371.             if (gateway == nil || gateway == "") {
  372.                 Report::Error(_("Gateway cannot be left empty.
  373. Please, specify a gateway."));
  374.                 continue;
  375.             }
  376.  
  377.             // ensure values are in IPv4 format
  378.             if (!IP::Check(ip)) {
  379.                 Report::Error(_("An invalid IP was specified.\n\n") + IP::Valid4());
  380.                 continue;
  381.             }
  382.             if (!IP::Check(netmask)) {
  383.                 Report::Error(_("An invalid Netmask was specified.\n\n") + IP::Valid4());
  384.                 continue;
  385.             }
  386.             if (!IP::Check(gateway)) {
  387.                 Report::Error(_("An invalid Gateway was specified.\n\n") + IP::Valid4());
  388.                 continue;
  389.             }
  390.  
  391.             VM_Common::ip = ip;
  392.             VM_Common::netmask = netmask;
  393.             VM_Common::gateway = gateway;
  394.             VM_Common::use_dhcp = false;
  395.             VM_Common::use_static = true;
  396.         }
  397.         else { // radio button `none selected
  398.             VM_Common::use_dhcp = false;
  399.             VM_Common::use_static = false;
  400.         }
  401.         }
  402.         else if (VM::GetVirtualizationType() == "full") {
  403.         VM::SetNE2000((integer) UI::QueryWidget (`id(`ne2000), `Value));
  404.         }
  405.         break;
  406.     }
  407.     else if (ret == `static) {
  408.         UI::ChangeWidget(`id(`ip), `Enabled, true);
  409.         UI::ChangeWidget(`id(`netmask), `Enabled, true);
  410.         UI::ChangeWidget(`id(`gateway), `Enabled, true);
  411.     }
  412.     else if (ret == `none || ret == `dhcp) {
  413.         UI::ChangeWidget(`id(`ip), `Enabled, false);
  414.         UI::ChangeWidget(`id(`netmask), `Enabled, false);
  415.         UI::ChangeWidget(`id(`gateway), `Enabled, false);
  416.     }
  417.     else {
  418.         y2error("unexpected retcode: %1", ret);
  419.         continue;
  420.     }
  421.     }
  422.  
  423.     Wizard::SetNextButton(`next, Label::NextButton());
  424.     Wizard::SetAbortButton(`abort, Label::AbortButton());
  425.     Wizard::RestoreBackButton();
  426.  
  427.     return ret;
  428. }
  429.  
  430.  
  431.  
  432.  
  433. Wizard::OpenNextBackDialog();
  434.  
  435. map aliases = $[
  436.         "NetworkOverview"    : ``(NetworkOverview()),
  437.         "AddInterface"    : ``(AddInterface()),
  438.         "EditInterface"    : ``(EditInterface()),
  439.     ];
  440.  
  441. map sequence = $[
  442.         "ws_start"    : "NetworkOverview",
  443.         "NetworkOverview"    :
  444.         $[
  445.             `next        :    `next,
  446.             `add        :    "AddInterface",
  447.             `edit        :    "EditInterface",
  448.             `abort        :    `abort
  449.         ],
  450.         "AddInterface"    :
  451.         $[
  452.             `next        :    "NetworkOverview",
  453.             `abort        :    `abort
  454.         ],
  455.         "EditInterface"    :
  456.         $[
  457.             `next        :    "NetworkOverview",
  458.             `abort        :    `abort
  459.         ],
  460.     ];
  461.  
  462.  
  463. symbol ret = Sequencer::Run(aliases, sequence);
  464.  
  465. Wizard::CloseDialog();
  466.  
  467. return ret;
  468.  
  469.  
  470. /* EOF */
  471. }
  472.