all: return output dictionary from "AddAndActivate2"

Add a "a{sv}" output argument to "AddAndActivate2" D-Bus API.
"AddAndActivate2" replaces "AddAndActivate" with more options.
It also has a dictionary argument to be forward compatible so that we
hopefully won't need an "AddAndActivate3". However, it lacked a similar
output dictionary. Add it for future extensibility. I think this is
really to workaround a shortcoming of D-Bus, which does provide strong
typing and type information about its API, but does not allow to extend
an existing API in a backward compatible manner. So we either resort to
Method(), Method2(), Method3() variants, or a catch-all variant with a
generic "a{sv}" input/output argument.

In libnm, rename "nm_client_add_and_activate_connection_options()" to
"nm_client_add_and_activate_connection2()". I think libnm API should have
an obvious correspondence with D-Bus API. Or stated differently, if
"AddAndActivateOptions" would be a better name, then the D-Bus API should
be renamed. We should prefer one name over the other, but regardless
of which is preferred, the naming for D-Bus and libnm API should
correspond.

In this case, I do think that AddAndActivate2() is a better name than
AddAndActivateOptions(). Hence I rename the libnm API.

Also, unless necessary, let libnm still call "AddAndActivate" instead of
"AddAndActivate2". Our backward compatibility works the way that libnm
requires a server version at least as new as itself. As such, libnm
theoretically could assume that server version is new enough to support
"AddAndActivate2" and could always use the more powerful variant.
However, we don't need to break compatibility intentionally and for
little gain. Here, it's easy to let libnm also handle old server API, by
continuing to use "AddAndActivate" for nm_client_add_and_activate_connection().
Note that during package update, we don't restart the currently running
NetworkManager instance. In such a scenario, it can easily happen that
nmcli/libnm is newer than the server version. Let's try a bit harder
to not break that.

Changes as discussed in [1].

[1] https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/37#note_79876
This commit is contained in:
Thomas Haller 2018-12-20 07:48:31 +01:00
parent 3ae5c9d595
commit fbb038af5e
8 changed files with 241 additions and 87 deletions

View file

@ -119,6 +119,8 @@
@options: Further options for the method call.
@path: Object path of the new connection that was just added.
@active_connection: The path of the active connection object representing this active connection.
@result: a dictionary of additional output arguments for future extension. Currently not additional
output arguments are supported.
Adds a new connection using the given details (if any) as a template
(automatically filling in missing settings with the capabilities of the
@ -138,6 +140,7 @@
<arg name="options" type="a{sv}" direction="in"/>
<arg name="path" type="o" direction="out"/>
<arg name="active_connection" type="o" direction="out"/>
<arg name="result" type="a{sv}" direction="out"/>
</method>
<!--

View file

@ -1447,8 +1447,8 @@ global:
libnm_1_16_0 {
global:
nm_client_add_and_activate_connection_options;
nm_client_add_and_activate_connection_options_finish;
nm_client_add_and_activate_connection2;
nm_client_add_and_activate_connection2_finish;
nm_device_get_connectivity;
nm_team_link_watcher_get_vlanid;
nm_team_link_watcher_new_arp_ping2;

View file

@ -1163,18 +1163,20 @@ add_activate_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
GSimpleAsyncResult *simple = user_data;
gs_unref_object GSimpleAsyncResult *simple = user_data;
gs_unref_variant GVariant *result_data = NULL;
NMActiveConnection *ac;
GError *error = NULL;
ac = nm_manager_add_and_activate_connection_finish (NM_MANAGER (object), result, &error);
if (ac)
g_simple_async_result_set_op_res_gpointer (simple, ac, g_object_unref);
else
ac = nm_manager_add_and_activate_connection_finish (NM_MANAGER (object), result, &result_data, &error);
if (ac) {
g_simple_async_result_set_op_res_gpointer (simple,
_nm_activate_result_new (ac, result_data),
(GDestroyNotify) _nm_activate_result_free);
} else
g_simple_async_result_take_error (simple, error);
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
/**
@ -1233,8 +1235,14 @@ nm_client_add_and_activate_connection_async (NMClient *client,
if (cancellable)
g_simple_async_result_set_check_cancellable (simple, cancellable);
nm_manager_add_and_activate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager,
partial, device, specific_object, NULL,
cancellable, add_activate_cb, simple);
partial,
device,
specific_object,
NULL,
FALSE,
cancellable,
add_activate_cb,
simple);
}
/**
@ -1257,6 +1265,7 @@ nm_client_add_and_activate_connection_finish (NMClient *client,
GError **error)
{
GSimpleAsyncResult *simple;
_NMActivateResult *r;
g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
@ -1264,12 +1273,12 @@ nm_client_add_and_activate_connection_finish (NMClient *client,
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
else
return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
r = g_simple_async_result_get_op_res_gpointer (simple);
return g_object_ref (r->active);
}
/**
* nm_client_add_and_activate_connection_options:
* nm_client_add_and_activate_connection2:
* @client: a #NMClient
* @partial: (allow-none): an #NMConnection to add; the connection may be
* partially filled (or even %NULL) and will be completed by NetworkManager
@ -1312,14 +1321,14 @@ nm_client_add_and_activate_connection_finish (NMClient *client,
* Since: 1.16
**/
void
nm_client_add_and_activate_connection_options (NMClient *client,
NMConnection *partial,
NMDevice *device,
const char *specific_object,
GVariant *options,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
nm_client_add_and_activate_connection2 (NMClient *client,
NMConnection *partial,
NMDevice *device,
const char *specific_object,
GVariant *options,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GSimpleAsyncResult *simple;
GError *error = NULL;
@ -1335,21 +1344,30 @@ nm_client_add_and_activate_connection_options (NMClient *client,
}
simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data,
nm_client_add_and_activate_connection_options);
nm_client_add_and_activate_connection2);
if (cancellable)
g_simple_async_result_set_check_cancellable (simple, cancellable);
nm_manager_add_and_activate_connection_async (NM_CLIENT_GET_PRIVATE (client)->manager,
partial, device, specific_object, options,
cancellable, add_activate_cb, simple);
partial,
device,
specific_object,
options,
TRUE,
cancellable,
add_activate_cb,
simple);
}
/**
* nm_client_add_and_activate_connection_options_finish:
* nm_client_add_and_activate_connection2_finish:
* @client: an #NMClient
* @result: the result passed to the #GAsyncReadyCallback
* @error: location for a #GError, or %NULL
* @out_result: (allow-none): (transfer full): the output result
* of type "a{sv}" returned by D-Bus' AddAndActivate2 call. Currently no
* output is implemented yet.
*
* Gets the result of a call to nm_client_add_and_activate_connection_options().
* Gets the result of a call to nm_client_add_and_activate_connection2().
*
* You can call nm_active_connection_get_connection() on the returned
* #NMActiveConnection to find the path of the created #NMConnection.
@ -1358,20 +1376,25 @@ nm_client_add_and_activate_connection_options (NMClient *client,
* failure, in which case @error will be set.
**/
NMActiveConnection *
nm_client_add_and_activate_connection_options_finish (NMClient *client,
GAsyncResult *result,
GError **error)
nm_client_add_and_activate_connection2_finish (NMClient *client,
GAsyncResult *result,
GVariant **out_result,
GError **error)
{
GSimpleAsyncResult *simple;
_NMActivateResult *r;
g_return_val_if_fail (NM_IS_CLIENT (client), NULL);
g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), NULL);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
if (g_simple_async_result_propagate_error (simple, error)) {
NM_SET_OUT (out_result, NULL);
return NULL;
else
return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
}
r = g_simple_async_result_get_op_res_gpointer (simple);
NM_SET_OUT (out_result, nm_g_variant_ref (r->add_and_activate_output));
return g_object_ref (r->active);
}
/**

View file

@ -340,18 +340,19 @@ NMActiveConnection *nm_client_add_and_activate_connection_finish (NMClient *clie
GError **error);
NM_AVAILABLE_IN_1_16
void nm_client_add_and_activate_connection_options (NMClient *client,
NMConnection *partial,
NMDevice *device,
const char *specific_object,
GVariant *options,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
void nm_client_add_and_activate_connection2 (NMClient *client,
NMConnection *partial,
NMDevice *device,
const char *specific_object,
GVariant *options,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
NM_AVAILABLE_IN_1_16
NMActiveConnection *nm_client_add_and_activate_connection_options_finish (NMClient *client,
GAsyncResult *result,
GError **error);
NMActiveConnection *nm_client_add_and_activate_connection2_finish (NMClient *client,
GAsyncResult *result,
GVariant **out_result,
GError **error);
gboolean nm_client_deactivate_connection (NMClient *client,
NMActiveConnection *active,

View file

@ -870,16 +870,49 @@ nm_manager_get_activating_connection (NMManager *manager)
return NM_MANAGER_GET_PRIVATE (manager)->activating_connection;
}
typedef enum {
ACTIVATE_TYPE_ACTIVATE_CONNECTION,
ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION,
ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION2,
} ActivateType;
typedef struct {
CList lst;
NMManager *manager;
GSimpleAsyncResult *simple;
GCancellable *cancellable;
gulong cancelled_id;
char *active_path;
char *new_connection_path;
GVariant *add_and_activate_output;
gulong cancelled_id;
ActivateType activate_type;
} ActivateInfo;
_NMActivateResult *
_nm_activate_result_new (NMActiveConnection *active,
GVariant *add_and_activate_output)
{
_NMActivateResult *r;
nm_assert (!add_and_activate_output || g_variant_is_of_type (add_and_activate_output, G_VARIANT_TYPE ("a{sv}")));
nm_assert (!add_and_activate_output || !g_variant_is_floating (add_and_activate_output));
r = g_slice_new (_NMActivateResult);
*r = (_NMActivateResult) {
.active = g_object_ref (active),
.add_and_activate_output = nm_g_variant_ref (add_and_activate_output),
};
return r;
}
void
_nm_activate_result_free (_NMActivateResult *result)
{
g_object_unref (result->active);
nm_g_variant_unref (result->add_and_activate_output);
g_slice_free (_NMActivateResult, result);
}
static void
activate_info_complete (ActivateInfo *info,
NMActiveConnection *active,
@ -889,12 +922,17 @@ activate_info_complete (ActivateInfo *info,
c_list_unlink_stale (&info->lst);
if (active)
g_simple_async_result_set_op_res_gpointer (info->simple, g_object_ref (active), g_object_unref);
else
if (active) {
g_simple_async_result_set_op_res_gpointer (info->simple,
_nm_activate_result_new (active,
info->add_and_activate_output),
(GDestroyNotify) _nm_activate_result_free);
} else
g_simple_async_result_set_from_error (info->simple, error);
g_simple_async_result_complete (info->simple);
nm_g_variant_unref (info->add_and_activate_output);
g_free (info->active_path);
g_free (info->new_connection_path);
g_object_unref (info->simple);
@ -1035,6 +1073,7 @@ nm_manager_activate_connection_async (NMManager *manager,
priv = NM_MANAGER_GET_PRIVATE (manager);
info = g_slice_new0 (ActivateInfo);
info->activate_type = ACTIVATE_TYPE_ACTIVATE_CONNECTION;
info->manager = manager;
info->simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data,
nm_manager_activate_connection_async);
@ -1058,14 +1097,16 @@ nm_manager_activate_connection_finish (NMManager *manager,
GError **error)
{
GSimpleAsyncResult *simple;
_NMActivateResult *r;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_activate_connection_async), NULL);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
return NULL;
else
return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
r = g_simple_async_result_get_op_res_gpointer (simple);
return g_object_ref (r->active);
}
static void
@ -1074,23 +1115,35 @@ add_activate_cb (GObject *object,
gpointer user_data)
{
ActivateInfo *info = user_data;
GError *error = NULL;
gs_free GError *error = NULL;
gboolean success;
if (nmdbus_manager_call_add_and_activate_connection_finish (NMDBUS_MANAGER (object),
NULL,
&info->active_path,
result, &error)) {
if (info->cancellable) {
info->cancelled_id = g_signal_connect (info->cancellable, "cancelled",
G_CALLBACK (activation_cancelled), info);
}
recheck_pending_activations (info->manager);
if (info->activate_type == ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION) {
success = nmdbus_manager_call_add_and_activate_connection_finish (NMDBUS_MANAGER (object),
NULL,
&info->active_path,
result,
&error);
} else {
success = nmdbus_manager_call_add_and_activate_connection2_finish (NMDBUS_MANAGER (object),
NULL,
&info->active_path,
&info->add_and_activate_output,
result,
&error);
}
if (!success) {
g_dbus_error_strip_remote_error (error);
activate_info_complete (info, NULL, error);
g_clear_error (&error);
return;
}
if (info->cancellable) {
info->cancelled_id = g_signal_connect (info->cancellable, "cancelled",
G_CALLBACK (activation_cancelled), info);
}
recheck_pending_activations (info->manager);
}
void
@ -1099,6 +1152,7 @@ nm_manager_add_and_activate_connection_async (NMManager *manager,
NMDevice *device,
const char *specific_object,
GVariant *options,
gboolean force_v2,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
@ -1106,6 +1160,7 @@ nm_manager_add_and_activate_connection_async (NMManager *manager,
NMManagerPrivate *priv;
GVariant *dict = NULL;
ActivateInfo *info;
ActivateType activate_type = ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION;
g_return_if_fail (NM_IS_MANAGER (manager));
g_return_if_fail (NM_IS_DEVICE (device));
@ -1128,32 +1183,61 @@ nm_manager_add_and_activate_connection_async (NMManager *manager,
dict = nm_connection_to_dbus (partial, NM_CONNECTION_SERIALIZE_ALL);
if (!dict)
dict = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
if (!options)
options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
if (force_v2) {
if (!options)
options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
activate_type = ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION2;
} else {
if (options) {
if (g_variant_n_children (options) > 0)
activate_type = ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION2;
else
nm_g_variant_unref_floating (options);
}
}
nmdbus_manager_call_add_and_activate_connection2 (priv->proxy,
dict,
nm_object_get_path (NM_OBJECT (device)),
specific_object ?: "/",
options,
cancellable,
add_activate_cb, info);
info->activate_type = activate_type;
if (activate_type == ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION2) {
nmdbus_manager_call_add_and_activate_connection2 (priv->proxy,
dict,
nm_object_get_path (NM_OBJECT (device)),
specific_object ?: "/",
options,
cancellable,
add_activate_cb,
info);
} else {
nmdbus_manager_call_add_and_activate_connection (priv->proxy,
dict,
nm_object_get_path (NM_OBJECT (device)),
specific_object ?: "/",
cancellable,
add_activate_cb,
info);
}
}
NMActiveConnection *
nm_manager_add_and_activate_connection_finish (NMManager *manager,
GAsyncResult *result,
GVariant **out_result,
GError **error)
{
GSimpleAsyncResult *simple;
_NMActivateResult *r;
g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), nm_manager_add_and_activate_connection_async), NULL);
simple = G_SIMPLE_ASYNC_RESULT (result);
if (g_simple_async_result_propagate_error (simple, error))
if (g_simple_async_result_propagate_error (simple, error)) {
NM_SET_OUT (out_result, NULL);
return NULL;
else
return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
}
r = g_simple_async_result_get_op_res_gpointer (simple);
NM_SET_OUT (out_result, nm_g_variant_ref (r->add_and_activate_output));
return g_object_ref (r->active);
}
static void

View file

@ -164,11 +164,13 @@ void nm_manager_add_and_activate_connection_async (NMManager *ma
NMDevice *device,
const char *specific_object,
GVariant *options,
gboolean force_v2,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
NMActiveConnection *nm_manager_add_and_activate_connection_finish (NMManager *manager,
GAsyncResult *result,
GVariant **out_result,
GError **error);
gboolean nm_manager_deactivate_connection (NMManager *manager,
@ -221,4 +223,18 @@ gboolean nm_manager_checkpoint_adjust_rollback_timeout_finish (NMManager *manage
GAsyncResult *result,
GError **error);
/*****************************************************************************/
typedef struct {
NMActiveConnection *active;
GVariant *add_and_activate_output;
} _NMActivateResult;
_NMActivateResult *_nm_activate_result_new (NMActiveConnection *active,
GVariant *add_and_activate_output);
void _nm_activate_result_free (_NMActivateResult *result);
/*****************************************************************************/
#endif /* __NM_MANAGER_H__ */

View file

@ -80,6 +80,7 @@ typedef enum {
ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_INTERNAL,
ASYNC_OP_TYPE_AC_AUTH_ACTIVATE_USER,
ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE,
ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2,
} AsyncOpType;
typedef struct {
@ -370,6 +371,7 @@ static void _internal_activation_auth_done (NMManager *self,
gboolean success,
const char *error_desc);
static void _add_and_activate_auth_done (NMManager *self,
AsyncOpType async_op_type,
NMActiveConnection *active,
NMConnection *connection,
GDBusMethodInvocation *invocation,
@ -486,6 +488,7 @@ _async_op_data_new_ac_auth_activate_user (NMManager *self,
static AsyncOpData *
_async_op_data_new_ac_auth_add_and_activate (NMManager *self,
AsyncOpType async_op_type,
NMActiveConnection *active_take,
GDBusMethodInvocation *invocation_take,
NMConnection *connection_take,
@ -493,8 +496,11 @@ _async_op_data_new_ac_auth_add_and_activate (NMManager *self,
{
AsyncOpData *async_op_data;
nm_assert (NM_IN_SET (async_op_type, ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE,
ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2));
async_op_data = g_slice_new0 (AsyncOpData);
async_op_data->async_op_type = ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE;
async_op_data->async_op_type = async_op_type;
async_op_data->self = g_object_ref (self);
async_op_data->ac_auth.active = active_take;
async_op_data->ac_auth.add_and_activate.invocation = invocation_take;
@ -535,7 +541,9 @@ _async_op_complete_ac_auth_cb (NMActiveConnection *active,
error_desc);
break;
case ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE:
case ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2:
_add_and_activate_auth_done (async_op_data->self,
async_op_data->async_op_type,
async_op_data->ac_auth.active,
async_op_data->ac_auth.add_and_activate.connection,
async_op_data->ac_auth.add_and_activate.invocation,
@ -5274,9 +5282,13 @@ activation_add_done (NMSettings *settings,
gs_free_error GError *local = NULL;
gpointer persist_ptr;
NMSettingsConnectionPersistMode persist;
gpointer async_op_type_ptr;
AsyncOpType async_op_type;
GVariant *result_floating;
nm_utils_user_data_unpack (user_data, &self, &active, &persist_ptr);
nm_utils_user_data_unpack (user_data, &self, &active, &persist_ptr, &async_op_type_ptr);
persist = GPOINTER_TO_INT (persist_ptr);
async_op_type = GPOINTER_TO_INT (async_op_type_ptr);
if (error)
goto fail;
@ -5295,10 +5307,17 @@ activation_add_done (NMSettings *settings,
"add-and-activate",
NULL);
g_dbus_method_invocation_return_value (context,
g_variant_new ("(oo)",
nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)),
nm_dbus_object_get_path (NM_DBUS_OBJECT (active))));
if (async_op_type == ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE) {
result_floating = g_variant_new ("(oo)",
nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)),
nm_dbus_object_get_path (NM_DBUS_OBJECT (active)));
} else {
result_floating = g_variant_new ("(ooa{sv})",
nm_dbus_object_get_path (NM_DBUS_OBJECT (new_connection)),
nm_dbus_object_get_path (NM_DBUS_OBJECT (active)),
g_variant_new_array (G_VARIANT_TYPE ("a{sv}"), NULL, 0));
}
g_dbus_method_invocation_return_value (context, result_floating);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD_ACTIVATE,
nm_active_connection_get_settings_connection (active),
@ -5327,6 +5346,7 @@ fail:
static void
_add_and_activate_auth_done (NMManager *self,
AsyncOpType async_op_type,
NMActiveConnection *active,
NMConnection *connection,
GDBusMethodInvocation *invocation,
@ -5364,7 +5384,8 @@ _add_and_activate_auth_done (NMManager *self,
activation_add_done,
nm_utils_user_data_pack (self,
g_object_ref (active),
GINT_TO_POINTER (persist)));
GINT_TO_POINTER (persist),
GINT_TO_POINTER (async_op_type)));
}
static void
@ -5391,11 +5412,16 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj,
gs_free NMConnection **conns = NULL;
NMSettingsConnectionPersistMode persist = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
gboolean bind_dbus_client = FALSE;
AsyncOpType async_op_type;
if (g_strcmp0 (method_info->parent.name, "AddAndActivateConnection2") == 0)
if (nm_streq (method_info->parent.name, "AddAndActivateConnection2")) {
async_op_type = ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE2;
g_variant_get (parameters, "(@a{sa{sv}}&o&o@a{sv})", &settings, &device_path, &specific_object_path, &options);
else
} else {
nm_assert (nm_streq (method_info->parent.name, "AddAndActivateConnection"));
async_op_type = ASYNC_OP_TYPE_AC_AUTH_ADD_AND_ACTIVATE;
g_variant_get (parameters, "(@a{sa{sv}}&o&o)", &settings, &device_path, &specific_object_path);
}
if (options) {
GVariantIter iter;
@ -5531,6 +5557,7 @@ impl_manager_add_and_activate_connection (NMDBusObject *obj,
incompl_conn,
_async_op_complete_ac_auth_cb,
_async_op_data_new_ac_auth_add_and_activate (self,
async_op_type,
active,
invocation,
incompl_conn,
@ -7892,6 +7919,7 @@ static const NMDBusInterfaceInfoExtended interface_info_manager = {
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("path", "o"),
NM_DEFINE_GDBUS_ARG_INFO ("active_connection", "o"),
NM_DEFINE_GDBUS_ARG_INFO ("result", "a{sv}"),
),
),
.handle = impl_manager_add_and_activate_connection,

View file

@ -1341,15 +1341,14 @@ class NetworkManager(ExportedObj):
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='a{sa{sv}}oo', out_signature='oo')
def AddAndActivateConnection(self, con_hash, devpath, specific_object):
return self.AddAndActivateConnection2(con_hash, devpath, specific_object, dict())
conpath, acpath, result = self.AddAndActivateConnection2(con_hash, devpath, specific_object, dict())
return (conpath, acpath)
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='a{sa{sv}}ooa{sv}', out_signature='oo')
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='a{sa{sv}}ooa{sv}', out_signature='ooa{sv}')
def AddAndActivateConnection2(self, con_hash, devpath, specific_object, options):
# TODO: Do some processing of the "options" parameter.
device = self.find_device_first(path = devpath, require = BusErr.UnknownDeviceException)
conpath = gl.settings.AddConnection(con_hash)
return (conpath, self.ActivateConnection(conpath, devpath, specific_object))
return (conpath, self.ActivateConnection(conpath, devpath, specific_object), [])
@dbus.service.method(dbus_interface=IFACE_NM, in_signature='o', out_signature='')
def DeactivateConnection(self, active_connection):