cli: fix saving connections in the connection editor
- Main command loop was moved to run in a separate thread (using GThread). Otherwise glib main loop would be blocked in processing D-Bus and other events. - Handle creating new vs. updating already saved connection.
This commit is contained in:
@@ -3654,6 +3654,44 @@ editor_sub_usage (const char *command)
|
|||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static gboolean nmc_editor_cb_called;
|
||||||
|
static GError *nmc_editor_error;
|
||||||
|
static GMutex nmc_editor_mutex;
|
||||||
|
static GCond nmc_editor_cond;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Store 'error' to shared 'nmc_editor_error' and signal the condition
|
||||||
|
* so that the 'editor-thread' thread could process that.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
set_and_signal_error (GError *error)
|
||||||
|
{
|
||||||
|
g_mutex_lock (&nmc_editor_mutex);
|
||||||
|
nmc_editor_cb_called = TRUE;
|
||||||
|
nmc_editor_error = error ? g_error_copy (error) : NULL;
|
||||||
|
g_cond_signal (&nmc_editor_cond);
|
||||||
|
g_mutex_unlock (&nmc_editor_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_connection_editor_cb (NMRemoteSettings *settings,
|
||||||
|
NMRemoteConnection *connection,
|
||||||
|
GError *error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
set_and_signal_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_connection_editor_cb (NMRemoteConnection *connection,
|
||||||
|
GError *error,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
set_and_signal_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_property_description (NMSetting *setting, const char *prop_name)
|
print_property_description (NMSetting *setting, const char *prop_name)
|
||||||
{
|
{
|
||||||
@@ -3997,6 +4035,7 @@ menu_switch_to_level1 (NmcEditorMenuContext *menu_ctx,
|
|||||||
static gboolean
|
static gboolean
|
||||||
editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type)
|
editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_type)
|
||||||
{
|
{
|
||||||
|
NMRemoteConnection *rem_con = NULL;
|
||||||
NmcEditorMainCmd cmd;
|
NmcEditorMainCmd cmd;
|
||||||
char *cmd_user;
|
char *cmd_user;
|
||||||
gboolean cmd_loop = TRUE;
|
gboolean cmd_loop = TRUE;
|
||||||
@@ -4022,6 +4061,9 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
|
|||||||
menu_ctx.valid_props_str = NULL;
|
menu_ctx.valid_props_str = NULL;
|
||||||
|
|
||||||
while (cmd_loop) {
|
while (cmd_loop) {
|
||||||
|
if (!rem_con)
|
||||||
|
rem_con = nm_remote_settings_get_connection_by_uuid (nmc->system_settings,
|
||||||
|
nm_connection_get_uuid (connection));
|
||||||
cmd_user = readline_x (menu_ctx.main_prompt);
|
cmd_user = readline_x (menu_ctx.main_prompt);
|
||||||
if (!cmd_user || *cmd_user == '\0')
|
if (!cmd_user || *cmd_user == '\0')
|
||||||
continue;
|
continue;
|
||||||
@@ -4293,21 +4335,45 @@ editor_menu_main (NmCli *nmc, NMConnection *connection, const char *connection_t
|
|||||||
case NMC_EDITOR_MAIN_CMD_SAVE:
|
case NMC_EDITOR_MAIN_CMD_SAVE:
|
||||||
/* Save the connection */
|
/* Save the connection */
|
||||||
if (nm_connection_verify (connection, &err1)) {
|
if (nm_connection_verify (connection, &err1)) {
|
||||||
info = g_malloc0 (sizeof (AddConnectionInfo));
|
if (!rem_con) {
|
||||||
info->nmc = nmc;
|
/* Tell the settings service to add the new connection */
|
||||||
info->con_name = g_strdup (nm_connection_get_id (connection));
|
info = g_malloc0 (sizeof (AddConnectionInfo));
|
||||||
//info->device = device;
|
info->nmc = nmc;
|
||||||
|
info->con_name = g_strdup (nm_connection_get_id (connection));
|
||||||
|
nm_remote_settings_add_connection (nmc->system_settings,
|
||||||
|
connection,
|
||||||
|
add_connection_editor_cb,
|
||||||
|
info);
|
||||||
|
} else {
|
||||||
|
/* Save/update already saved (existing) connection */
|
||||||
|
nm_connection_replace_settings_from_connection (NM_CONNECTION (rem_con),
|
||||||
|
connection,
|
||||||
|
NULL);
|
||||||
|
nm_remote_connection_commit_changes (rem_con,
|
||||||
|
update_connection_editor_cb,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* Tell the settings service to add the new connection */
|
g_mutex_lock (&nmc_editor_mutex);
|
||||||
nm_remote_settings_add_connection (nmc->system_settings,
|
//FIXME: add also a timeout for cases the callback is not called
|
||||||
connection,
|
while (!nmc_editor_cb_called)
|
||||||
add_connection_cb,
|
g_cond_wait (&nmc_editor_cond, &nmc_editor_mutex);
|
||||||
info);
|
|
||||||
|
|
||||||
// FIXME: we should run cmd loop in a thread of something,
|
if (nmc_editor_error) {
|
||||||
// because the current way blocks glib main loop, and thus D-Bus
|
printf (_("Error: Failed to save '%s' (%s) connection: (%d) %s\n"),
|
||||||
// callbacks (and all other events) can't be processed !!!
|
nm_connection_get_id (connection),
|
||||||
|
nm_connection_get_uuid (connection),
|
||||||
|
nmc_editor_error->code, nmc_editor_error->message);
|
||||||
|
|
||||||
|
g_error_free (nmc_editor_error);
|
||||||
|
} else
|
||||||
|
printf (_("Connection '%s' (%s) sucessfully saved.\n"),
|
||||||
|
nm_connection_get_id (connection),
|
||||||
|
nm_connection_get_uuid (connection));
|
||||||
|
|
||||||
|
nmc_editor_cb_called = FALSE;
|
||||||
|
nmc_editor_error = NULL;
|
||||||
|
g_mutex_unlock (&nmc_editor_mutex);
|
||||||
} else
|
} else
|
||||||
printf (_("Error: connection verification failed: %s\n"),
|
printf (_("Error: connection verification failed: %s\n"),
|
||||||
err1 ? err1->message : _("(unknown)"));
|
err1 ? err1->message : _("(unknown)"));
|
||||||
@@ -4624,7 +4690,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
|
|||||||
if (connection)
|
if (connection)
|
||||||
g_object_unref (connection);
|
g_object_unref (connection);
|
||||||
|
|
||||||
nmc->should_wait = FALSE;
|
nmc->should_wait = TRUE;
|
||||||
return nmc->return_value;
|
return nmc->return_value;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -4787,6 +4853,35 @@ do_connection_reload (NmCli *nmc, int argc, char **argv)
|
|||||||
return nmc->return_value;
|
return nmc->return_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NmCli *nmc;
|
||||||
|
int argc;
|
||||||
|
char **argv;
|
||||||
|
} NmcEditorThreadData;
|
||||||
|
|
||||||
|
static GThread *editor_thread;
|
||||||
|
static NmcEditorThreadData editor_thread_data;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to run do_connection_edit() in a thread so that
|
||||||
|
* glib main loop is not blocked and could receive and process D-Bus
|
||||||
|
* return messages.
|
||||||
|
*/
|
||||||
|
static gpointer
|
||||||
|
connection_editor_thread_func (gpointer data)
|
||||||
|
{
|
||||||
|
NmcEditorThreadData *td = (NmcEditorThreadData *) data;
|
||||||
|
|
||||||
|
/* run editor for editing/adding connections */
|
||||||
|
td->nmc->return_value = do_connection_edit (td->nmc, td->argc, td->argv);
|
||||||
|
|
||||||
|
/* quit glib main loop now that we are with this thread */
|
||||||
|
quit ();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static NMCResultCode
|
static NMCResultCode
|
||||||
parse_cmd (NmCli *nmc, int argc, char **argv)
|
parse_cmd (NmCli *nmc, int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -4827,7 +4922,11 @@ parse_cmd (NmCli *nmc, int argc, char **argv)
|
|||||||
nmc->return_value = do_connection_add (nmc, argc-1, argv+1);
|
nmc->return_value = do_connection_add (nmc, argc-1, argv+1);
|
||||||
}
|
}
|
||||||
else if (matches(*argv, "edit") == 0) {
|
else if (matches(*argv, "edit") == 0) {
|
||||||
nmc->return_value = do_connection_edit (nmc, argc-1, argv+1);
|
editor_thread_data.nmc = nmc;
|
||||||
|
editor_thread_data.argc = argc - 1;
|
||||||
|
editor_thread_data.argv = argv + 1;
|
||||||
|
editor_thread = g_thread_new ("editor-thread", connection_editor_thread_func, &editor_thread_data);
|
||||||
|
g_thread_unref (editor_thread);
|
||||||
}
|
}
|
||||||
else if (matches(*argv, "delete") == 0) {
|
else if (matches(*argv, "delete") == 0) {
|
||||||
nmc->return_value = do_connection_delete (nmc, argc-1, argv+1);
|
nmc->return_value = do_connection_delete (nmc, argc-1, argv+1);
|
||||||
|
Reference in New Issue
Block a user