ACC SHELL
{
/**
*
* Authors: Lukas Ocilka <locilka@suse.cz>
*
* Purpose: This script allows to setup network in first
* stage of installation.
*
* See More: FATE #301967
*
* $Id: inst_network_setup.ycp 57028 2009-04-29 10:58:09Z lslezak $
*
*/
textdomain "installation";
import "Wizard";
import "String";
import "GetInstArgs";
import "IP";
import "Label";
import "Netmask";
import "NetworkService";
import "Popup";
import "Report";
import "Hostname";
import "Sequencer";
import "Progress";
import "FileUtils";
import "Mode";
import "Stage";
import "Progress";
import "Proxy";
import "Linuxrc";
import "Internet";
/* Variables --> */
symbol default_ret = GetInstArgs::going_back() ? `back : `next;
boolean enable_back = GetInstArgs::enable_back();
boolean enable_next = GetInstArgs::enable_next();
boolean enable_back_in_netsetup = true;
/* Currently probed network cards */
list <map <string, any> > lan_cards = nil;
/* Currently available network cards prepared for table representation */
list <term> table_items = [];
/* Flag that network configuration is not needed */
boolean some_card_has_ip = false;
/*
* Map of maps for each network device $["eth0" : $["interface_name":"HTML Summary"]]
* containing the hardware information.
*/
map <string, map <string, string> > hardware_information = $[];
/* Netork setting used in Write function */
map <string, any> network_settings = $[];
map <string, any> default_network_settings = $["setup_type":"dhcp"];
/* <-- Variables */
/* Functions --> */
string CreateRichTextHWSummary (map <string, any> & device_map) {
string ret = "";
if (device_map["device"]:"" != "") {
ret = ret + (ret != "" ? "<br>":"") +
// TRANSLATORS: hardware information - HTML summary text
// %1 is replaced with a variable network_device
sformat(_("Network Device: %1"), device_map["device"]:"");
}
ret = ret + (ret != "" ? "<br>":"") +
// TRANSLATORS: hardware information - HTML summary text
// %1 is replaced with "Wireless" or "Wired"
// See #nt1 below
sformat(_("Network type: %1"),
((boolean) device_map["wlan"]:false == true ?
// TRANSLATORS: Describes a "Network type"
// see #nt1 above
_("Wireless")
:
// TRANSLATORS: Describes a "Network type"
// see #nt1 above
_("Wired")
)
);
if (device_map["model"]:"" != "") {
ret = ret + (ret != "" ? "<br>":"") +
// TRANSLATORS: hardware information - HTML summary text
// %1 is replaced with a variable device_model
sformat(_("Model: %1"), device_map["model"]:"");
}
if (device_map["resource","hwaddr",0,"addr"]:"" != "") {
ret = ret + (ret != "" ? "<br>":"") +
// TRANSLATORS: hardware information - HTML summary text
// %1 is replaced with a variable mac_address
sformat(_("MAC Address: %1"), device_map["resource","hwaddr",0,"addr"]:"");
}
if (device_map["vendor"]:"" != "") {
ret = ret + (ret != "" ? "<br>":"") +
// TRANSLATORS: hardware information - HTML summary text
// %1 is replaced with a variable hardware_vendor
sformat(_("Hardware Vendor: %1"), device_map["vendor"]:"");
}
string device_name = device_map["dev_name"]:"";
if (hardware_information[device_name,"link_status"]:nil != nil) {
ret = ret + (ret != "" ? "<br>":"") +
sformat(
// TRANSLATORS: hardware information - HTML summary text
// %1 is either "Connected" or "Disconnected" (*1)
_("Link is: %1"),
(hardware_information[device_name,"link_status"]:nil == "1" ?
// TRANSLATORS: hardware information, see *1
_("Connected")
:
// TRANSLATORS: hardware information, see *1
_("Disconnected")
)
);
}
return ret;
}
void ReadProxySettingsFromSystem () {
// Read proxy settings and adjust the default settings
boolean progress_orig = Progress::set (false);
Proxy::Read();
Progress::set (progress_orig);
map default_proxy_settings = Proxy::Export();
map log_settings = default_proxy_settings;
if (log_settings["proxy_user"]:"" != "") log_settings["proxy_user"] = "***hidden***";
if (log_settings["proxy_password"]:"" != "") log_settings["proxy_password"] = "***hidden***";
y2milestone ("Default proxy settings: %1", log_settings);
default_network_settings["use_proxy"] = default_proxy_settings["enabled"]:false;
// Examle: "http://cache.example.com:3128/"
string http_proxy = default_proxy_settings["http_proxy"]:"";
if (regexpmatch (http_proxy, "/$"))
http_proxy = regexpsub (http_proxy, "(.*)/$", "\\1");
if (regexpmatch (http_proxy, "^[hH][tT][tT][pP]:/+"))
http_proxy = regexpsub (http_proxy, "^[hH][tT][tT][pP]:/+(.*)", "\\1");
list <string> http_proxy_settings = splitstring (http_proxy, ":");
y2milestone ("Using proxy values: %1", http_proxy_settings);
default_network_settings["proxy_server"] = http_proxy_settings[0]:"";
default_network_settings["proxy_port"] = http_proxy_settings[1]:"";
default_network_settings["proxy_user"] = default_proxy_settings["proxy_user"]:"";
default_network_settings["proxy_password"] = default_proxy_settings["proxy_password"]:"";
}
symbol ProbeAndGetNetworkCards () {
Wizard::SetContents (
// TRANSLATORS: dialog caption
_("Network Setup Wizard: Probing Hardware..."),
`VBox (
// TRANSLATORS: dialog busy message
`Label (_("Probing network cards..."))
),
// TRANSLATORS: dialog help
_("Please wait while the installation is probing the network cards..."),
false,
false
);
Wizard::SetTitleIcon ("yast-controller");
some_card_has_ip = false;
lan_cards = (list <map <string, any> >) SCR::Read (.probe.netcard);
table_items = [];
foreach (map <string, any> one_netcard, lan_cards, {
y2milestone ("Found netcard: %1", one_netcard);
string card_name = one_netcard["model"]:one_netcard["device"]:_("Unknown Network Card");
if (size (card_name) > 43) card_name = substring (card_name, 0, 40) + "...";
string device_name = (string) one_netcard["dev_name"]:nil;
if (device_name == nil) {
y2error ("Cannot obtain \"dev_name\" from %1. Netcard will not be used.", one_netcard);
return;
}
table_items = add (
table_items,
`item (`id (device_name), card_name, device_name)
);
// empty map
hardware_information[device_name] = $[];
// Link status
if (one_netcard["resource","link",0,"state"]:nil != nil) {
hardware_information[device_name,"link_status"] = (one_netcard["resource","link",0,"state"]:false ? "1":"0");
}
// hardware information later used in UI
string hwinfo_richtext = CreateRichTextHWSummary (one_netcard);
if (hwinfo_richtext != nil && hwinfo_richtext != "")
hardware_information[device_name,"richtext"] = hwinfo_richtext;
hardware_information[device_name,"module"] = one_netcard["driver_module"]:"";
hardware_information[device_name,"unique_key"] = one_netcard["unique_key"]:"";
hardware_information[device_name,"hward"] = one_netcard["resource","hwaddr",0,"addr"]:"";
y2milestone ("Found network device: '%1' %2", device_name, card_name);
});
ReadProxySettingsFromSystem();
// Use the default values
if (network_settings == nil || network_settings == $[]) {
network_settings = default_network_settings;
}
if (size (table_items) == 0) return `abort;
return `next;
}
void FillUpHardwareInformationWidget () {
string current_netcard =
(string) UI::QueryWidget (`id ("netcard_selection"), `CurrentItem);
UI::ChangeWidget (
`id ("hardware_information"),
// TRANSLATORS: hardware information widget content (a fallback)
`Value, hardware_information[current_netcard,"richtext"]:_("No additional information")
);
}
void MarkAlreadySelectedDevice () {
// Pre-select the fist connected device
// if no device is already selected
if (network_settings["network_device"]:nil == nil) {
foreach (map <string, any> one_netcard, lan_cards, {
string device_name = one_netcard["dev_name"]:"";
// First connected device
if (hardware_information[device_name,"link_status"]:"X" == "1") {
UI::ChangeWidget (
`id ("netcard_selection"),
`CurrentItem,
device_name
);
break;
}
});
return;
}
UI::ChangeWidget (
`id ("netcard_selection"),
`CurrentItem,
network_settings["network_device"]:""
);
}
boolean CheckSelectedNetworkCard (string selected_netcard) {
// Checking whether any netcard is selected
if (selected_netcard == nil || selected_netcard == "") {
// TRANSLATORS: pop-up error message
Report::Error (_("No network card has been selected.
Please select a network card to configure it later."));
return false;
// Checking whether the netcard link is active
} else if (hardware_information[selected_netcard,"link_status"]:nil == "0") {
if (! Report::AnyQuestion (
// TRANSLATORS: popup dialog caption
_("Warning"),
sformat (
// TRANSLATORS: popup dialog question
// %1 is replaced with a network device string
_("The link of the selected interface %1 is disconnected.
It needs to be connected for a proper network configuration.
Are you sure you want to use it?"),
selected_netcard
),
// TRANSLATORS: popup dialog button
_("&Yes, Use It"),
Label::NoButton(),
`no_button
)) {
y2milestone ("User decided not to use disconnected '%1'", selected_netcard);
return false;
} else {
y2warning ("User decided to use '%1' despite reported as inactive", selected_netcard);
}
}
return true;
}
symbol NetworkCardDialog () {
enable_back_in_netsetup = true;
if (size (table_items) == 1) {
network_settings["network_device"] = tostring (table_items[0,0,0]:"");
y2milestone ("Only one network inteface, selecting %1", network_settings["network_device"]:nil);
enable_back_in_netsetup = false;
return `next;
}
Wizard::SetContentsButtons (
// TRANSLATORS: dialog caption
_("Network Setup"),
`VBox (
`Left (`Label (_("Please, select a network card to be configured"))),
`VWeight (3, `Table (
`id ("netcard_selection"),
`opt (`notify, `immediate),
`header (
_("Network Card"),
_("Device")
),
table_items
)),
`VSpacing (1),
// TRANSLATORS: Rich text widget label
`Left (`Label (_("Hardware Information of the Selected Network Card"))),
`VWeight (2, `RichText (
`id ("hardware_information"),
""
))
),
// TRANSLATORS: dialog help 1/3
_("<p>Here you can configure your network cards to be used immediately.</p>") +
// TRANSLATORS: dialog help 2/3
_("<p>If you do not need a network connection now,
you can safely skip the configuration.</p>") +
// TRANSLATORS: dialog help 3/3
_("<p>To configure a network card, select it from the list
and click the <b>Next</b> button.
Otherwise,click<b>Cancel</b>.</p>"),
Label::BackButton(),
Label::NextButton()
);
Wizard::DisableBackButton();
Wizard::EnableAbortButton();
Wizard::EnableNextButton();
Wizard::SetAbortButton(`abort, Label::CancelButton());
Wizard::SetTitleIcon ("yast-controller");
MarkAlreadySelectedDevice();
FillUpHardwareInformationWidget();
any user_input = nil;
symbol dialog_ret = `next;
while (true) {
user_input = UI::UserInput();
if (user_input == "netcard_selection") {
FillUpHardwareInformationWidget();
continue;
} else if (user_input == `next) {
network_settings["network_device"] = (string) UI::QueryWidget (
`id ("netcard_selection"),
`CurrentItem
);
if (! CheckSelectedNetworkCard (network_settings["network_device"]:""))
continue;
dialog_ret = `next;
break;
} else if (user_input == `cancel) {
dialog_ret = `abort;
break;
} else if (user_input == `abort) {
dialog_ret = `abort;
break;
} else if (user_input == `back) {
dialog_ret = `back;
break;
} else {
y2milestone ("Uknown user input: %1", user_input);
}
}
return dialog_ret;
}
void AdjustNetworkWidgets (string default_button) {
UI::ChangeWidget (`id ("network_type"), `CurrentButton, default_button);
UI::ChangeWidget (`id ("static_addr_frame"), `Enabled, (default_button != "dhcp"));
}
void SetValidCharsForNetworkWidgets () {
foreach (string id, ["ip_address", "netmask", "gateway", "dns_server"], {
UI::ChangeWidget (`id(id), `ValidChars, IP::ValidChars4);
});
}
boolean ValidateStaticSetupSettings () {
// ["ip_address", "netmask", "gateway", "dns_server"]
string ip_address = (string) UI::QueryWidget (`id ("ip_address"), `Value);
if (ip_address == "" || regexpmatch (ip_address, "^[ \t\n]+$")) {
UI::SetFocus (`id ("ip_address"));
// TRANSLATORS: error message
Report::Error (_("IP address cannot be empty."));
return false;
} else if (! IP::Check4 (ip_address) && ! IP::Check6 (ip_address)) {
UI::SetFocus (`id ("ip_address"));
Report::Error (sformat (
// TRANSLATORS: Error message, %1 is replaced with invalid IP address
_("'%1' is an invalid IP address."),
ip_address
) + "\n\n" + IP::Valid4());
return false;
}
string netmask = (string) UI::QueryWidget (`id ("netmask"), `Value);
if (netmask == "" || regexpmatch (netmask, "^[ \t\n]+$")) {
UI::SetFocus (`id ("netmask"));
// TRANSLATORS: error message
Report::Error (_("Netmask cannot be empty."));
return false;
} else if (! Netmask::Check4 (netmask)) {
UI::SetFocus (`id ("netmask"));
Report::Error (sformat (
// TRANSLATORS: Error message, %1 is replaced with invalid netmask
_("'%1' is an invalid netmask."),
netmask
));
return false;
}
string gateway = (string) UI::QueryWidget (`id ("gateway"), `Value);
if (gateway == "" || regexpmatch (gateway, "^[ \t\n]+$")) {
UI::SetFocus (`id ("gateway"));
// TRANSLATORS: error message
Report::Error (_("Gateway IP address cannot be empty."));
return false;
} else if (! IP::Check4 (gateway) && ! IP::Check6 (gateway)) {
UI::SetFocus (`id ("gateway"));
Report::Error (sformat (
// TRANSLATORS: Error message, %1 is replaced with invalid IP address
_("'%1' is an invalid IP address of the gateway."),
gateway
) + "\n\n" + IP::Valid4());
return false;
}
string dns_server = (string) UI::QueryWidget (`id ("dns_server"), `Value);
if (dns_server == "" || regexpmatch (dns_server, "^[ \t\n]+$")) {
UI::SetFocus (`id ("dns_server"));
// TRANSLATORS: error message
Report::Error (_("DNS server IP address cannot be empty."));
return false;
} else if (! IP::Check4 (dns_server) && ! IP::Check6 (dns_server)) {
UI::SetFocus (`id ("dns_server"));
Report::Error (sformat (
// TRANSLATORS: Error message, %1 is replaced with invalid IP address
_("'%1' is an invalid IP address of the DNS server."),
dns_server
) + "\n\n" + IP::Valid4());
return false;
}
return true;
}
string GetProxyServerFromURL (string proxy_server) {
y2milestone ("Entered proxy server: %1", proxy_server);
if (regexpmatch (proxy_server, ".*[hH][tT][tT][pP]://"))
proxy_server = regexpsub (proxy_server, ".*[hH][tT][tT][pP]://(.*)", "\\1");
if (regexpmatch (proxy_server, "/+$"))
proxy_server = regexpsub (proxy_server, "(.*)/+", "\\1");
y2milestone ("Tested proxy server: %1", proxy_server);
return proxy_server;
}
boolean ValidateProxySettings () {
// ["proxy_server", "proxy_port"]
string proxy_server = (string) UI::QueryWidget (`id ("proxy_server"), `Value);
proxy_server = GetProxyServerFromURL (proxy_server);
if (proxy_server == "" || regexpmatch (proxy_server, "^[ \t\n]+$")) {
UI::SetFocus (`id ("proxy_server"));
// TRANSLATORS: error message
Report::Error (_("Proxy server name or IP address must be set."));
return false;
} else if (! IP::Check4 (proxy_server) && ! IP::Check6 (proxy_server) && ! Hostname::CheckFQ (proxy_server)) {
UI::SetFocus (`id ("proxy_server"));
Report::Error (sformat (
// TRANSLATORS: Error message, %1 is replaced with invalid IP address
_("'%1' is an invalid IP address or invalid hostname
of a proxy server."),
proxy_server
) + "\n\n" + IP::Valid4());
return false;
}
string proxy_port = (string) UI::QueryWidget (`id ("proxy_port"), `Value);
// empty
if (proxy_port == "" || regexpmatch (proxy_port, "^[ \t\n]+$")) {
UI::SetFocus (`id ("proxy_port"));
// TRANSLATORS: error message
Report::Error (_("Proxy port must be set."));
return false;
// not matching 'number' format
} else if (! regexpmatch (proxy_port, "^[0123456789]+$")) {
UI::SetFocus (`id ("proxy_port"));
Report::Error (sformat (
// TRANSLATORS: Error message, %1 is replaced with invalid IP address
_("'%1' is an invalid proxy port number.
Port number must be between 1 and 65535 inclusive."),
proxy_port
));
return false;
// a number
} else {
integer port_nr = tointeger (proxy_port);
// but wrong number
if (port_nr < 1 || port_nr > 65535) {
UI::SetFocus (`id ("proxy_port"));
Report::Error (sformat (
// TRANSLATORS: Error message, %1 is replaced with invalid IP address
_("'%1' is an invalid proxy port number.
Port number must be between 1 and 65535 inclusive."),
proxy_port
));
return false;
}
}
return true;
}
boolean ValidateNetworkSettings () {
// only static setup needs to check these settings
string network_setup_type = (string) UI::QueryWidget (`id ("network_type"), `CurrentButton);
if (network_setup_type == "static" && ! ValidateStaticSetupSettings ()) {
return false;
}
boolean use_proxy = (boolean) UI::QueryWidget (`id ("use_proxy"), `Value);
if (use_proxy && ! ValidateProxySettings ()) {
return false;
}
return true;
}
void StoreNetworkSettingsMap () {
// Network settings
string network_setup_type = (string) UI::QueryWidget (`id ("network_type"), `CurrentButton);
if (network_setup_type == "static") {
network_settings["setup_type"] = "static";
} else if (network_setup_type == "dhcp") {
network_settings["setup_type"] = "dhcp";
} else {
y2error ("Unknown network setup '%1'", network_setup_type);
}
foreach (string widget_id, ["ip_address", "netmask", "gateway", "dns_server"], {
network_settings[widget_id] = (string) UI::QueryWidget (`id (widget_id), `Value);
});
// Proxy settings
boolean use_proxy = (boolean) UI::QueryWidget (`id ("use_proxy"), `Value);
if (use_proxy) {
network_settings["use_proxy"] = true;
foreach (string widget_id, ["proxy_server", "proxy_port", "proxy_user", "proxy_password"], {
network_settings[widget_id] = (string) UI::QueryWidget (`id (widget_id), `Value);
});
network_settings["proxy_server"] = GetProxyServerFromURL (network_settings["proxy_server"]:"");
}
}
void FillUpNetworkSettings () {
AdjustNetworkWidgets (network_settings["setup_type"]:"");
foreach (string widget_id, [
"ip_address", "netmask", "gateway", "dns_server",
"proxy_server", "proxy_port", "proxy_user", "proxy_password"
], {
if (network_settings[widget_id]:nil != nil)
UI::ChangeWidget (`id (widget_id), `Value, network_settings[widget_id]:"");
});
UI::ChangeWidget (`id ("use_proxy"), `Value, (network_settings["use_proxy"]:false == true));
}
symbol NetworkSetupDialog () {
// centered & aligned dialog
// see bugzilla #295043
term netsetup_dialog =
`VBox (
`VStretch(),
`Left (`Label (sformat(
// TRANSLATORS: dialog label, %1 is replaced with a selected network device name, e.g, eth3
// See *2
_("Please, select your network setup type for %1"),
// TRANSLATORS: a fallback card name for *2
network_settings["network_device"]:_("Unknown Network Card")
))),
`RadioButtonGroup (
`id ("network_type"),
`VBox (
`Left (`RadioButton (`id ("dhcp"), `opt(`notify), _("Automatic Address Setup (via &DHCP)"))),
`Left (`RadioButton (`id ("static"), `opt(`notify), _("&Static Address Setup")))
)
),
`VSpacing (1),
`Left (`HBox (
`HSpacing (4),
`HSquash (`Frame (
`id ("static_addr_frame"),
_("Static Address Settings"),
`VBox (
`Left(`HBox (
`HSquash (`MinWidth (15, `InputField (`id ("ip_address"), _("&IP Address")))),
`HSpacing (0.5),
`HSquash (`MinWidth (15, `InputField (`id ("netmask"), _("Net&mask"))))
)),
`Left(`HBox (
`HSquash (`MinWidth (15, `InputField (`id ("gateway"), _("Default &Gateway IP")))),
`HSpacing (0.5),
`HSquash (`MinWidth (15, `InputField (`id ("dns_server"), _("D&NS Server IP"))))
))
)
))
)),
`VSpacing (2),
`VSquash (
`HBox (
`HSpacing (4),
`Left (`CheckBoxFrame (
`id ("use_proxy"),
_("&Use Proxy for Accessing the Internet"),
false,
`VBox (
`Left (`HBox (
`HSquash (`MinWidth (42, `InputField (`id ("proxy_server"), _("&HTTP Proxy Server"), "http://"))),
`HSpacing (0.5),
`HSquash (`MinWidth (6, `ComboBox (`id ("proxy_port"), `opt (`editable), _("&Port"), [ "", "3128", "8080" ])))
)),
`Left (`HBox (
`HSquash (`MinWidth (14, `InputField (`id ("proxy_user"), _("Us&er (Optional)")))),
`HSpacing (0.5),
`HSquash (`MinWidth (14, `Password (`id ("proxy_password"), _("Pass&word (Optional)"))))
))
)
))
)
),
`VStretch()
);
Wizard::SetContentsButtons (
// TRANSLATORS: dialog caption
_("Network Setup"),
`HBox (
`HStretch(),
netsetup_dialog,
`HStretch()
),
// TRANSLATORS: dialog help 1/2
_("<p><big><b>Network Setup</b></big>
<br>Here you can configure your network card.
Select either DHCP or static setup. DHCP fits for most cases.
For details contact your Internet provider or your network
administrator.</p>") +
// TRANSLATORS: dialog help 2/2
_("<p><big><b>Proxy</b></big>
<br>Proxy is a server-based cache for accessing the web.
In most cases, if you have a direct connection to the Internet,
it doesn't need to be used.</p>"),
Label::BackButton(),
Label::OKButton()
);
if (enable_back_in_netsetup) {
Wizard::EnableBackButton();
} else {
Wizard::DisableBackButton();
}
Wizard::EnableAbortButton();
Wizard::EnableNextButton();
Wizard::SetAbortButton(`cancel, Label::CancelButton());
Wizard::SetTitleIcon ("yast-network");
SetValidCharsForNetworkWidgets ();
// use the default settings when not yet set
if (network_settings == $[] || network_settings == nil) {
network_settings = default_network_settings;
}
FillUpNetworkSettings();
any user_input = nil;
symbol dialog_ret = `next;
while (true) {
user_input = UI::UserInput();
if (user_input == `cancel) {
dialog_ret = `abort;
break;
} else if (user_input == `back) {
dialog_ret = `back;
break;
} else if (user_input == "dhcp") {
AdjustNetworkWidgets ("dhcp");
} else if (user_input == "static") {
AdjustNetworkWidgets ("static");
} else if (user_input == `next) {
if (ValidateNetworkSettings()) {
dialog_ret = `next;
StoreNetworkSettingsMap();
break;
}
} else {
y2error ("Unknown ret: %1", user_input);
}
}
return dialog_ret;
}
boolean FlushAllIPSettings () {
foreach (string netdevice, map hwi, hardware_information, {
string cmd = sformat ("/sbin/ip address flush '%1'", netdevice);
map run_cmd = (map) SCR::Execute (.target.bash_output, cmd);
y2milestone ("Running %1 returned %2", cmd, run_cmd);
});
// Bugzilla #308577
// All local dhcpcd clients are shut down
Internet::ShutdownAllLocalDHCPClients();
return true;
}
boolean Action_AdjustDHCPNetworkSetup () {
FlushAllIPSettings();
string cmd = sformat ("/sbin/dhcpcd '%1'", String::Quote (network_settings["network_device"]:""));
map run_cmd = (map) WFM::Execute (.local.bash_output, cmd);
y2milestone ("Running %1 returned %2", cmd, run_cmd);
if (run_cmd["exit"]:-1 != 0) {
return false;
}
return true;
}
void ReportMoreErrorInformationIfPossible (string command, map command_run, string popup_headline) {
string errors = "";
if (command_run["stdout"]:"" != "") {
errors = (errors != "" ? "\n":"") + errors + command_run["stdout"]:"";
}
if (command_run["stderr"]:"" != "") {
errors = (errors != "" ? "\n":"") + errors + command_run["stderr"]:"";
}
if (errors != "") {
Popup::LongText (
// TRANSLATORS: error popup headline
popup_headline,
`MinSize (65,7, `RichText (sformat (
// TRANSLATORS: error popup content (HTML)
// %1 is replaced with a bash command
// %2 is replaced with (possibly multiline) error output of the command
_("<p>Command: <tt>%1</tt> has failed.</p>
<p>The output of the command was:
<pre>%2</pre></p>"),
command,
errors
))),
30, 7
);
}
}
boolean Action_AdjustStaticNetworkSetup () {
// ["ip_address", "netmask", "gateway", "dns_server"]
string network_device = network_settings["network_device"]:"";
string ip_address = network_settings["ip_address"]:"";
string netmask = network_settings["netmask"]:"";
// convert "255.255.240.0" type to bits
if (! regexpmatch (netmask, "^[0123456789]+$")) {
netmask = tostring (Netmask::ToBits (netmask));
}
string default_gateway = network_settings["gateway"]:"";
string dns_server = network_settings["dns_server"]:"";
// Wake up the link
string cmd = sformat (
"/sbin/ip link set '%1' up",
String::Quote (network_device)
);
map run_cmd = (map) SCR::Execute (.target.bash_output, cmd);
y2milestone ("Running %1 returned %2", cmd, run_cmd);
if (run_cmd["exit"]:-1 != 0) {
// TRANSLATORS: popup hedline
ReportMoreErrorInformationIfPossible (cmd, run_cmd, _("Setting up Network Failed"));
return false;
}
FlushAllIPSettings();
// Set the IP
cmd = sformat (
"/sbin/ip address add '%1/%2' brd + dev '%3'",
String::Quote (ip_address),
String::Quote (netmask),
String::Quote (network_device)
);
run_cmd = (map) SCR::Execute (.target.bash_output, cmd);
y2milestone ("Running %1 returned %2", cmd, run_cmd);
if (run_cmd["exit"]:-1 != 0) {
// TRANSLATORS: popup headline
ReportMoreErrorInformationIfPossible (cmd, run_cmd, _("Setting up Network Failed"));
return false;
}
// Set the default gateway
cmd = sformat (
"/sbin/ip route add default via '%1'",
String::Quote (default_gateway)
);
run_cmd = (map) SCR::Execute (.target.bash_output, cmd);
y2milestone ("Running %1 returned %2", cmd, run_cmd);
if (run_cmd["exit"]:-1 != 0) {
// TRANSLATORS: popup headline
ReportMoreErrorInformationIfPossible (cmd, run_cmd, _("Setting up Network Failed"));
return false;
}
// Write resolv conf
if (! Mode::normal()) {
string resolv_file = "/etc/resolv.conf";
string resolv_conf = sformat ("nameserver %1\n", dns_server);
boolean success = (boolean) SCR::Write (.target.string, resolv_file, resolv_conf);
if (! success) {
y2error ("Cannot write into %1 file", resolv_file);
return false;
}
}
return true;
}
// Adjusts environment variables via new builtin 'setenv'
void SetEnvironmentVariables (map <string, any> env_proxy_variables) {
// map <string, any> env_proxy_variables = $[
// "http_proxy" : proxy_server,
// "https_proxy" : proxy_server,
// "ftp_proxy" : proxy_server,
// "proxy_user" : proxy_user,
// "proxy_password" : proxy_pass,
// ];
setenv ("http_proxy", env_proxy_variables["http_proxy"]:"");
setenv ("HTTPS_PROXY", env_proxy_variables["https_proxy"]:"");
setenv ("FTP_PROXY", env_proxy_variables["ftp_proxy"]:"");
setenv ("NO_PROXY", "localhost, 127.0.0.1");
}
boolean Action_ProxySetup () {
string tmp_sysconfig_dir = "/tmp/first_stage_network_setup/sysconfig/";
string sysconfig_file = "/etc/sysconfig/proxy";
string curlrc_file = "/root/.curlrc";
if (! FileUtils::Exists (curlrc_file)) {
y2milestone (
"Creating file %1 returned: %2",
curlrc_file,
SCR::Execute (.target.bash, sformat ("touch '%1'", String::Quote (curlrc_file)))
);
// symlink the correct location of the conf-file
// $HOME directory might be '/' in inst-sys
y2milestone (
"Creating .curlrc symlink returned: %1",
SCR::Execute (.target.bash, sformat ("ln --symbolic --force '%1' '/.curlrc'", String::Quote (curlrc_file)))
);
}
string wgetrc_file = "/root/.wgetrc";
if (! FileUtils::Exists (wgetrc_file)) {
y2milestone (
"Creating file %1 returned: %2",
wgetrc_file,
SCR::Execute (.target.bash, sformat ("touch '%1'", String::Quote (wgetrc_file)))
);
// symlink the correct location of the conf-file
// $HOME directory might be '/' in inst-sys
y2milestone (
"Creating .wgetrc symlink returned: %1",
SCR::Execute (.target.bash, sformat ("ln --symbolic --force '%1' '/.wgetrc'", String::Quote (wgetrc_file)))
);
}
if (Stage::initial()) {
// Flush the cache if needed
// file will be changed
SCR::Write (.sysconfig.proxy, nil);
SCR::Write (.root.curlrc, nil);
SCR::Write (.root.wgetrc, nil);
// Creates temporary directory
// Cerates 'proxy' file there
// Merges the 'proxy' file to the current inst-sys
string cmd = sformat ("mkdir -p '%1' &&
touch '%1proxy' &&
/sbin/adddir '%1' '/etc/sysconfig/'", String::Quote (tmp_sysconfig_dir));
map cmd_run = (map) SCR::Execute (.target.bash_output, cmd);
if (cmd_run["exit"]:-1 != 0) {
y2error ("Command %1 failed with %2", cmd, cmd_run);
// TRANSLATORS: popup error message
Report::Error (_("A failure occurred during preparing
the installation system for writing the proxy configuration."));
return false;
}
// File has been changed, reread proxy settings
boolean progress_orig = Progress::set (false);
Proxy::Read();
Progress::set (progress_orig);
}
string proxy_server = sformat (
"http://%1:%2/",
network_settings["proxy_server"]:"",
network_settings["proxy_port"]:""
);
string proxy_user = network_settings["proxy_user"]:"";
string proxy_pass = network_settings["proxy_password"]:"";
map <string, any> import_proxy = $[
"http_proxy" : proxy_server,
"https_proxy" : proxy_server,
"ftp_proxy" : proxy_server,
"proxy_user" : proxy_user,
"proxy_password" : proxy_pass,
];
if (network_settings["use_proxy"]:nil == true) {
import_proxy["enabled"] = true;
} else {
import_proxy["enabled"] = false;
}
Proxy::Import (import_proxy);
boolean progress_orig = Progress::set (false);
Proxy::Write();
Progress::set (progress_orig);
// Bugzilla #305163
SetEnvironmentVariables (import_proxy);
return true;
}
boolean WriteInstallInfEntry (string inst_inf_entry, string value) {
// Entry name must be set
if (inst_inf_entry == "" || inst_inf_entry == nil) {
y2error ("No entry name defined");
return false;
}
// Value must be set
if (value == "" || value == nil) {
y2warning ("Value for '%1' is '%2'", inst_inf_entry, value);
// Can contain username/passowrd
} else {
y2debug ("Writing %1=%2", inst_inf_entry, value);
}
return SCR::Write (add (.etc.install_inf, inst_inf_entry), value);
}
/**
* Writes network setings to the install.inf file.
*/
boolean Action_WriteInstallInf () {
string inf_filename = "/etc/install.inf";
if (! Stage::initial()) {
y2milestone ("Not an inst-sys, skipping writing %1", inf_filename);
return true;
}
if (! FileUtils::Exists (inf_filename)) {
y2error ("File %1 is missing!", inf_filename);
return false;
}
// These variables are already present in the install.inf
list <string> already_used_variables = SCR::Dir (.etc.install_inf);
list <string> network_variables = [
"NetConfig", "IP", "Netmask", "Netdevice", "Gateway", "Nameserver",
"HWAddr", "Alias", "NetUniqueID", "Broadcast", "Hostname",
];
// Remove all network-related settings
foreach (string inf_var, network_variables, {
if (contains (already_used_variables, inf_var)) {
y2milestone ("Removing %1 from install.inf", inf_var);
SCR::Write (add(.etc.install_inf, inf_var), nil);
}
});
// Write settings into the install.inf
string netdevice = network_settings["network_device"]:"";
WriteInstallInfEntry ("Netdevice", netdevice);
// DHCP setup type
if (network_settings["setup_type"]:nil == "dhcp") {
WriteInstallInfEntry ("NetConfig", "dhcp");
// Static setup type
} else if (network_settings["setup_type"]:nil == "static") {
WriteInstallInfEntry ("NetConfig", "static");
WriteInstallInfEntry ("IP", network_settings["ip_address"]:"");
WriteInstallInfEntry ("Hostname", network_settings["ip_address"]:"");
string netmask = network_settings["netmask"]:"";
// If netmask is defined as a number of bits, convert it
if (regexpmatch (netmask, "^[0123456789]+$")) {
netmask = IP::ToString (tointeger (netmask));
y2milestone ("Converted netmask from %1 to %2", network_settings["netmask"]:"", netmask);
}
WriteInstallInfEntry ("Netmask", netmask);
WriteInstallInfEntry (
"Broadcast",
IP::ComputeBroadcast (network_settings["ip_address"]:"", network_settings["netmask"]:"")
);
WriteInstallInfEntry ("Gateway", network_settings["gateway"]:"");
WriteInstallInfEntry ("Nameserver", network_settings["dns_server"]:"");
// Unknown setup type
} else {
y2error ("Unknown netsetup type %1, using 'dhcp'", network_settings["setup_type"]:nil);
WriteInstallInfEntry ("NetConfig", "dhcp");
}
// Write also hardware information
WriteInstallInfEntry ("Alias", hardware_information[netdevice,"module"]:"");
WriteInstallInfEntry ("NetUniqueID", hardware_information[netdevice,"unique_key"]:"");
WriteInstallInfEntry ("HWAddr", hardware_information[netdevice,"hward"]:"");
if (network_settings["use_proxy"]:nil == true) {
string proxy_auth = "";
if (network_settings["proxy_user"]:"" != "" && network_settings["proxy_password"]:"" != "") {
proxy_auth = sformat ("%1:%2",
// escaping ":"s in username
mergestring (splitstring (network_settings["proxy_user"]:"", ":"), "\\:"),
// escaping ":"s in password
mergestring (splitstring (network_settings["proxy_password"]:"", ":"), "\\:")
);
}
string proxy_server = nil;
// no proxy auth
if (proxy_auth == "") {
proxy_server = sformat (
"http://%1:%2/",
network_settings["proxy_server"]:"",
network_settings["proxy_port"]:""
);
// write proxy auth as well
} else {
proxy_server = sformat (
"http://%1@%2:%3/",
proxy_auth,
network_settings["proxy_server"]:"",
network_settings["proxy_port"]:""
);
}
WriteInstallInfEntry ("Proxy", proxy_server);
} else {
WriteInstallInfEntry ("Proxy", nil);
}
// Flush the SCR agent cache to the disk
SCR::Write (.etc.install_inf, nil);
// Reset cached install.inf
Linuxrc::ResetInstallInf();
return true;
}
// Internet test failed but user might want to accept it
// true -> skip
// false -> do not skip
boolean SkipFailedInetTest () {
if (Popup::AnyQuestion (
// TRANSLATORS: a pop-up dialog headline
_("Internet Test Failed"),
// TRANSLATORS: a pop-up dialog question, see buttons *3
_("The Internet connection test failed. You should be
redirected to the previous dialog to change the configuration.
Go back and change it?"),
// TRANSLATORS: popup dialog button (*3)
_("Go Back"),
// TRANSLATORS: popup dialog button (*3)
_("Skip"),
`yes
)) {
return false;
}
return true;
}
void LogDebugInformation () {
y2milestone ("--- logging network settings ---");
foreach (string one_command, [
"/sbin/ip addr show",
"/sbin/ip route show",
"/bin/cat /etc/resolv.conf"
], {
y2milestone (
"Command: %1 returned %2",
one_command,
SCR::Execute (.target.bash_output, one_command)
);
});
y2milestone ("--- logging network settings ---");
}
// FIXME: should be unified with Network YaST module
boolean Action_TestInternetConnection () {
// ping-based test removed on Coolo's request
// (in some networks, ping is denied by firewall)
//
// // Test the DNS plus routing
// boolean ping_result = false;
// map cmd_failed = $[];
// string cmd_failed_cmd = "";
//
// // Testing more addresses, at least one should succeed
// foreach (string one_address, ["novell.com", "www.opensuse.org", "www.suse.com"], {
// string cmd = sformat ("/bin/ping -q -n -c1 '%1'", String::Quote (one_address));
// map run_cmd = (map) SCR::Execute (.target.bash_output, cmd);
// y2milestone ("Running %1 returned %2", cmd, run_cmd);
//
// // Comand failed
// if (run_cmd["exit"]:-1 != 0) {
// // Store the last failed command output
// cmd_failed_cmd = cmd;
// cmd_failed = run_cmd;
// // Success
// } else {
// // A successfull ping means we do not need to test more of them
// ping_result = true;
// break;
// }
// });
//
// // All ping-commands failed
// if (ping_result != true) {
// LogDebugInformation();
//
// // TRANSLATORS: popup headline
// ReportMoreErrorInformationIfPossible (cmd_failed_cmd, cmd_failed, _("Internet Test Failed"));
//
// if (SkipFailedInetTest()) {
// y2warning ("Internet test failed, but skipping the rest on user's request...");
// return true;
// }
//
// return false;
// }
boolean www_result = false;
map www_failed = $[];
string cmd_failed_www = "";
foreach (string www_address, [
"http://www.novell.com",
"http://www.opensuse.org",
"http://www.suse.com"
], {
string cmd = sformat (
"curl --silent --show-error --max-time 45 --connect-timeout 30 '%1' 1>/dev/null",
String::Quote (www_address)
);
map run_cmd = (map) SCR::Execute (.target.bash_output, cmd);
y2milestone ("Running %1 returned %2", cmd, run_cmd);
// Comand failed
if (run_cmd["exit"]:-1 != 0) {
// Store the last failed command output
www_failed = run_cmd;
cmd_failed_www = cmd;
// Success
} else {
// A successfull ping means we do not need to test more of them
www_result = true;
break;
}
});
// All curl-commands failed
if (www_result != true) {
LogDebugInformation();
// TRANSLATORS: popup headline
ReportMoreErrorInformationIfPossible (cmd_failed_www, www_failed, _("Internet Test Failed"));
if (SkipFailedInetTest()) {
y2warning ("Internet test failed, but skipping the rest on user's request...");
return true;
}
return false;
}
return true;
}
symbol WriteNetworkSetupDialog () {
/**
* Example:
* network_settings =~ $[
* "dns_server":"192.168.0.3",
* "gateway":"192.168.0.1",
* "ip_address":"192.168.1.100",
* "netmask":"255.255.255.0",
* "network_device":"eth2",
* "proxy_password":"pass",
* "proxy_port":"3128",
* "proxy_server":"cache.suse.cz",
* "proxy_user":"user",
* "setup_type":"static",
* "use_proxy":true
* ]
*/
list <string> actions_todo = [];
list <string> actions_doing = [];
list actions_functions = [];
list <string> visible_icons = [];
list <string> invisible_icons = [];
// Dynamic network setup
if (network_settings["setup_type"]:"" == "dhcp") {
// TRANSLATORS: progress step
actions_todo = add (actions_todo, _("Adjust automatic network setup (via DHCP)"));
// TRANSLATORS: progress step
actions_doing = add (actions_doing, _("Adjusting automatic network setup (via DHCP)..."));
actions_functions = add (actions_functions, Action_AdjustDHCPNetworkSetup);
invisible_icons = add (invisible_icons, "32x32/apps/yast-network.png");
visible_icons = add (visible_icons, "32x32/apps/yast-dns.png");
// Static network setup
} else if (network_settings["setup_type"]:"" == "static") {
// TRANSLATORS: progress step
actions_todo = add (actions_todo, _("Adjust static network setup"));
// TRANSLATORS: progress step
actions_doing = add (actions_doing, _("Adjusting static network setup..."));
actions_functions = add (actions_functions, Action_AdjustStaticNetworkSetup);
invisible_icons = add (invisible_icons, "32x32/apps/yast-network.png");
visible_icons = add (visible_icons, "32x32/apps/yast-dns.png");
// Error
} else {
y2error ("Unknown network setup type: '%1'", network_settings["setup_type"]:"");
// TRANSLATORS: pop-up error message
Report::Error (_("Unknown network setup.
Please, go back and provide a valid network setup."));
return `back;
}
// Always write settings, might be already in use
// and we might want to disable it
// TRANSLATORS: progress step
actions_todo = add (actions_todo, _("Write proxy settings"));
// TRANSLATORS: progress step
actions_doing = add (actions_doing, _("Writing proxy settings..."));
actions_functions = add (actions_functions, Action_ProxySetup);
invisible_icons = add (invisible_icons, "32x32/apps/yast-network.png");
visible_icons = add (visible_icons, "32x32/apps/yast-proxy.png");
// Write install.inf only in inst-sys
if (Stage::initial()) {
// TRANSLATORS: progress step
actions_todo = add (actions_todo, _("Adjust installation system"));
// TRANSLATORS: progress step
actions_doing = add (actions_doing, _("Adjusting installation system..."));
actions_functions = add (actions_functions, Action_WriteInstallInf);
invisible_icons = add (invisible_icons, "32x32/apps/yast-network.png");
visible_icons = add (visible_icons, "32x32/apps/yast.png");
}
// TRANSLATORS: progress step
actions_todo = add (actions_todo, _("Test Internet connection"));
// TRANSLATORS: progress step
actions_doing = add (actions_doing, _("Testing Internet connection..."));
actions_functions = add (actions_functions, Action_TestInternetConnection);
invisible_icons = add (invisible_icons, "32x32/apps/yast-network.png");
visible_icons = add (visible_icons, "32x32/apps/yast-isns.png");
Progress::NewProgressIcons (
// TRANSLATORS: dialog caption
_("Writing Network Setup"),
" ",
size (actions_todo),
actions_todo,
actions_doing,
// TRANSLATORS: dialog help
_("<p>Please, wait while network configuration is being written and tested...</p>"),
[visible_icons, invisible_icons]
);
Wizard::SetBackButton (`back, Label::BackButton());
Wizard::SetNextButton (`next, Label::NextButton());
Wizard::SetAbortButton(`abort, Label::CancelButton());
Wizard::SetTitleIcon ("yast-network");
boolean all_ok = true;
foreach (any run_function, actions_functions, {
Progress::NextStage();
y2milestone ("Running function: %1", run_function);
boolean () run_this = (boolean()) (run_function);
boolean ret = run_this();
y2milestone ("Function %1 returned %2", run_function, ret);
if (ret != true) {
all_ok = false;
break;
}
});
// If writing failed, return `back
if (all_ok != true) {
y2warning ("Writing has failed, returning to the previous dialog");
Report::Error (_("Writing the network settings failed.
You will be returned to the previous dialog to either
change the settings, or cancel the network setup."));
return `back;
}
Progress::Finish();
sleep (500);
return `next;
}
/* <-- Functions */
/* Script itself --> */
Wizard::CreateDialog();
ProbeAndGetNetworkCards();
if (table_items == nil || size (table_items) == 0) {
y2milestone ("No network cards found");
return default_ret;
}
map aliases = $[
"netcard" : ``( NetworkCardDialog() ),
"netsetup" : ``( NetworkSetupDialog() ),
"write" : ``( WriteNetworkSetupDialog() ),
];
map sequence = $[
"ws_start" : "netcard",
"netcard" : $[
`abort : `abort,
`next : "netsetup",
],
"netsetup" : $[
`abort : `abort,
`next : "write",
],
"write" : $[
`abort : `abort,
`next : `next,
],
];
any ret = Sequencer::Run (aliases, sequence);
Wizard::CloseDialog();
if (ret == `abort) {
return `abort;
} else {
return default_ret;
}
/* EOF */
}
ACC SHELL 2018