nmcli: streamline connection addition

This is a huge refactoring in attempt to 1.) reduce the horrible redundancy in
the connection addition path and 2.) reduce confusion between various sources
of property value (command line, properties, interactive mode).

* The conversions from the strings was done all over the place:
  settings.c already does for all sensible properties.
  The rest is removed.

* The validations are done randomly and redundantly:
  server does some validation, and per-property client validations
  useful for interactive mode are done in settings.c
  The rest is removed.

* The information about defaults and required options was redundantly
  scattered in per-type completion functions and interactive mode
  questionnaries. This is now driven by the option_info[] table.

In general, we do our best to just map the command line options to
properties and allow mixing them. For the rest there's the
check_and_set() callbacks (basically to keep compatibility with previous
nmcli versions). This this is now all possible:

$ nmcli c add type ethernet ifname '*'
  This always worked

$ nmcli c add type bond-slave save no -- connection.autoconnect no
  The "save" and "--" still work

$ nmcli c add connection.type ethernet ifname eth0
  Properties can now be used

$ nmcli c add type ethernet ip4 1.2.3.4 mac 80:86:66:77:88:99 con-name whatever
  There's no implementation mandated order of the properties (the type
  still must be known to determine which properties make sense)

$ nmcli --ask c add type ethernet ip4 1.2.3.4 mac 80:86:66:77:88:99 con-name whatever
  The interactive mode asks only for properties that weren't specified
  on command line
This commit is contained in:
Lubomir Rintel 2016-05-20 20:43:58 +02:00
parent 057d477b2a
commit c5324ed285
2 changed files with 1404 additions and 3751 deletions

File diff suppressed because it is too large Load diff

View file

@ -2405,7 +2405,44 @@ nmc_setting_custom_init (NMSetting *setting)
{
g_return_if_fail (NM_IS_SETTING (setting));
if (NM_IS_SETTING_IP4_CONFIG (setting)) {
if (NM_IS_SETTING_VLAN (setting)) {
/* Set sensible initial VLAN values */
g_object_set (NM_SETTING_VLAN (setting),
NM_SETTING_VLAN_ID, 1,
NULL);
} else if (NM_IS_SETTING_INFINIBAND (setting)) {
/* Initialize 'transport-mode' so that 'infiniband' is valid */
g_object_set (NM_SETTING_INFINIBAND (setting),
NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
NULL);
} else if (NM_IS_SETTING_CDMA (setting)) {
/* Initialize 'number' so that 'cdma' is valid */
g_object_set (NM_SETTING_CDMA (setting),
NM_SETTING_CDMA_NUMBER, "#777",
NULL);
} else if (NM_IS_SETTING_GSM (setting)) {
/* Initialize 'number' so that 'gsm' is valid */
g_object_set (NM_SETTING_GSM (setting),
NM_SETTING_GSM_NUMBER, "*99#",
NULL);
} else if (NM_IS_SETTING_OLPC_MESH (setting)) {
g_object_set (NM_SETTING_OLPC_MESH (setting),
NM_SETTING_OLPC_MESH_CHANNEL, 1,
NULL);
} else if (NM_IS_SETTING_WIRELESS (setting)) {
/* For Wi-Fi set mode to "infrastructure". Even though mode == NULL
* is regarded as "infrastructure", explicit value makes no doubts.
*/
g_object_set (NM_SETTING_WIRELESS (setting),
NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
NULL);
nmc_setting_wireless_connect_handlers (NM_SETTING_WIRELESS (setting));
} else if (NM_IS_SETTING_ADSL (setting)) {
/* Initialize a protocol */
g_object_set (NM_SETTING_ADSL (setting),
NM_SETTING_ADSL_PROTOCOL, NM_SETTING_ADSL_PROTOCOL_PPPOE,
NULL);
} else if (NM_IS_SETTING_IP4_CONFIG (setting)) {
g_object_set (NM_SETTING_IP_CONFIG (setting),
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
NULL);
@ -2415,11 +2452,14 @@ nmc_setting_custom_init (NMSetting *setting)
NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO,
NULL);
nmc_setting_ip6_connect_handlers (NM_SETTING_IP_CONFIG (setting));
} else if (NM_IS_SETTING_WIRELESS (setting)) {
g_object_set (NM_SETTING_WIRELESS (setting),
NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA,
} else if (NM_IS_SETTING_TUN (setting)) {
g_object_set (NM_SETTING_TUN (setting),
NM_SETTING_TUN_MODE, NM_SETTING_TUN_MODE_TUN,
NULL);
} else if (NM_IS_SETTING_BLUETOOTH (setting)) {
g_object_set (NM_SETTING_BLUETOOTH (setting),
NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
NULL);
nmc_setting_wireless_connect_handlers (NM_SETTING_WIRELESS (setting));
}
}
@ -2997,6 +3037,32 @@ done:
}
/* --- NM_SETTING_CONNECTION_SETTING_NAME property setter functions --- */
static gboolean
nmc_property_connection_set_type (NMSetting *setting, const char *prop, const char *val, GError **error)
{
gs_free char *uuid = NULL;
if (nm_setting_connection_get_uuid (NM_SETTING_CONNECTION (setting))) {
/* Don't allow setting type unless the connection is brand new.
* Just because it's a bad idea and the user wouldn't probably want that.
* No technical reason, really.
* Also, using uuid to see if the connection is brand new is a bit
* hacky: we can not see if the type is already set, because
* nmc_setting_set_property() is called only after the property
* we're setting (type) has been removed. */
g_set_error (error, 1, 0, _("Can not change the connection type"));
return FALSE;
}
uuid = nm_utils_uuid_generate ();
g_object_set (G_OBJECT (setting),
NM_SETTING_CONNECTION_UUID, uuid,
NULL);
g_object_set (G_OBJECT (setting), prop, val, NULL);
return TRUE;
}
#if 0
/*
* Setting/removing UUID has been forbidden.
@ -6149,7 +6215,7 @@ nmc_properties_init (void)
NULL);
nmc_add_prop_funcs (GLUE (CONNECTION, TYPE),
nmc_property_connection_get_type,
NULL, /* read-only */
nmc_property_connection_set_type,
NULL,
NULL,
NULL,