summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2016-05-16 14:42:41 +0200
committerBeniamino Galvani <bgalvani@redhat.com>2016-05-16 15:26:43 +0200
commit04a6158f68a6447c8fb083f326e14bca3568659c (patch)
tree1be44491aea9172ddca2d2e57ace59ee7ddfd9bd
parentf8fb670c6fbe23907365516c421eb475ae4cbcb3 (diff)
downloadNetworkManager-bg/team-expose-dev-config-rh1310435.tar.gz
team: expose current device configuration through D-Bus and nmclibg/team-expose-dev-config-rh1310435
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
-rw-r--r--clients/cli/devices.c102
-rw-r--r--introspection/nm-device-team.xml7
-rw-r--r--libnm/libnm.ver1
-rw-r--r--libnm/nm-device-team.c39
-rw-r--r--libnm/nm-device-team.h3
-rw-r--r--src/devices/team/nm-device-team.c73
-rw-r--r--src/devices/team/nm-device-team.h3
7 files changed, 207 insertions, 21 deletions
diff --git a/clients/cli/devices.c b/clients/cli/devices.c
index 65c4be7286..e1688278a4 100644
--- a/clients/cli/devices.c
+++ b/clients/cli/devices.c
@@ -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 */
diff --git a/introspection/nm-device-team.xml b/introspection/nm-device-team.xml
index 05bbbafe46..64faaec4b0 100644
--- a/introspection/nm-device-team.xml
+++ b/introspection/nm-device-team.xml
@@ -26,6 +26,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
-->
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index f8e2c4eb2d..abd4c57e44 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -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;
diff --git a/libnm/nm-device-team.c b/libnm/nm-device-team.c
index b855d5ec38..059f13e59b 100644
--- a/libnm/nm-device-team.c
+++ b/libnm/nm-device-team.c
@@ -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 },
};
@@ -198,6 +220,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 +290,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));
}
diff --git a/libnm/nm-device-team.h b/libnm/nm-device-team.h
index a9b71c6ab0..522e3d29c0 100644
--- a/libnm/nm-device-team.h
+++ b/libnm/nm-device-team.h
@@ -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
diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c
index 47930f437c..6e0f658c95 100644
--- a/src/devices/team/nm-device-team.c
+++ b/src/devices/team/nm-device-team.c
@@ -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);
@@ -149,6 +154,27 @@ ensure_teamd_connection (NMDevice *device)
}
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);
+ g_object_notify (G_OBJECT (self), NM_DEVICE_TEAM_CONFIG);
+ }
+}
+
+static void
update_connection (NMDevice *device, NMConnection *connection)
{
NMDeviceTeam *self = NM_DEVICE_TEAM (device);
@@ -162,14 +188,8 @@ update_connection (NMDevice *device, NMConnection *connection)
g_object_set (G_OBJECT (s_team), NM_SETTING_TEAM_CONFIG, NULL, NULL);
if (ensure_teamd_connection (device)) {
- const char *config = NULL;
- int err;
-
- 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);
+ teamd_read_config (device);
+ 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);
}
}
@@ -696,6 +722,23 @@ nm_device_team_new (const char *iface)
}
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);
diff --git a/src/devices/team/nm-device-team.h b/src/devices/team/nm-device-team.h
index 0e81afa744..27bd8227db 100644
--- a/src/devices/team/nm-device-team.h
+++ b/src/devices/team/nm-device-team.h
@@ -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;