mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-02-04 17:40:38 +01:00
team: expose current device configuration through D-Bus and nmcli
Add a new "Config" property to the D-Bus interface for team devices and show its value through "nmcli device show". The property contains the full JSON configuration from teamd for the device. https://bugzilla.redhat.com/show_bug.cgi?id=1310435
This commit is contained in:
parent
3df3e46d64
commit
3c649e6429
7 changed files with 210 additions and 23 deletions
|
|
@ -186,7 +186,7 @@ static NmcOutputField nmc_fields_dev_wimax_list[] = {
|
|||
#define NMC_FIELDS_DEV_WIMAX_LIST_COMMON "NSP,SIGNAL,TYPE,DEVICE,ACTIVE"
|
||||
#define NMC_FIELDS_DEV_WIMAX_LIST_FOR_DEV_LIST "NAME,"NMC_FIELDS_DEV_WIMAX_LIST_COMMON
|
||||
|
||||
/* Available fields for 'device show' - BOND, TEAM, BRIDGE part */
|
||||
/* Available fields for 'device show' - BOND, BRIDGE part */
|
||||
static NmcOutputField nmc_fields_dev_show_master_prop[] = {
|
||||
{"NAME", N_("NAME")}, /* 0 */
|
||||
{"SLAVES", N_("SLAVES")}, /* 1 */
|
||||
|
|
@ -195,6 +195,16 @@ static NmcOutputField nmc_fields_dev_show_master_prop[] = {
|
|||
#define NMC_FIELDS_DEV_SHOW_MASTER_PROP_ALL "NAME,SLAVES"
|
||||
#define NMC_FIELDS_DEV_SHOW_MASTER_PROP_COMMON "NAME,SLAVES"
|
||||
|
||||
/* Available fields for 'device show' - TEAM part */
|
||||
static NmcOutputField nmc_fields_dev_show_team_prop[] = {
|
||||
{"NAME", N_("NAME")}, /* 0 */
|
||||
{"SLAVES", N_("SLAVES")}, /* 1 */
|
||||
{"CONFIG", N_("CONFIG")}, /* 2 */
|
||||
{NULL, NULL}
|
||||
};
|
||||
#define NMC_FIELDS_DEV_SHOW_TEAM_PROP_ALL "NAME,SLAVES,CONFIG"
|
||||
#define NMC_FIELDS_DEV_SHOW_TEAM_PROP_COMMON "NAME,SLAVES,CONFIG"
|
||||
|
||||
/* Available fields for 'device show' - VLAN part */
|
||||
static NmcOutputField nmc_fields_dev_show_vlan_prop[] = {
|
||||
{"NAME", N_("NAME")}, /* 0 */
|
||||
|
|
@ -234,7 +244,7 @@ static NmcOutputField nmc_fields_dev_show_sections[] = {
|
|||
{"IP6", N_("IP6"), 0, nmc_fields_ip6_config + 1 }, /* 9 */
|
||||
{"DHCP6", N_("DHCP6"), 0, nmc_fields_dhcp6_config + 1 }, /* 10 */
|
||||
{"BOND", N_("BOND"), 0, nmc_fields_dev_show_master_prop + 1 }, /* 11 */
|
||||
{"TEAM", N_("TEAM"), 0, nmc_fields_dev_show_master_prop + 1 }, /* 12 */
|
||||
{"TEAM", N_("TEAM"), 0, nmc_fields_dev_show_team_prop + 1 }, /* 12 */
|
||||
{"BRIDGE", N_("BRIDGE"), 0, nmc_fields_dev_show_master_prop + 1 }, /* 13 */
|
||||
{"VLAN", N_("VLAN"), 0, nmc_fields_dev_show_vlan_prop + 1 }, /* 14 */
|
||||
{"BLUETOOTH", N_("BLUETOOTH"), 0, nmc_fields_dev_show_bluetooth + 1 }, /* 15 */
|
||||
|
|
@ -840,10 +850,10 @@ get_active_connection_id (NMDevice *device)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
print_bond_team_bridge_info (NMDevice *device,
|
||||
NmCli *nmc,
|
||||
const char *group_prefix,
|
||||
const char *one_field)
|
||||
print_bond_bridge_info (NMDevice *device,
|
||||
NmCli *nmc,
|
||||
const char *group_prefix,
|
||||
const char *one_field)
|
||||
{
|
||||
const GPtrArray *slaves = NULL;
|
||||
GString *slaves_str;
|
||||
|
|
@ -853,10 +863,10 @@ print_bond_team_bridge_info (NMDevice *device,
|
|||
|
||||
if (NM_IS_DEVICE_BOND (device))
|
||||
slaves = nm_device_bond_get_slaves (NM_DEVICE_BOND (device));
|
||||
else if (NM_IS_DEVICE_TEAM (device))
|
||||
slaves = nm_device_team_get_slaves (NM_DEVICE_TEAM (device));
|
||||
else if (NM_IS_DEVICE_BRIDGE (device))
|
||||
slaves = nm_device_bridge_get_slaves (NM_DEVICE_BRIDGE (device));
|
||||
else
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
||||
slaves_str = g_string_new (NULL);
|
||||
for (idx = 0; slaves && idx < slaves->len; idx++) {
|
||||
|
|
@ -891,6 +901,76 @@ print_bond_team_bridge_info (NMDevice *device,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static char *
|
||||
sanitize_team_config (const char *config)
|
||||
{
|
||||
char *ret;
|
||||
int i;
|
||||
|
||||
if (!config)
|
||||
return NULL;
|
||||
|
||||
ret = g_strdup (config);
|
||||
|
||||
for (i = 0; i < strlen (ret); i++) {
|
||||
if (ret[i] == '\n')
|
||||
ret[i] = ' ';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
print_team_info (NMDevice *device,
|
||||
NmCli *nmc,
|
||||
const char *group_prefix,
|
||||
const char *one_field)
|
||||
{
|
||||
const GPtrArray *slaves = NULL;
|
||||
GString *slaves_str;
|
||||
int idx;
|
||||
NmcOutputField *tmpl, *arr;
|
||||
size_t tmpl_len;
|
||||
|
||||
if (NM_IS_DEVICE_TEAM (device))
|
||||
slaves = nm_device_team_get_slaves (NM_DEVICE_TEAM (device));
|
||||
else
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
||||
slaves_str = g_string_new (NULL);
|
||||
for (idx = 0; slaves && idx < slaves->len; idx++) {
|
||||
NMDevice *slave = g_ptr_array_index (slaves, idx);
|
||||
const char *iface = nm_device_get_iface (slave);
|
||||
|
||||
if (iface) {
|
||||
g_string_append (slaves_str, iface);
|
||||
g_string_append_c (slaves_str, ' ');
|
||||
}
|
||||
}
|
||||
if (slaves_str->len > 0)
|
||||
g_string_truncate (slaves_str, slaves_str->len-1); /* Chop off last space */
|
||||
|
||||
tmpl = nmc_fields_dev_show_team_prop;
|
||||
tmpl_len = sizeof (nmc_fields_dev_show_team_prop);
|
||||
nmc->print_fields.indices = parse_output_fields (one_field ? one_field : NMC_FIELDS_DEV_SHOW_TEAM_PROP_ALL,
|
||||
tmpl, FALSE, NULL, NULL);
|
||||
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_FIELD_NAMES);
|
||||
g_ptr_array_add (nmc->output_data, arr);
|
||||
|
||||
arr = nmc_dup_fields_array (tmpl, tmpl_len, NMC_OF_FLAG_SECTION_PREFIX);
|
||||
set_val_strc (arr, 0, group_prefix); /* TEAM */
|
||||
set_val_str (arr, 1, slaves_str->str);
|
||||
set_val_str (arr, 2, sanitize_team_config (nm_device_team_get_config (NM_DEVICE_TEAM (device))));
|
||||
g_ptr_array_add (nmc->output_data, arr);
|
||||
|
||||
print_data (nmc); /* Print all data */
|
||||
|
||||
g_string_free (slaves_str, FALSE);
|
||||
nmc_empty_output_fields (nmc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
show_device_info (NMDevice *device, NmCli *nmc)
|
||||
{
|
||||
|
|
@ -1146,19 +1226,19 @@ show_device_info (NMDevice *device, NmCli *nmc)
|
|||
/* Bond specific information */
|
||||
if (NM_IS_DEVICE_BOND (device)) {
|
||||
if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[11].name))
|
||||
was_output = print_bond_team_bridge_info (device, nmc, nmc_fields_dev_show_sections[11].name, section_fld);
|
||||
was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[11].name, section_fld);
|
||||
}
|
||||
|
||||
/* Team specific information */
|
||||
if (NM_IS_DEVICE_TEAM (device)) {
|
||||
if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[12].name))
|
||||
was_output = print_bond_team_bridge_info (device, nmc, nmc_fields_dev_show_sections[12].name, section_fld);
|
||||
was_output = print_team_info (device, nmc, nmc_fields_dev_show_sections[12].name, section_fld);
|
||||
}
|
||||
|
||||
/* Bridge specific information */
|
||||
if (NM_IS_DEVICE_BRIDGE (device)) {
|
||||
if (!strcasecmp (nmc_fields_dev_show_sections[section_idx].name, nmc_fields_dev_show_sections[13].name))
|
||||
was_output = print_bond_team_bridge_info (device, nmc, nmc_fields_dev_show_sections[13].name, section_fld);
|
||||
was_output = print_bond_bridge_info (device, nmc, nmc_fields_dev_show_sections[13].name, section_fld);
|
||||
}
|
||||
|
||||
/* VLAN-specific information */
|
||||
|
|
|
|||
|
|
@ -25,6 +25,13 @@
|
|||
-->
|
||||
<property name="Slaves" type="ao" access="read"/>
|
||||
|
||||
<!--
|
||||
Config:
|
||||
|
||||
The JSON configuration currently applied on the device.
|
||||
-->
|
||||
<property name="Config" type="s" access="read" />
|
||||
|
||||
<!--
|
||||
PropertiesChanged:
|
||||
@properties: A dictionary mapping property names to variant boxed values
|
||||
|
|
|
|||
|
|
@ -1061,6 +1061,7 @@ global:
|
|||
|
||||
libnm_1_4_0 {
|
||||
global:
|
||||
nm_device_team_get_config;
|
||||
nm_setting_ip_config_get_dns_priority;
|
||||
nm_vpn_editor_plugin_load;
|
||||
nm_vpn_plugin_info_get_auth_dialog;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ typedef struct {
|
|||
char *hw_address;
|
||||
gboolean carrier;
|
||||
GPtrArray *slaves;
|
||||
char *config;
|
||||
} NMDeviceTeamPrivate;
|
||||
|
||||
enum {
|
||||
|
|
@ -46,6 +47,7 @@ enum {
|
|||
PROP_HW_ADDRESS,
|
||||
PROP_CARRIER,
|
||||
PROP_SLAVES,
|
||||
PROP_CONFIG,
|
||||
|
||||
LAST_PROP
|
||||
};
|
||||
|
|
@ -101,6 +103,25 @@ nm_device_team_get_slaves (NMDeviceTeam *device)
|
|||
return NM_DEVICE_TEAM_GET_PRIVATE (device)->slaves;
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_team_get_config:
|
||||
* @device: a #NMDeviceTeam
|
||||
*
|
||||
* Gets the current JSON configuration of the #NMDeviceTeam
|
||||
*
|
||||
* Returns: the current configuration. This is the internal string used by the
|
||||
* device, and must not be modified.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
const char *
|
||||
nm_device_team_get_config (NMDeviceTeam *device)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_DEVICE_TEAM (device), NULL);
|
||||
|
||||
return NM_DEVICE_TEAM_GET_PRIVATE (device)->config;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_hw_address (NMDevice *device)
|
||||
{
|
||||
|
|
@ -150,6 +171,7 @@ init_dbus (NMObject *object)
|
|||
{ NM_DEVICE_TEAM_HW_ADDRESS, &priv->hw_address },
|
||||
{ NM_DEVICE_TEAM_CARRIER, &priv->carrier },
|
||||
{ NM_DEVICE_TEAM_SLAVES, &priv->slaves, NULL, NM_TYPE_DEVICE },
|
||||
{ NM_DEVICE_TEAM_CONFIG, &priv->config },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
@ -176,6 +198,7 @@ finalize (GObject *object)
|
|||
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (object);
|
||||
|
||||
g_free (priv->hw_address);
|
||||
g_free (priv->config);
|
||||
|
||||
G_OBJECT_CLASS (nm_device_team_parent_class)->finalize (object);
|
||||
}
|
||||
|
|
@ -198,6 +221,9 @@ get_property (GObject *object,
|
|||
case PROP_SLAVES:
|
||||
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_team_get_slaves (device)));
|
||||
break;
|
||||
case PROP_CONFIG:
|
||||
g_value_set_string (value, nm_device_team_get_config (device));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -265,4 +291,18 @@ nm_device_team_class_init (NMDeviceTeamClass *team_class)
|
|||
G_TYPE_PTR_ARRAY,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* NMDeviceTeam:config:
|
||||
*
|
||||
* The current JSON configuration of the device.
|
||||
*
|
||||
* Since: 1.4
|
||||
**/
|
||||
g_object_class_install_property
|
||||
(object_class, PROP_CONFIG,
|
||||
g_param_spec_string (NM_DEVICE_TEAM_CONFIG, "", "",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ G_BEGIN_DECLS
|
|||
#define NM_DEVICE_TEAM_HW_ADDRESS "hw-address"
|
||||
#define NM_DEVICE_TEAM_CARRIER "carrier"
|
||||
#define NM_DEVICE_TEAM_SLAVES "slaves"
|
||||
#define NM_DEVICE_TEAM_CONFIG "config"
|
||||
|
||||
/**
|
||||
* NMDeviceTeam:
|
||||
|
|
@ -59,6 +60,8 @@ GType nm_device_team_get_type (void);
|
|||
const char *nm_device_team_get_hw_address (NMDeviceTeam *device);
|
||||
gboolean nm_device_team_get_carrier (NMDeviceTeam *device);
|
||||
const GPtrArray *nm_device_team_get_slaves (NMDeviceTeam *device);
|
||||
NM_AVAILABLE_IN_1_4
|
||||
const char *nm_device_team_get_config (NMDeviceTeam *device);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ G_DEFINE_TYPE (NMDeviceTeam, nm_device_team, NM_TYPE_DEVICE)
|
|||
|
||||
#define NM_DEVICE_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TEAM, NMDeviceTeamPrivate))
|
||||
|
||||
NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceTeam,
|
||||
PROP_CONFIG,
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
struct teamdctl *tdc;
|
||||
GPid teamd_pid;
|
||||
|
|
@ -52,6 +56,7 @@ typedef struct {
|
|||
guint teamd_timeout;
|
||||
guint teamd_dbus_watch;
|
||||
gboolean teamd_dbus_name_owned;
|
||||
char *config;
|
||||
} NMDeviceTeamPrivate;
|
||||
|
||||
static gboolean teamd_start (NMDevice *device, NMSettingTeam *s_team);
|
||||
|
|
@ -148,6 +153,27 @@ ensure_teamd_connection (NMDevice *device)
|
|||
return !!priv->tdc;
|
||||
}
|
||||
|
||||
static void
|
||||
teamd_read_config (NMDevice *device)
|
||||
{
|
||||
NMDeviceTeam *self = NM_DEVICE_TEAM (device);
|
||||
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self);
|
||||
char *config = NULL;
|
||||
int err;
|
||||
|
||||
if (priv->tdc) {
|
||||
err = teamdctl_config_get_raw_direct (priv->tdc, &config);
|
||||
if (err)
|
||||
_LOGI (LOGD_TEAM, "failed to read teamd config (err=%d)", err);
|
||||
}
|
||||
|
||||
if (!nm_streq0 (config, priv->config)) {
|
||||
g_free (priv->config);
|
||||
priv->config = g_strdup (config);
|
||||
_notify (self, PROP_CONFIG);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_connection (NMDevice *device, NMConnection *connection)
|
||||
{
|
||||
|
|
@ -159,18 +185,12 @@ update_connection (NMDevice *device, NMConnection *connection)
|
|||
s_team = (NMSettingTeam *) nm_setting_team_new ();
|
||||
nm_connection_add_setting (connection, (NMSetting *) s_team);
|
||||
}
|
||||
g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, NULL, NULL);
|
||||
|
||||
if (ensure_teamd_connection (device)) {
|
||||
const char *config = NULL;
|
||||
int err;
|
||||
/* Read the configuration only if not already set */
|
||||
if (!priv->config && ensure_teamd_connection (device))
|
||||
teamd_read_config (device);
|
||||
|
||||
err = teamdctl_config_get_raw_direct (priv->tdc, (char **)&config);
|
||||
if (err == 0)
|
||||
g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, config, NULL);
|
||||
else
|
||||
_LOGE (LOGD_TEAM, "failed to read teamd config (err=%d)", err);
|
||||
}
|
||||
g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, priv->config, NULL);
|
||||
}
|
||||
|
||||
/******************************************************************/
|
||||
|
|
@ -279,6 +299,11 @@ teamd_timeout_cb (gpointer user_data)
|
|||
|
||||
g_warn_if_fail (nm_device_is_activating (device));
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
||||
} else {
|
||||
/* Read again the configuration after the timeout since it might
|
||||
* have changed.
|
||||
*/
|
||||
teamd_read_config (device);
|
||||
}
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
|
|
@ -331,9 +356,10 @@ teamd_dbus_appeared (GDBusConnection *connection,
|
|||
*/
|
||||
success = ensure_teamd_connection (device);
|
||||
if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) {
|
||||
if (success)
|
||||
if (success) {
|
||||
teamd_read_config (device);
|
||||
nm_device_activate_schedule_stage2_device_config (device);
|
||||
else if (!nm_device_uses_assumed_connection (device))
|
||||
} else if (!nm_device_uses_assumed_connection (device))
|
||||
nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED);
|
||||
}
|
||||
}
|
||||
|
|
@ -695,6 +721,23 @@ nm_device_team_new (const char *iface)
|
|||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
get_property (GObject *object, guint prop_id,
|
||||
GValue *value, GParamSpec *pspec)
|
||||
{
|
||||
NMDeviceTeam *self = NM_DEVICE_TEAM (object);
|
||||
NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (self);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_CONFIG:
|
||||
g_value_set_string (value, priv->config);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nm_device_team_init (NMDeviceTeam * self)
|
||||
{
|
||||
|
|
@ -733,6 +776,7 @@ dispose (GObject *object)
|
|||
}
|
||||
|
||||
teamd_cleanup (device, TRUE);
|
||||
g_clear_pointer (&priv->config, g_free);
|
||||
|
||||
G_OBJECT_CLASS (nm_device_team_parent_class)->dispose (object);
|
||||
}
|
||||
|
|
@ -749,6 +793,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
|
|||
|
||||
object_class->constructed = constructed;
|
||||
object_class->dispose = dispose;
|
||||
object_class->get_property = get_property;
|
||||
|
||||
parent_class->create_and_realize = create_and_realize;
|
||||
parent_class->get_generic_capabilities = get_generic_capabilities;
|
||||
|
|
@ -765,6 +810,14 @@ nm_device_team_class_init (NMDeviceTeamClass *klass)
|
|||
parent_class->enslave_slave = enslave_slave;
|
||||
parent_class->release_slave = release_slave;
|
||||
|
||||
obj_properties[PROP_CONFIG] =
|
||||
g_param_spec_string (NM_DEVICE_TEAM_CONFIG, "", "",
|
||||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
|
||||
|
||||
nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass),
|
||||
NMDBUS_TYPE_DEVICE_TEAM_SKELETON,
|
||||
NULL);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ G_BEGIN_DECLS
|
|||
#define NM_IS_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TEAM))
|
||||
#define NM_DEVICE_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass))
|
||||
|
||||
/* Properties */
|
||||
#define NM_DEVICE_TEAM_CONFIG "config"
|
||||
|
||||
typedef NMDevice NMDeviceTeam;
|
||||
typedef NMDeviceClass NMDeviceTeamClass;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue