mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-06-11 11:58:23 +02:00
nmtui/bond: introduce "other options" list
Bond connections can have options that are not exposed by any widget in the bond editor. The presence of certain mode-specific options makes it impossible to change the mode, e.g. from 802.3ad to active-backup when `lacp_rate` is set. Introduce an "Other options" list that shows all bond options not already configurable by a specific widget, and allow the user to edit them as key=value entries. Resolves #1805 Resolves: https://redhat.atlassian.net/browse/NMT-1888
This commit is contained in:
parent
e8f379abb8
commit
6a841072ec
4 changed files with 111 additions and 7 deletions
3
NEWS
3
NEWS
|
|
@ -61,6 +61,9 @@ USE AT YOUR OWN RISK. NOT RECOMMENDED FOR PRODUCTION USE!
|
||||||
* Allow persisting the managed state across reboots from nmcli and the D-Bus API.
|
* Allow persisting the managed state across reboots from nmcli and the D-Bus API.
|
||||||
* Allow changing the device's administrative state in the kernel at the same
|
* Allow changing the device's administrative state in the kernel at the same
|
||||||
time as a change to the managed state from nmcli and the D-Bus API.
|
time as a change to the managed state from nmcli and the D-Bus API.
|
||||||
|
* Allow configuring all bond options in nmtui by introducing a
|
||||||
|
"other options" field, which covers options not already covered by a
|
||||||
|
dedicated input field.
|
||||||
|
|
||||||
=============================================
|
=============================================
|
||||||
NetworkManager-1.56
|
NetworkManager-1.56
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,13 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:nmt-address-list
|
* SECTION:nmt-address-list
|
||||||
* @short_description: An editable list of IP addresses or hostnames
|
* @short_description: An editable list of IP addresses, hostnames, or key=value pairs
|
||||||
*
|
*
|
||||||
* #NmtAddressList is a subclass of #NmtWidgetList that contains
|
* #NmtAddressList is a subclass of #NmtWidgetList that contains
|
||||||
* entries displaying IP addresses, address/prefix strings, or
|
* entries displaying IP addresses, address/prefix strings,
|
||||||
* hostnames. This is designed for binding its #NmtAddressList:strings
|
* hostnames, or key=value pairs. This is designed for binding its
|
||||||
* property to an appropriate #NMSettingIP4Config or
|
* #NmtAddressList:strings property to an appropriate property via one
|
||||||
* #NMSettingIP6Config property via one of the nm-editor-bindings
|
* of the nm-editor-bindings functions.
|
||||||
* functions.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libnm-client-aux-extern/nm-default-client.h"
|
#include "libnm-client-aux-extern/nm-default-client.h"
|
||||||
|
|
@ -115,6 +114,18 @@ hostname_filter(NmtNewtEntry *entry, const char *text, int ch, int position, gpo
|
||||||
return g_ascii_isalnum(ch) || ch == '.' || ch == '-' || ch == '~';
|
return g_ascii_isalnum(ch) || ch == '.' || ch == '-' || ch == '~';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
key_value_validate(NmtNewtEntry *entry, const char *text, gpointer user_data)
|
||||||
|
{
|
||||||
|
const char *val;
|
||||||
|
|
||||||
|
if (!text || !text[0])
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
val = strchr(text, '=');
|
||||||
|
return val && val != text && val[1];
|
||||||
|
}
|
||||||
|
|
||||||
static NmtNewtWidget *
|
static NmtNewtWidget *
|
||||||
nmt_address_list_create_widget(NmtWidgetList *list, int num)
|
nmt_address_list_create_widget(NmtWidgetList *list, int num)
|
||||||
{
|
{
|
||||||
|
|
@ -132,6 +143,9 @@ nmt_address_list_create_widget(NmtWidgetList *list, int num)
|
||||||
} else if (priv->list_type == NMT_ADDRESS_LIST_HOSTNAME) {
|
} else if (priv->list_type == NMT_ADDRESS_LIST_HOSTNAME) {
|
||||||
entry = nmt_newt_entry_new(25, NMT_NEWT_ENTRY_NONEMPTY);
|
entry = nmt_newt_entry_new(25, NMT_NEWT_ENTRY_NONEMPTY);
|
||||||
nmt_newt_entry_set_filter(NMT_NEWT_ENTRY(entry), hostname_filter, list);
|
nmt_newt_entry_set_filter(NMT_NEWT_ENTRY(entry), hostname_filter, list);
|
||||||
|
} else if (priv->list_type == NMT_ADDRESS_LIST_KEY_VALUE) {
|
||||||
|
entry = nmt_newt_entry_new(40, 0);
|
||||||
|
nmt_newt_entry_set_validator(NMT_NEWT_ENTRY(entry), key_value_validate, NULL);
|
||||||
} else {
|
} else {
|
||||||
g_return_val_if_reached(NULL);
|
g_return_val_if_reached(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,8 @@ typedef enum {
|
||||||
NMT_ADDRESS_LIST_IP4,
|
NMT_ADDRESS_LIST_IP4,
|
||||||
NMT_ADDRESS_LIST_IP6_WITH_PREFIX,
|
NMT_ADDRESS_LIST_IP6_WITH_PREFIX,
|
||||||
NMT_ADDRESS_LIST_IP6,
|
NMT_ADDRESS_LIST_IP6,
|
||||||
NMT_ADDRESS_LIST_HOSTNAME
|
NMT_ADDRESS_LIST_HOSTNAME,
|
||||||
|
NMT_ADDRESS_LIST_KEY_VALUE
|
||||||
} NmtAddressListType;
|
} NmtAddressListType;
|
||||||
|
|
||||||
NmtNewtWidget *nmt_address_list_new(NmtAddressListType list_type);
|
NmtNewtWidget *nmt_address_list_new(NmtAddressListType list_type);
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ typedef struct {
|
||||||
NmtNewtEntry *downdelay;
|
NmtNewtEntry *downdelay;
|
||||||
NmtNewtEntry *arp_interval;
|
NmtNewtEntry *arp_interval;
|
||||||
NmtAddressList *arp_ip_target;
|
NmtAddressList *arp_ip_target;
|
||||||
|
NmtAddressList *other_options;
|
||||||
|
|
||||||
NmtPageBondMonitoringMode monitoring_mode;
|
NmtPageBondMonitoringMode monitoring_mode;
|
||||||
|
|
||||||
|
|
@ -63,6 +64,43 @@ static void arp_ip_target_widget_changed(GObject *object, GParamSpec *pspec, gpo
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_is_other_option(const char *option)
|
||||||
|
{
|
||||||
|
return !NM_IN_STRSET(option,
|
||||||
|
NM_SETTING_BOND_OPTION_MODE,
|
||||||
|
NM_SETTING_BOND_OPTION_PRIMARY,
|
||||||
|
NM_SETTING_BOND_OPTION_MIIMON,
|
||||||
|
NM_SETTING_BOND_OPTION_UPDELAY,
|
||||||
|
NM_SETTING_BOND_OPTION_DOWNDELAY,
|
||||||
|
NM_SETTING_BOND_OPTION_ARP_INTERVAL,
|
||||||
|
NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_bond_update_other_options(NMSettingBond *s_bond, NmtAddressList *list)
|
||||||
|
{
|
||||||
|
gs_unref_ptrarray GPtrArray *arr = g_ptr_array_new_with_free_func(g_free);
|
||||||
|
guint num_opts = nm_setting_bond_get_num_options(s_bond);
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < num_opts; i++) {
|
||||||
|
const char *opt_name;
|
||||||
|
const char *opt_value;
|
||||||
|
|
||||||
|
nm_assert(nm_setting_bond_get_option(s_bond, i, &opt_name, &opt_value));
|
||||||
|
|
||||||
|
if (_is_other_option(opt_name)) {
|
||||||
|
g_ptr_array_add(arr, g_strdup_printf("%s=%s", opt_name, opt_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add(arr, NULL);
|
||||||
|
g_object_set(G_OBJECT(list), "strings", arr->pdata, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
NmtEditorPage *
|
NmtEditorPage *
|
||||||
nmt_page_bond_new(NMConnection *conn, NmtDeviceEntry *deventry)
|
nmt_page_bond_new(NMConnection *conn, NmtDeviceEntry *deventry)
|
||||||
{
|
{
|
||||||
|
|
@ -155,6 +193,8 @@ bond_options_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
|
||||||
nmt_newt_widget_set_visible(NMT_NEWT_WIDGET(priv->arp_interval), !visible_mii);
|
nmt_newt_widget_set_visible(NMT_NEWT_WIDGET(priv->arp_interval), !visible_mii);
|
||||||
nmt_newt_widget_set_visible(NMT_NEWT_WIDGET(priv->arp_ip_target), !visible_mii);
|
nmt_newt_widget_set_visible(NMT_NEWT_WIDGET(priv->arp_ip_target), !visible_mii);
|
||||||
|
|
||||||
|
_bond_update_other_options(s_bond, priv->other_options);
|
||||||
|
|
||||||
priv->updating = FALSE;
|
priv->updating = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -308,6 +348,47 @@ arp_ip_target_widget_changed(GObject *object, GParamSpec *pspec, gpointer user_d
|
||||||
g_strfreev(ips);
|
g_strfreev(ips);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
other_options_widget_changed(GObject *object, GParamSpec *pspec, gpointer user_data)
|
||||||
|
{
|
||||||
|
NmtPageBond *bond = NMT_PAGE_BOND(user_data);
|
||||||
|
NmtPageBondPrivate *priv = NMT_PAGE_BOND_GET_PRIVATE(bond);
|
||||||
|
gs_strfreev char **other_options = NULL;
|
||||||
|
const char *name;
|
||||||
|
guint num;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (priv->updating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
priv->updating = TRUE;
|
||||||
|
|
||||||
|
g_object_get(G_OBJECT(priv->other_options), "strings", &other_options, NULL);
|
||||||
|
|
||||||
|
again:
|
||||||
|
num = nm_setting_bond_get_num_options(priv->s_bond);
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
nm_assert(nm_setting_bond_get_option(priv->s_bond, i, &name, NULL));
|
||||||
|
|
||||||
|
if (_is_other_option(name)) {
|
||||||
|
nm_setting_bond_remove_option(priv->s_bond, name);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; other_options && other_options[i]; i++) {
|
||||||
|
char *val = strchr(other_options[i], '=');
|
||||||
|
|
||||||
|
if (val && val != other_options[i] && val[1]) {
|
||||||
|
*val = '\0';
|
||||||
|
if (_is_other_option(other_options[i]))
|
||||||
|
nm_setting_bond_add_option(priv->s_bond, other_options[i], val + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->updating = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
bond_connection_type_filter(GType connection_type, gpointer user_data)
|
bond_connection_type_filter(GType connection_type, gpointer user_data)
|
||||||
{
|
{
|
||||||
|
|
@ -395,6 +476,11 @@ nmt_page_bond_constructed(GObject *object)
|
||||||
nmt_editor_grid_append(grid, _("ARP targets"), widget, NULL);
|
nmt_editor_grid_append(grid, _("ARP targets"), widget, NULL);
|
||||||
priv->arp_ip_target = NMT_ADDRESS_LIST(widget);
|
priv->arp_ip_target = NMT_ADDRESS_LIST(widget);
|
||||||
|
|
||||||
|
widget = nmt_address_list_new(NMT_ADDRESS_LIST_KEY_VALUE);
|
||||||
|
g_signal_connect(widget, "notify::strings", G_CALLBACK(other_options_widget_changed), bond);
|
||||||
|
nmt_editor_grid_append(grid, _("Other options (key=value)"), widget, NULL);
|
||||||
|
priv->other_options = NMT_ADDRESS_LIST(widget);
|
||||||
|
|
||||||
widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED_ETHERNET);
|
widget = nmt_mac_entry_new(40, ETH_ALEN, NMT_MAC_ENTRY_TYPE_CLONED_ETHERNET);
|
||||||
g_object_bind_property(s_wired,
|
g_object_bind_property(s_wired,
|
||||||
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
|
NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue