X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=ui%2Fncurses%2Fnc-config.c;h=4685fa5d0db1988661503115163ddf30c9a7a552;hp=54eb7ac5740d891bd32c6a7bcc57655cbf19bc8a;hb=07f6db7fc29a93fae3213af18371cccb17e0276a;hpb=494988c501287e03da3becba5c03cbce7c3d9d20 diff --git a/ui/ncurses/nc-config.c b/ui/ncurses/nc-config.c index 54eb7ac..4685fa5 100644 --- a/ui/ncurses/nc-config.c +++ b/ui/ncurses/nc-config.c @@ -29,19 +29,14 @@ #include #include +#include "ui/common/discover-client.h" #include "nc-cui.h" #include "nc-config.h" #include "nc-widgets.h" -#define N_FIELDS 25 +#define N_FIELDS 49 -extern const char *config_help_text; - -enum autoboot_type { - AUTOBOOT_ANY, - AUTOBOOT_ONE, - AUTOBOOT_DISABLED, -}; +extern struct help_text config_help_text; enum net_conf_type { NET_CONF_TYPE_DHCP_ALL, @@ -57,6 +52,9 @@ struct config_screen { bool exit; bool show_help; + bool need_redraw; + bool need_update; + void (*on_exit)(struct cui *); int scroll_y; @@ -66,16 +64,28 @@ struct config_screen { int network_config_y; enum net_conf_type net_conf_type; - enum autoboot_type autoboot_type; + + bool autoboot_enabled; + bool ipmi_override; + bool net_override; struct { - struct nc_widget_select *autoboot_f; struct nc_widget_label *autoboot_l; - struct nc_widget_select *boot_device_f; + struct nc_widget_select *autoboot_f; + struct nc_widget_label *boot_order_l; + struct nc_widget_subset *boot_order_f; + struct nc_widget_label *boot_empty_l; + struct nc_widget_button *boot_add_b; + struct nc_widget_button *boot_none_b; + struct nc_widget_button *boot_any_b; struct nc_widget_textbox *timeout_f; struct nc_widget_label *timeout_l; struct nc_widget_label *timeout_help_l; + struct nc_widget_label *ipmi_type_l; + struct nc_widget_label *ipmi_clear_l; + struct nc_widget_button *ipmi_clear_b; + struct nc_widget_label *network_l; struct nc_widget_select *network_f; @@ -89,11 +99,29 @@ struct config_screen { struct nc_widget_label *gateway_l; struct nc_widget_textbox *gateway_f; struct nc_widget_label *gateway_help_l; + struct nc_widget_label *url_l; + struct nc_widget_textbox *url_f; + struct nc_widget_label *url_help_l; struct nc_widget_label *dns_l; struct nc_widget_textbox *dns_f; struct nc_widget_label *dns_dhcp_help_l; struct nc_widget_label *dns_help_l; - + struct nc_widget_label *http_proxy_l; + struct nc_widget_textbox *http_proxy_f; + struct nc_widget_label *https_proxy_l; + struct nc_widget_textbox *https_proxy_f; + + struct nc_widget_label *allow_write_l; + struct nc_widget_select *allow_write_f; + struct nc_widget_label *boot_console_l; + struct nc_widget_select *boot_console_f; + struct nc_widget_label *manual_console_l; + struct nc_widget_label *current_console_l; + + struct nc_widget_button *update_password_l; + + struct nc_widget_label *net_override_l; + struct nc_widget_label *safe_mode; struct nc_widget_button *ok_b; struct nc_widget_button *help_b; struct nc_widget_button *cancel_b; @@ -145,10 +173,11 @@ static void config_screen_process_key(struct nc_scr *scr, int key) } else if (screen->show_help) { screen->show_help = false; + screen->need_redraw = true; cui_show_help(screen->cui, _("System Configuration"), - config_help_text); + &config_help_text); - } else if (handled) { + } else if (handled && (screen->cui->current == scr)) { pad_refresh(screen); } } @@ -159,17 +188,6 @@ static void config_screen_resize(struct nc_scr *scr) (void)screen; } -static int config_screen_post(struct nc_scr *scr) -{ - struct config_screen *screen = config_screen_from_scr(scr); - widgetset_post(screen->widgetset); - nc_scr_frame_draw(scr); - redrawwin(scr->main_ncw); - wrefresh(screen->scr.main_ncw); - pad_refresh(screen); - return 0; -} - static int config_screen_unpost(struct nc_scr *scr) { struct config_screen *screen = config_screen_from_scr(scr); @@ -187,38 +205,47 @@ static int screen_process_form(struct config_screen *screen) const struct system_info *sysinfo = screen->cui->sysinfo; enum net_conf_type net_conf_type; struct interface_config *iface; - struct config *config; + bool allow_write; char *str, *end; - int rc, idx; + struct config *config; + int i, n_boot_opts, rc; + unsigned int *order, idx; + char mac[20]; config = config_copy(screen, screen->cui->config); - screen->autoboot_type = - widget_select_get_value(screen->widgets.autoboot_f); - - config->autoboot_enabled = screen->autoboot_type != AUTOBOOT_DISABLED; - - if (screen->autoboot_type == AUTOBOOT_ONE) { - char mac[20], *uuid = NULL; - - /* if idx is -1 here, we have an unknown UUID selected. - * Otherwise, it's a blockdev index (idx <= n_blockdevs) or an - * interface index. - */ - idx = widget_select_get_value(screen->widgets.boot_device_f); - if (idx >= (int)sysinfo->n_blockdevs) { - struct interface_info *info = sysinfo-> - interfaces[idx - sysinfo->n_blockdevs]; - mac_str(info->hwaddr, info->hwaddr_size, - mac, sizeof(mac)); - uuid = mac; - } else if (idx != -1) { - uuid = sysinfo->blockdevs[idx]->uuid; - } - - if (uuid) { - talloc_free(config->boot_device); - config->boot_device = talloc_strdup(config, uuid); + talloc_free(config->autoboot_opts); + config->n_autoboot_opts = 0; + + n_boot_opts = widget_subset_get_order(config, &order, + screen->widgets.boot_order_f); + + config->autoboot_enabled = widget_select_get_value( + screen->widgets.autoboot_f); + + config->n_autoboot_opts = n_boot_opts; + config->autoboot_opts = talloc_array(config, struct autoboot_option, + n_boot_opts); + + for (i = 0; i < n_boot_opts; i++) { + if (order[i] < sysinfo->n_blockdevs) { + /* disk uuid */ + config->autoboot_opts[i].boot_type = BOOT_DEVICE_UUID; + config->autoboot_opts[i].uuid = talloc_strdup(config, + sysinfo->blockdevs[order[i]]->uuid); + } else if(order[i] < (sysinfo->n_blockdevs + sysinfo->n_interfaces)) { + /* net uuid */ + order[i] -= sysinfo->n_blockdevs; + config->autoboot_opts[i].boot_type = BOOT_DEVICE_UUID; + mac_str(sysinfo->interfaces[order[i]]->hwaddr, + sysinfo->interfaces[order[i]]->hwaddr_size, + mac, sizeof(mac)); + config->autoboot_opts[i].uuid = talloc_strdup(config, mac); + } else { + /* device type */ + order[i] -= (sysinfo->n_blockdevs + sysinfo->n_interfaces); + config->autoboot_opts[i].boot_type = BOOT_DEVICE_TYPE; + config->autoboot_opts[i].type = order[i]; } } @@ -260,11 +287,12 @@ static int screen_process_form(struct config_screen *screen) } if (net_conf_type == NET_CONF_TYPE_STATIC) { - char *ip, *mask, *gateway; + char *ip, *mask, *gateway, *url; ip = widget_textbox_get_value(screen->widgets.ip_addr_f); mask = widget_textbox_get_value(screen->widgets.ip_mask_f); gateway = widget_textbox_get_value(screen->widgets.gateway_f); + url = widget_textbox_get_value(screen->widgets.url_f); if (!ip || !*ip || !mask || !*mask) { screen->scr.frame.status = @@ -278,6 +306,7 @@ static int screen_process_form(struct config_screen *screen) iface->static_config.address = talloc_asprintf(iface, "%s/%s", ip, mask); iface->static_config.gateway = talloc_strdup(iface, gateway); + iface->static_config.url = talloc_strdup(iface, url); } str = widget_textbox_get_value(screen->widgets.dns_f); @@ -307,6 +336,31 @@ static int screen_process_form(struct config_screen *screen) } } + talloc_free(config->http_proxy); + talloc_free(config->https_proxy); + str = widget_textbox_get_value(screen->widgets.http_proxy_f); + config->http_proxy = talloc_strdup(config, str); + str = widget_textbox_get_value(screen->widgets.https_proxy_f); + config->https_proxy = talloc_strdup(config, str); + + allow_write = widget_select_get_value(screen->widgets.allow_write_f); + if (allow_write != config->allow_writes) + config->allow_writes = allow_write; + + if (config->n_consoles && !config->manual_console) { + idx = widget_select_get_value(screen->widgets.boot_console_f); + if (!config->boot_console) { + config->boot_console = talloc_strdup(config, + config->consoles[idx]); + } else if (strncmp(config->boot_console, config->consoles[idx], + strlen(config->boot_console)) != 0) { + talloc_free(config->boot_console); + config->boot_console = talloc_strdup(config, + config->consoles[idx]); + } + } + + config->safe_mode = false; rc = cui_send_config(screen->cui, config); talloc_free(config); @@ -318,15 +372,39 @@ static int screen_process_form(struct config_screen *screen) return 0; } +static void config_screen_config_cb(struct nc_scr *scr) +{ + struct config_screen *screen = config_screen_from_scr(scr); + + if (!screen_process_form(screen)) + screen->exit = true; +} + +#ifdef CRYPT_SUPPORT +static void password_click(void *arg) +{ + struct config_screen *screen = arg; + + screen->need_update = true; + cui_show_auth(screen->cui, screen->scr.main_ncw, true, NULL); +} +#endif + static void ok_click(void *arg) { struct config_screen *screen = arg; - if (screen_process_form(screen)) - /* errors are written to the status line, so we'll need - * to refresh */ - wrefresh(screen->scr.main_ncw); - else - screen->exit = true; + + if (discover_client_authenticated(screen->cui->client)) { + if (screen_process_form(screen)) + /* errors are written to the status line, so we'll need + * to refresh */ + wrefresh(screen->scr.main_ncw); + else + screen->exit = true; + } else { + cui_show_auth(screen->cui, screen->scr.main_ncw, false, + config_screen_config_cb); + } } static void help_click(void *arg) @@ -341,6 +419,26 @@ static void cancel_click(void *arg) screen->exit = true; } +static void ipmi_clear_click(void *arg) +{ + struct config_screen *screen = arg; + struct config *config; + int rc; + + config = config_copy(screen, screen->cui->config); + config->ipmi_bootdev = IPMI_BOOTDEV_INVALID; + config->safe_mode = false; + + rc = cui_send_config(screen->cui, config); + talloc_free(config); + + if (rc) + pb_log("cui_send_config failed!\n"); + else + pb_debug("config sent!\n"); + screen->exit = true; +} + static int layout_pair(struct config_screen *screen, int y, struct nc_widget_label *label, struct nc_widget *field) @@ -358,40 +456,98 @@ static void config_screen_layout_widgets(struct config_screen *screen) bool show; y = 1; + /* currently, the longest label we have is the DNS-servers + * widget, so layout our screen based on that */ help_x = screen->field_x + 2 + widget_width(widget_textbox_base(screen->widgets.dns_f)); - y += layout_pair(screen, y, screen->widgets.autoboot_l, - widget_select_base(screen->widgets.autoboot_f)); + wl = widget_label_base(screen->widgets.autoboot_l); + widget_set_visible(wl, true); + widget_move(wl, y, screen->label_x); - wf = widget_select_base(screen->widgets.boot_device_f); - if (screen->autoboot_type == AUTOBOOT_ONE) { - widget_set_visible(wf, true); - widget_move(wf, y, screen->field_x + 3); - y += widget_height(wf); + wf = widget_select_base(screen->widgets.autoboot_f); + widget_set_visible(wf, true); + widget_move(wf, y, screen->field_x); + y += widget_height(wf); + + show = screen->autoboot_enabled; + + if (show) + y += 1; + + wl = widget_label_base(screen->widgets.boot_order_l); + widget_set_visible(wl, show); + widget_move(wl, y, screen->label_x); + + wf = widget_subset_base(screen->widgets.boot_order_f); + widget_move(wf, y, screen->field_x); + wl = widget_label_base(screen->widgets.boot_empty_l); + widget_move(wl, y, screen->field_x); + + if (widget_subset_height(screen->widgets.boot_order_f)) { + widget_set_visible(wl, false); + widget_set_visible(wf, show); + y += show ? widget_height(wf) : 0; } else { + widget_set_visible(wl, show); widget_set_visible(wf, false); + y += show ? 1 : 0; } - y += 1; + if (show) { + y += 1; + widget_move(widget_button_base(screen->widgets.boot_add_b), + y++, screen->field_x); + widget_move(widget_button_base(screen->widgets.boot_any_b), + y++, screen->field_x); + widget_move(widget_button_base(screen->widgets.boot_none_b), + y, screen->field_x); + } + + wf = widget_button_base(screen->widgets.boot_add_b); + if (widget_subset_n_inactive(screen->widgets.boot_order_f) && show) + widget_set_visible(wf, true); + else + widget_set_visible(wf, false); + + if (show) + y += 2; + + widget_set_visible(widget_button_base(screen->widgets.boot_any_b), show); + widget_set_visible(widget_button_base(screen->widgets.boot_none_b), show); wf = widget_textbox_base(screen->widgets.timeout_f); wl = widget_label_base(screen->widgets.timeout_l); wh = widget_label_base(screen->widgets.timeout_help_l); - if (screen->autoboot_type != AUTOBOOT_DISABLED) { - widget_set_visible(wl, true); - widget_set_visible(wf, true); - widget_set_visible(wh, true); + widget_set_visible(wl, screen->autoboot_enabled); + widget_set_visible(wf, screen->autoboot_enabled); + widget_set_visible(wh, screen->autoboot_enabled); + if (screen->autoboot_enabled) { + widget_set_visible(wh, screen->autoboot_enabled); widget_move(wl, y, screen->label_x); widget_move(wf, y, screen->field_x); widget_move(wh, y, screen->field_x + widget_width(wf) + 1); y += 2; - } else { - widget_set_visible(wl, false); - widget_set_visible(wf, false); - widget_set_visible(wh, false); + } else + y += 1; + + if (screen->ipmi_override) { + wl = widget_label_base(screen->widgets.ipmi_type_l); + widget_set_visible(wl, true); + widget_move(wl, y, screen->label_x); + y += 1; + + wl = widget_label_base(screen->widgets.ipmi_clear_l); + wf = widget_button_base(screen->widgets.ipmi_clear_b); + widget_set_visible(wl, true); + widget_set_visible(wf, true); + widget_move(wl, y, screen->label_x); + widget_move(wf, y, screen->field_x); + y += 1; } + y += 1; + y += layout_pair(screen, y, screen->widgets.network_l, widget_select_base(screen->widgets.network_f)); @@ -453,6 +609,19 @@ static void config_screen_layout_widgets(struct config_screen *screen) y++; } + wl = widget_label_base(screen->widgets.url_l); + wf = widget_textbox_base(screen->widgets.url_f); + wh = widget_label_base(screen->widgets.url_help_l); + widget_set_visible(wl, show); + widget_set_visible(wf, show); + widget_set_visible(wh, show); + + if (show) { + layout_pair(screen, y, screen->widgets.url_l, wf); + widget_move(wh, y, help_x); + y++; + } + wh = widget_label_base(screen->widgets.dns_help_l); layout_pair(screen, y, screen->widgets.dns_l, widget_textbox_base(screen->widgets.dns_f)); @@ -468,14 +637,73 @@ static void config_screen_layout_widgets(struct config_screen *screen) y += 1; } + wf = widget_textbox_base(screen->widgets.http_proxy_f); + layout_pair(screen, y, screen->widgets.http_proxy_l, wf); + y++; + wf = widget_textbox_base(screen->widgets.https_proxy_f); + layout_pair(screen, y, screen->widgets.https_proxy_l, wf); + y++; + y += 1; + layout_pair(screen, y, screen->widgets.allow_write_l, + widget_select_base(screen->widgets.allow_write_f)); + y += widget_height(widget_select_base(screen->widgets.allow_write_f)); + + y += 1; + + if (screen->widgets.manual_console_l) { + layout_pair(screen, y++, screen->widgets.boot_console_l, + widget_label_base(screen->widgets.manual_console_l)); + widget_move(widget_label_base(screen->widgets.current_console_l), + y, screen->field_x); + widget_set_visible(widget_select_base( + screen->widgets.boot_console_f), false); + y += 2; + } else if (widget_height(widget_select_base(screen->widgets.boot_console_f))) { + layout_pair(screen, y, screen->widgets.boot_console_l, + widget_select_base(screen->widgets.boot_console_f)); + y += widget_height(widget_select_base(screen->widgets.boot_console_f)); + widget_move(widget_label_base(screen->widgets.current_console_l), + y, screen->field_x); + y += 2; + } else { + widget_set_visible(widget_label_base( + screen->widgets.boot_console_l), false); + widget_set_visible(widget_select_base( + screen->widgets.boot_console_f), false); + widget_set_visible(widget_label_base( + screen->widgets.current_console_l), false); + } + +#ifdef CRYPT_SUPPORT + widget_move(widget_button_base(screen->widgets.update_password_l), + y, screen->field_x); + y += 2; +#endif + + if (screen->net_override) { + widget_move(widget_label_base(screen->widgets.net_override_l), + y, screen->label_x); + widget_set_visible(widget_label_base(screen->widgets.net_override_l), + true); + y += 1; + } + + if (screen->cui->config->safe_mode) { + widget_move(widget_label_base(screen->widgets.safe_mode), + y, screen->label_x); + widget_set_visible(widget_label_base(screen->widgets.safe_mode), + true); + y += 1; + } + widget_move(widget_button_base(screen->widgets.ok_b), y, screen->field_x); widget_move(widget_button_base(screen->widgets.help_b), - y, screen->field_x + 10); + y, screen->field_x + 14); widget_move(widget_button_base(screen->widgets.cancel_b), - y, screen->field_x + 20); + y, screen->field_x + 28); } static void config_screen_network_change(void *arg, int value) @@ -487,15 +715,76 @@ static void config_screen_network_change(void *arg, int value) widgetset_post(screen->widgetset); } +static void config_screen_boot_order_change(void *arg, int value) +{ + (void)value; + struct config_screen *screen = arg; + widgetset_unpost(screen->widgetset); + config_screen_layout_widgets(screen); + widgetset_post(screen->widgetset); +} + static void config_screen_autoboot_change(void *arg, int value) { struct config_screen *screen = arg; - screen->autoboot_type = value; + screen->autoboot_enabled = !!value; + widgetset_unpost(screen->widgetset); + config_screen_layout_widgets(screen); + widgetset_post(screen->widgetset); +} + +static void config_screen_add_device(void *arg) +{ + struct config_screen *screen = arg; + + cui_show_subset(screen->cui, _("Select a boot device to add"), + screen->widgets.boot_order_f); +} + +static void config_screen_autoboot_none(void *arg) +{ + struct config_screen *screen = arg; + struct nc_widget_subset *subset = screen->widgets.boot_order_f; + + widget_subset_clear_active(subset); + + widgetset_unpost(screen->widgetset); + config_screen_layout_widgets(screen); + widgetset_post(screen->widgetset); +} + +static void config_screen_autoboot_any(void *arg) +{ + struct config_screen *screen = arg; + const struct system_info *sysinfo = screen->cui->sysinfo; + struct nc_widget_subset *subset = screen->widgets.boot_order_f; + int idx; + + widget_subset_clear_active(subset); + + idx = sysinfo->n_blockdevs + sysinfo->n_interfaces + DEVICE_TYPE_ANY; + + widget_subset_make_active(screen->widgets.boot_order_f, idx); + + screen->autoboot_enabled = true; + widgetset_unpost(screen->widgetset); config_screen_layout_widgets(screen); widgetset_post(screen->widgetset); } +static void config_screen_update_subset(void *arg, + struct nc_widget_subset *subset, int idx) +{ + struct config_screen *screen = arg; + + if (idx >= 0) + widget_subset_make_active(subset, idx); + if (!screen->autoboot_enabled) + screen->autoboot_enabled = true; + config_screen_layout_widgets(screen); +} + static struct interface_config *first_active_interface( const struct config *config) { @@ -533,10 +822,35 @@ static void config_screen_setup_empty(struct config_screen *screen) widget_new_label(screen->widgetset, 2, screen->field_x, _("Waiting for configuration data...")); screen->widgets.cancel_b = widget_new_button(screen->widgetset, - 4, screen->field_x, 6, _("Cancel"), + 4, screen->field_x, 9, _("Cancel"), cancel_click, screen); } +static int find_autoboot_idx(const struct system_info *sysinfo, + struct autoboot_option *opt) +{ + unsigned int i; + + if (opt->boot_type == BOOT_DEVICE_TYPE) + return sysinfo->n_blockdevs + sysinfo->n_interfaces + opt->type; + + for (i = 0; i < sysinfo->n_blockdevs; i++) { + if (!strcmp(sysinfo->blockdevs[i]->uuid, opt->uuid)) + return i; + } + + for (i = 0; i < sysinfo->n_interfaces; i++) { + struct interface_info *info = sysinfo->interfaces[i]; + char mac[20]; + + mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac)); + + if (!strcmp(mac, opt->uuid)) + return sysinfo->n_blockdevs + i; + } + + return -1; +} static void config_screen_setup_widgets(struct config_screen *screen, const struct config *config, @@ -544,9 +858,10 @@ static void config_screen_setup_widgets(struct config_screen *screen, { struct nc_widgetset *set = screen->widgetset; struct interface_config *ifcfg; - char *str, *ip, *mask, *gw; + char *str, *ip, *mask, *gw, *url, *tty, *label; enum net_conf_type type; unsigned int i; + int add_len, clear_len, any_len, min_len = 20; bool found; build_assert(sizeof(screen->widgets) / sizeof(struct widget *) @@ -555,81 +870,100 @@ static void config_screen_setup_widgets(struct config_screen *screen, type = screen->net_conf_type; ifcfg = first_active_interface(config); + screen->autoboot_enabled = config->autoboot_enabled; + screen->widgets.autoboot_l = widget_new_label(set, 0, 0, _("Autoboot:")); - screen->widgets.autoboot_f = widget_new_select(set, 0, 0, 55); + screen->widgets.autoboot_f = widget_new_select(set, 0, 0, + COLS - screen->field_x - 1); + + widget_select_add_option(screen->widgets.autoboot_f, 0, _("Disabled"), + !screen->autoboot_enabled); + widget_select_add_option(screen->widgets.autoboot_f, 1, _("Enabled"), + screen->autoboot_enabled); widget_select_on_change(screen->widgets.autoboot_f, config_screen_autoboot_change, screen); - screen->widgets.boot_device_f = widget_new_select(set, 0, 0, 55); - - widget_select_add_option(screen->widgets.autoboot_f, - AUTOBOOT_DISABLED, - _("Don't autoboot"), - screen->autoboot_type == - AUTOBOOT_DISABLED); - widget_select_add_option(screen->widgets.autoboot_f, - AUTOBOOT_ANY, - _("Autoboot from any " - "disk/network device"), - screen->autoboot_type == - AUTOBOOT_ANY); - widget_select_add_option(screen->widgets.autoboot_f, - AUTOBOOT_ONE, - _("Only autoboot from a specific " - "disk/network device"), - screen->autoboot_type == - AUTOBOOT_ONE); - - found = false; + add_len = max(min_len, strncols(_("Add Device"))); + clear_len = max(min_len, strncols(_("Clear"))); + any_len = max(min_len, strncols(_("Clear & Boot Any"))); + + screen->widgets.boot_add_b = widget_new_button(set, 0, 0, add_len, + _("Add Device"), + config_screen_add_device, screen); + + screen->widgets.boot_none_b = widget_new_button(set, 0, 0, clear_len, + _("Clear"), + config_screen_autoboot_none, screen); + + screen->widgets.boot_any_b = widget_new_button(set, 0, 0, any_len, + _("Clear & Boot Any"), + config_screen_autoboot_any, screen); + + screen->widgets.boot_order_l = widget_new_label(set, 0, 0, + _("Boot Order:")); + screen->widgets.boot_order_f = widget_new_subset(set, 0, 0, + COLS - screen->field_x, + config_screen_update_subset); + screen->widgets.boot_empty_l = widget_new_label(set, 0, 0, + _("(None)")); + + widget_subset_on_change(screen->widgets.boot_order_f, + config_screen_boot_order_change, screen); for (i = 0; i < sysinfo->n_blockdevs; i++) { struct blockdev_info *bd = sysinfo->blockdevs[i]; - bool selected; - char *label; - - selected = config->boot_device && - !strcmp(config->boot_device, bd->uuid); - if (selected) - found = true; label = talloc_asprintf(screen, _("disk: %s [uuid: %s]"), bd->name, bd->uuid); - widget_select_add_option(screen->widgets.boot_device_f, i, - label, selected); + widget_subset_add_option(screen->widgets.boot_order_f, label); } for (i = 0; i < sysinfo->n_interfaces; i++) { struct interface_info *info = sysinfo->interfaces[i]; - char *label, mac[20]; - bool selected; + char mac[20]; mac_str(info->hwaddr, info->hwaddr_size, mac, sizeof(mac)); - selected = config->boot_device && - !strcmp(config->boot_device, mac); - if (selected) - found = true; label = talloc_asprintf(screen, _("net: %s [mac: %s]"), info->name, mac); - widget_select_add_option(screen->widgets.boot_device_f, - i + sysinfo->n_blockdevs, - label, selected); + widget_subset_add_option(screen->widgets.boot_order_f, label); } - if (screen->autoboot_type == AUTOBOOT_ONE && !found) { - char *label; + for (i = DEVICE_TYPE_NETWORK; i < DEVICE_TYPE_UNKNOWN; i++) { + + if (i == DEVICE_TYPE_ANY) + label = talloc_asprintf(screen, _("Any Device")); + else + label = talloc_asprintf(screen, _("Any %s device"), + device_type_display_name(i)); - label = talloc_asprintf(screen, _("Unknown UUID: %s"), - config->boot_device); + widget_subset_add_option(screen->widgets.boot_order_f, label); + } - widget_select_add_option(screen->widgets.boot_device_f, -1, - label, true); + for (i = 0; i < config->n_autoboot_opts; i++) { + struct autoboot_option *opt = &config->autoboot_opts[i]; + int idx; + + idx = find_autoboot_idx(sysinfo, opt); + + if (idx >= 0) { + widget_subset_make_active(screen->widgets.boot_order_f, + idx); + } else { + if (opt->boot_type == BOOT_DEVICE_TYPE) + pb_log("%s: Unknown autoboot option: %d\n", + __func__, opt->type); + else + pb_log("%s: Unknown autoboot UUID: %s\n", + __func__, opt->uuid); + } } + str = talloc_asprintf(screen, "%d", config->autoboot_timeout_sec); screen->widgets.timeout_l = widget_new_label(set, 0, 0, _("Timeout:")); screen->widgets.timeout_f = widget_new_textbox(set, 0, 0, 5, str); @@ -639,8 +973,26 @@ static void config_screen_setup_widgets(struct config_screen *screen, widget_textbox_set_fixed_size(screen->widgets.timeout_f); widget_textbox_set_validator_integer(screen->widgets.timeout_f, 0, 999); + if (config->ipmi_bootdev) { + label = talloc_asprintf(screen, + _("%s IPMI boot option: %s"), + config->ipmi_bootdev_persistent ? + _("Persistent") : _("Temporary"), + ipmi_bootdev_display_name(config->ipmi_bootdev)); + screen->widgets.ipmi_type_l = widget_new_label(set, 0, 0, + label); + screen->widgets.ipmi_clear_l = widget_new_label(set, 0, 0, + _("Clear option:")); + screen->widgets.ipmi_clear_b = widget_new_button(set, 0, 0, + strncols(_("Clear IPMI override now")) + 10, + _("Clear IPMI override now"), + ipmi_clear_click, screen); + screen->ipmi_override = true; + } + screen->widgets.network_l = widget_new_label(set, 0, 0, _("Network:")); - screen->widgets.network_f = widget_new_select(set, 0, 0, 50); + screen->widgets.network_f = widget_new_select(set, 0, 0, + COLS - screen->field_x - 1); widget_select_add_option(screen->widgets.network_f, NET_CONF_TYPE_DHCP_ALL, @@ -677,7 +1029,7 @@ static void config_screen_setup_widgets(struct config_screen *screen, i, str, is_default); } - gw = ip = mask = NULL; + url = gw = ip = mask = NULL; if (ifcfg && ifcfg->method == CONFIG_METHOD_STATIC) { char *sep; @@ -690,6 +1042,13 @@ static void config_screen_setup_widgets(struct config_screen *screen, mask = sep + 1; } gw = ifcfg->static_config.gateway; + url = ifcfg->static_config.url; + } + + screen->net_override = ifcfg && ifcfg->override; + if (screen->net_override) { + screen->widgets.net_override_l = widget_new_label(set, 0, 0, + _("Network Override Active! 'OK' will overwrite interface config")); } screen->widgets.ip_addr_l = widget_new_label(set, 0, 0, _("IP/mask:")); @@ -701,8 +1060,8 @@ static void config_screen_setup_widgets(struct config_screen *screen, widget_textbox_set_fixed_size(screen->widgets.ip_addr_f); widget_textbox_set_fixed_size(screen->widgets.ip_mask_f); - widget_textbox_set_validator_ipv4(screen->widgets.ip_addr_f); - widget_textbox_set_validator_integer(screen->widgets.ip_mask_f, 1, 31); + widget_textbox_set_validator_ip(screen->widgets.ip_addr_f); + widget_textbox_set_validator_integer(screen->widgets.ip_mask_f, 1, 127); screen->widgets.gateway_l = widget_new_label(set, 0, 0, _("Gateway:")); screen->widgets.gateway_f = widget_new_textbox(set, 0, 0, 16, gw); @@ -710,7 +1069,13 @@ static void config_screen_setup_widgets(struct config_screen *screen, widget_new_label(set, 0, 0, _("(eg. 192.168.0.1)")); widget_textbox_set_fixed_size(screen->widgets.gateway_f); - widget_textbox_set_validator_ipv4(screen->widgets.gateway_f); + widget_textbox_set_validator_ip(screen->widgets.gateway_f); + + screen->widgets.url_l = widget_new_label(set, 0, 0, _("URL:")); + screen->widgets.url_f = widget_new_textbox(set, 0, 0, 32, url); + widget_textbox_set_validator_url(screen->widgets.url_f); + screen->widgets.url_help_l = + widget_new_label(set, 0, 0, _("(eg. tftp://)")); str = talloc_strdup(screen, ""); for (i = 0; i < config->network.n_dns_servers; i++) { @@ -725,34 +1090,92 @@ static void config_screen_setup_widgets(struct config_screen *screen, screen->widgets.dns_help_l = widget_new_label(set, 0, 0, _("(eg. 192.168.0.2)")); - widget_textbox_set_validator_ipv4_multi(screen->widgets.dns_f); + widget_textbox_set_validator_ip_multi(screen->widgets.dns_f); screen->widgets.dns_dhcp_help_l = widget_new_label(set, 0, 0, _("(if not provided by DHCP server)")); - screen->widgets.ok_b = widget_new_button(set, 0, 0, 6, _("OK"), + screen->widgets.http_proxy_l = widget_new_label(set, 0, 0, + _("HTTP Proxy:")); + screen->widgets.http_proxy_f = widget_new_textbox(set, 0, 0, 32, + config->http_proxy); + screen->widgets.https_proxy_l = widget_new_label(set, 0, 0, + _("HTTPS Proxy:")); + screen->widgets.https_proxy_f = widget_new_textbox(set, 0, 0, 32, + config->https_proxy); + + if (config->safe_mode) + screen->widgets.safe_mode = widget_new_label(set, 0, 0, + _("Selecting 'OK' will exit safe mode")); + + screen->widgets.allow_write_l = widget_new_label(set, 0, 0, + _("Disk R/W:")); + screen->widgets.allow_write_f = widget_new_select(set, 0, 0, + COLS - screen->field_x - 1); + + widget_select_add_option(screen->widgets.allow_write_f, 0, + _("Prevent all writes to disk"), + !config->allow_writes); + + widget_select_add_option(screen->widgets.allow_write_f, 1, + _("Allow bootloader scripts to modify disks"), + config->allow_writes); + + screen->widgets.boot_console_l = widget_new_label(set, 0, 0, + _("Boot console:")); + screen->widgets.boot_console_f = widget_new_select(set, 0, 0, + COLS - screen->field_x - 1); + + for (i = 0; i < config->n_consoles; i++){ + found = config->boot_console && + strncmp(config->boot_console, config->consoles[i], + strlen(config->boot_console)) == 0; + widget_select_add_option(screen->widgets.boot_console_f, i, + config->consoles[i], found); + } + + if (config->manual_console) { + label = talloc_asprintf(screen, _("Manually set: '%s'"), + config->boot_console); + screen->widgets.manual_console_l = widget_new_label(set, 0, 0, label); + } + + tty = talloc_asprintf(screen, _("Current interface: %s"), + ttyname(STDIN_FILENO)); + screen->widgets.current_console_l = widget_new_label(set, 0 , 0, tty); + +#ifdef CRYPT_SUPPORT + screen->widgets.update_password_l = widget_new_button(set, 0, 0, 30, + _("Update system password"), password_click, screen); +#endif + + screen->widgets.ok_b = widget_new_button(set, 0, 0, 10, _("OK"), ok_click, screen); - screen->widgets.help_b = widget_new_button(set, 0, 0, 6, _("Help"), + screen->widgets.help_b = widget_new_button(set, 0, 0, 10, _("Help"), help_click, screen); - screen->widgets.cancel_b = widget_new_button(set, 0, 0, 6, _("Cancel"), + screen->widgets.cancel_b = widget_new_button(set, 0, 0, 10, _("Cancel"), cancel_click, screen); } static void config_screen_widget_focus(struct nc_widget *widget, void *arg) { struct config_screen *screen = arg; - int w_y, s_max; + int w_y, w_height, w_focus, s_max, adjust; - w_y = widget_y(widget) + widget_focus_y(widget); + w_height = widget_height(widget); + w_focus = widget_focus_y(widget); + w_y = widget_y(widget) + w_focus; s_max = getmaxy(screen->scr.sub_ncw) - 1; if (w_y < screen->scroll_y) screen->scroll_y = w_y; - else if (w_y + screen->scroll_y + 1 > s_max) - screen->scroll_y = 1 + w_y - s_max; - - else + else if (w_y + screen->scroll_y + 1 > s_max) { + /* Fit as much of the widget into the screen as possible */ + adjust = min(s_max - 1, w_height - w_focus); + if (w_y + adjust >= screen->scroll_y + s_max) + screen->scroll_y = max(0, 1 + w_y + adjust - s_max); + } else return; pad_refresh(screen); @@ -768,17 +1191,22 @@ static void config_screen_draw(struct config_screen *screen, /* The size of the pad we'll need depends on the number of interfaces. * * We use N_FIELDS (which is quite conservative, as some fields share - * a line) as a base, then add 3 (as the network select field is - * takes 3 lines), and n_interfaces (as the network interface field - * has n_interfaces lines). + * a line) as a base, then: + * - add 6 (as the network select & boot device select fields take 3 + * lines each), + * - add n_interfaces for every field in the network select field, and + * - add (n_blockdevs + n_interfaces) for every field in the boot device + * select field */ - height = N_FIELDS + 3; - if (sysinfo) + height = N_FIELDS + 6; + if (sysinfo) { height += sysinfo->n_interfaces; + height += (sysinfo->n_blockdevs + sysinfo->n_interfaces); + } if (!screen->pad || getmaxy(screen->pad) < height) { if (screen->pad) delwin(screen->pad); - screen->pad = newpad(height, COLS); + screen->pad = newpad(height, COLS + 10); } if (screen->widgetset) { @@ -796,12 +1224,6 @@ static void config_screen_draw(struct config_screen *screen, config_screen_setup_empty(screen); } else { screen->net_conf_type = find_net_conf_type(config); - if (!config->autoboot_enabled) - screen->autoboot_type = AUTOBOOT_DISABLED; - else - screen->autoboot_type = config->boot_device ? - AUTOBOOT_ONE : AUTOBOOT_ANY; - config_screen_setup_widgets(screen, config, sysinfo); config_screen_layout_widgets(screen); } @@ -814,10 +1236,43 @@ void config_screen_update(struct config_screen *screen, const struct config *config, const struct system_info *sysinfo) { + if (screen->cui->current != config_screen_scr(screen)) { + screen->need_update = true; + return; + } + config_screen_draw(screen, config, sysinfo); pad_refresh(screen); } +static int config_screen_post(struct nc_scr *scr) +{ + struct config_screen *screen = config_screen_from_scr(scr); + + /* We may have been posted after an auth action completed */ + if (screen->exit) { + screen->on_exit(screen->cui); + return 0; + } + + if (screen->need_update) { + config_screen_draw(screen, screen->cui->config, + screen->cui->sysinfo); + screen->need_update = false; + } else { + widgetset_post(screen->widgetset); + } + + nc_scr_frame_draw(scr); + if (screen->need_redraw) { + redrawwin(scr->main_ncw); + screen->need_redraw = false; + } + wrefresh(screen->scr.main_ncw); + pad_refresh(screen); + return 0; +} + static int config_screen_destroy(void *arg) { struct config_screen *screen = arg; @@ -842,9 +1297,13 @@ struct config_screen *config_screen_init(struct cui *cui, screen->cui = cui; screen->on_exit = on_exit; + screen->need_redraw = false; + screen->need_update = false; screen->label_x = 2; screen->field_x = 17; + screen->ipmi_override = false; + screen->scr.frame.ltitle = talloc_strdup(screen, _("Petitboot System Configuration")); screen->scr.frame.rtitle = NULL;