diff options
author | Beniamino Galvani <bgalvani@redhat.com> | 2019-09-17 09:34:44 +0200 |
---|---|---|
committer | Beniamino Galvani <bgalvani@redhat.com> | 2019-09-17 09:34:44 +0200 |
commit | 686c6b003237c3fa6a76823f377d815a4b11a483 (patch) | |
tree | 9953a2620c89ff86eb89c464cd41c3f387e7a3cf | |
parent | c177a38e88021392412a796154d47168b8b17598 (diff) | |
parent | 5afcf9c045adc883ddeec5f1671fc3dd56d79c18 (diff) | |
download | NetworkManager-686c6b003237c3fa6a76823f377d815a4b11a483.tar.gz |
merge: branch 'bg/cli-general-reload'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/265
-rw-r--r-- | clients/cli/common.c | 46 | ||||
-rw-r--r-- | clients/cli/common.h | 8 | ||||
-rw-r--r-- | clients/cli/connections.c | 15 | ||||
-rw-r--r-- | clients/cli/general.c | 97 | ||||
-rw-r--r-- | data/NetworkManager.service.in | 2 | ||||
-rw-r--r-- | libnm-core/nm-dbus-interface.h | 28 | ||||
-rw-r--r-- | libnm/libnm.ver | 3 | ||||
-rw-r--r-- | libnm/nm-client.c | 82 | ||||
-rw-r--r-- | libnm/nm-client.h | 11 | ||||
-rw-r--r-- | libnm/nm-manager.c | 58 | ||||
-rw-r--r-- | libnm/nm-manager.h | 9 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/nm-config-data.h | 19 | ||||
-rw-r--r-- | src/nm-manager.c | 8 |
14 files changed, 359 insertions, 29 deletions
diff --git a/clients/cli/common.c b/clients/cli/common.c index eeef9b64c9..9b2d07aacd 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.c @@ -1421,10 +1421,56 @@ nmc_error_get_simple_message (GError *error) /* Return a clear message instead of the obscure D-Bus policy error */ if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_ACCESS_DENIED)) return _("access denied"); + if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) + return _("NetworkManager is not running"); else return error->message; } +GVariant * +nmc_dbus_call_sync (NmCli *nmc, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GError **error) +{ + gs_unref_object GDBusConnection *connection = NULL; + gs_free_error GError *local = NULL; + GVariant *result; + + if (nmc->timeout == -1) + nmc->timeout = 90; + + connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &local); + if (!connection) { + g_set_error (error, + NMCLI_ERROR, + NMC_RESULT_ERROR_UNKNOWN, + _("Error: error connecting to system bus: %s"), + local->message); + return NULL; + } + + result = g_dbus_connection_call_sync (connection, + "org.freedesktop.NetworkManager", + object_path, + interface_name, + method_name, + parameters, + reply_type, + G_DBUS_CALL_FLAGS_NONE, + nmc->timeout * 1000, + NULL, + error); + + if (error && *error) + g_dbus_error_strip_remote_error (*error); + + return result; +} + /*****************************************************************************/ NM_UTILS_LOOKUP_STR_DEFINE (nm_connectivity_to_string, NMConnectivityState, diff --git a/clients/cli/common.h b/clients/cli/common.h index 40dee6d0f4..50574a1baf 100644 --- a/clients/cli/common.h +++ b/clients/cli/common.h @@ -89,4 +89,12 @@ extern const NmcMetaGenericInfo *const metagen_dhcp_config[]; const char *nm_connectivity_to_string (NMConnectivityState connectivity); +GVariant *nmc_dbus_call_sync (NmCli *nmc, + const char *object_path, + const char *interface_name, + const char *method_name, + GVariant *parameters, + const GVariantType *reply_type, + GError **error); + #endif /* NMC_COMMON_H */ diff --git a/clients/cli/connections.c b/clients/cli/connections.c index 8e848ffd19..003400d5fe 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -8845,17 +8845,24 @@ do_connection_monitor (NmCli *nmc, int argc, char **argv) static NMCResultCode do_connection_reload (NmCli *nmc, int argc, char **argv) { - GError *error = NULL; + gs_unref_variant GVariant *result = NULL; + gs_free_error GError *error = NULL; next_arg (nmc, &argc, &argv, NULL); if (nmc->complete) return nmc->return_value; - if (!nm_client_reload_connections (nmc->client, NULL, &error)) { + result = nmc_dbus_call_sync (nmc, + "/org/freedesktop/NetworkManager/Settings", + "org.freedesktop.NetworkManager.Settings", + "ReloadConnections", + g_variant_new ("()"), + G_VARIANT_TYPE("(b)"), + &error); + if (error) { g_string_printf (nmc->return_text, _("Error: failed to reload connections: %s."), nmc_error_get_simple_message (error)); nmc->return_value = NMC_RESULT_ERROR_UNKNOWN; - g_clear_error (&error); } return nmc->return_value; @@ -9245,7 +9252,7 @@ static const NMCCommand connection_cmds[] = { { "add", do_connection_add, usage_connection_add, TRUE, TRUE }, { "edit", do_connection_edit, usage_connection_edit, TRUE, TRUE }, { "delete", do_connection_delete, usage_connection_delete, TRUE, TRUE }, - { "reload", do_connection_reload, usage_connection_reload, TRUE, TRUE }, + { "reload", do_connection_reload, usage_connection_reload, FALSE, FALSE }, { "load", do_connection_load, usage_connection_load, TRUE, TRUE }, { "modify", do_connection_modify, usage_connection_modify, TRUE, TRUE }, { "clone", do_connection_clone, usage_connection_clone, TRUE, TRUE }, diff --git a/clients/cli/general.c b/clients/cli/general.c index b70edf9217..14502111d7 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -354,6 +354,38 @@ usage_general_permissions (void) } static void +usage_general_reload (void) +{ + g_printerr (_("Usage: nmcli general reload { ARGUMENTS | help }\n" + "\n" + "ARGUMENTS := [<flag>[,<flag>...]]\n" + "\n" + "Reload NetworkManager's configuration and perform certain updates, like\n" + "flushing caches or rewriting external state to disk. This is similar to\n" + "sending SIGHUP to NetworkManager but it allows for more fine-grained\n" + "control over what to reload through the flags argument. It also allows\n" + "non-root access via PolicyKit and contrary to signals it is synchronous.\n" + "\n" + "Available flags are:\n" + "\n" + " 'conf' Reload the NetworkManager.conf configuration from\n" + " disk. Note that this does not include connections, which\n" + " can be reloaded through 'nmcli connection reload' instead.\n" + "\n" + " 'dns-rc' Update DNS configuration, which usually involves writing\n" + " /etc/resolv.conf anew.\n" + "\n" + " 'dns-full' Restart the DNS plugin. This is for example useful when\n" + " using dnsmasq plugin, which uses additional configuration\n" + " in /etc/NetworkManager/dnsmasq.d. If you edit those files,\n" + " you can restart the DNS plugin. This action shortly\n" + " interrupts name resolution.\n" + "\n" + "With no flags, everything that is supported is reloaded, which is\n" + "identical to sending a SIGHUP.\n")); +} + +static void usage_general_logging (void) { g_printerr (_("Usage: nmcli general logging { ARGUMENTS | help }\n" @@ -596,6 +628,70 @@ show_nm_permissions (NmCli *nmc) } static NMCResultCode +do_general_reload (NmCli *nmc, int argc, char **argv) +{ + gs_unref_variant GVariant *result = NULL; + gs_free_error GError *error = NULL; + gs_free const char **values = NULL; + gs_free char *err_token = NULL; + gs_free char *joined = NULL; + int flags = 0; + + next_arg (nmc, &argc, &argv, NULL); + + if (nmc->complete) { + if (argc == 0) + return nmc->return_value; + + if (argc == 1) { + values = nm_utils_enum_get_values (nm_manager_reload_flags_get_type (), + NM_MANAGER_RELOAD_FLAG_CONF, + NM_MANAGER_RELOAD_FLAG_ALL); + nmc_complete_strv (*argv, -1, values); + } + return nmc->return_value; + } + + if (argc > 0) { + if (!nm_utils_enum_from_str (nm_manager_reload_flags_get_type (), *argv, &flags, &err_token)) { + values = nm_utils_enum_get_values (nm_manager_reload_flags_get_type (), + NM_MANAGER_RELOAD_FLAG_CONF, + NM_MANAGER_RELOAD_FLAG_ALL); + joined = g_strjoinv (",", (char **) values); + g_string_printf (nmc->return_text, + _("Error: invalid reload flag '%s'. Allowed flags are: %s"), + err_token, + joined); + return NMC_RESULT_ERROR_USER_INPUT; + } + argc--; + argv++; + } + + if (argc > 0) { + g_string_printf (nmc->return_text, _("Error: extra argument '%s'"), *argv); + return NMC_RESULT_ERROR_USER_INPUT; + } + + result = nmc_dbus_call_sync (nmc, + "/org/freedesktop/NetworkManager", + "org.freedesktop.NetworkManager", + "Reload", + g_variant_new ("(u)", flags), + G_VARIANT_TYPE("()"), + &error); + + if (error) { + g_string_printf (nmc->return_text, + _("Error: failed to reload: %s"), + nmc_error_get_simple_message (error)); + return NMC_RESULT_ERROR_UNKNOWN; + } + + return nmc->return_value; +} + +static NMCResultCode do_general_permissions (NmCli *nmc, int argc, char **argv) { next_arg (nmc, &argc, &argv, NULL); @@ -772,6 +868,7 @@ static const NMCCommand general_cmds[] = { { "hostname", do_general_hostname, usage_general_hostname, TRUE, TRUE }, { "permissions", do_general_permissions, usage_general_permissions, TRUE, TRUE }, { "logging", do_general_logging, usage_general_logging, TRUE, TRUE }, + { "reload", do_general_reload, usage_general_reload, FALSE, FALSE }, { NULL, do_general_status, usage_general, TRUE, TRUE }, }; diff --git a/data/NetworkManager.service.in b/data/NetworkManager.service.in index 2f442bf233..91ebd9a36e 100644 --- a/data/NetworkManager.service.in +++ b/data/NetworkManager.service.in @@ -8,7 +8,7 @@ Before=network.target @DISTRO_NETWORK_SERVICE@ [Service] Type=dbus BusName=org.freedesktop.NetworkManager -ExecReload=/usr/bin/dbus-send --print-reply --system --type=method_call --dest=org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager.Reload uint32:0 +ExecReload=/usr/bin/busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager Reload u 0 #ExecReload=/bin/kill -HUP $MAINPID ExecStart=@sbindir@/NetworkManager --no-daemon Restart=on-failure diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h index f00506e2d7..1e7f377d12 100644 --- a/libnm-core/nm-dbus-interface.h +++ b/libnm-core/nm-dbus-interface.h @@ -1122,4 +1122,32 @@ typedef enum { NM_TERNARY_TRUE = 1, } NMTernary; +/** + * NMManagerReloadFlags: + * @NM_MANAGER_RELOAD_FLAG_NONE: an alias for numeric zero, no flags set. This + * reloads everything that is supported and is identical to a SIGHUP. + * @NM_MANAGER_RELOAD_FLAG_CONF: reload the NetworkManager.conf configuration + * from disk. Note that this does not include connections, which can be + * reloaded via Setting's ReloadConnections(). + * @NM_MANAGER_RELOAD_FLAG_DNS_RC: update DNS configuration, which usually + * involves writing /etc/resolv.conf anew. + * @NM_MANAGER_RELOAD_FLAG_DNS_FULL: means to restart the DNS plugin. This + * is for example useful when using dnsmasq plugin, which uses additional + * configuration in /etc/NetworkManager/dnsmasq.d. If you edit those files, + * you can restart the DNS plugin. This action shortly interrupts name + * resolution. + * @NM_MANAGER_RELOAD_FLAG_ALL: all flags. + * + * Flags for the manager Reload() call. + * + * Since: 1.22 + */ +typedef enum { /*< flags >*/ + NM_MANAGER_RELOAD_FLAG_NONE = 0, /*< skip >*/ + NM_MANAGER_RELOAD_FLAG_CONF = 0x1, + NM_MANAGER_RELOAD_FLAG_DNS_RC = 0x2, + NM_MANAGER_RELOAD_FLAG_DNS_FULL = 0x4, + NM_MANAGER_RELOAD_FLAG_ALL = 0x7, /*< skip >*/ +} NMManagerReloadFlags; + #endif /* __NM_DBUS_INTERFACE_H__ */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 68eaf745e9..e9a69d6881 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -1631,5 +1631,8 @@ global: libnm_1_22_0 { global: + nm_client_reload; + nm_client_reload_finish; + nm_manager_reload_flags_get_type; nm_setting_gsm_get_auto_config; } libnm_1_20_0; diff --git a/libnm/nm-client.c b/libnm/nm-client.c index d744406bb9..26bf91f5fa 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -2737,6 +2737,88 @@ nm_client_checkpoint_adjust_rollback_timeout_finish (NMClient *client, error); } +static void +reload_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + gs_unref_object GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nm_manager_reload_finish (NM_MANAGER (object), result, &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else + g_simple_async_result_take_error (simple, error); + + g_simple_async_result_complete (simple); +} + +/** + * nm_client_reload: + * @client: the %NMClient + * @flags: flags indicating what to reload. + * @cancellable: a #GCancellable, or %NULL + * @callback: (scope async): callback to be called when the add operation completes + * @user_data: (closure): caller-specific data passed to @callback + * + * Reload NetworkManager's configuration and perform certain updates, like + * flushing caches or rewriting external state to disk. This is similar to + * sending SIGHUP to NetworkManager but it allows for more fine-grained control + * over what to reload (see @flags). It also allows non-root access via + * PolicyKit and contrary to signals it is synchronous. + * + * Since: 1.22 + **/ +void +nm_client_reload (NMClient *client, + NMManagerReloadFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + GError *error = NULL; + + g_return_if_fail (NM_IS_CLIENT (client)); + + if (!_nm_client_check_nm_running (client, &error)) { + g_simple_async_report_take_gerror_in_idle (G_OBJECT (client), callback, user_data, error); + return; + } + + simple = g_simple_async_result_new (G_OBJECT (client), callback, user_data, + nm_client_reload); + if (cancellable) + g_simple_async_result_set_check_cancellable (simple, cancellable); + nm_manager_reload (NM_CLIENT_GET_PRIVATE (client)->manager, + flags, + cancellable, reload_cb, simple); +} + +/** + * nm_client_reload_finish: + * @client: an #NMClient + * @result: the result passed to the #GAsyncReadyCallback + * @error: location for a #GError, or %NULL + * + * Gets the result of a call to nm_client_reload(). + * + * Returns: %TRUE on success or %FALSE on failure. + * + * Since: 1.22 + **/ +gboolean +nm_client_reload_finish (NMClient *client, + GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (NM_IS_CLIENT (client), FALSE); + g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE); + + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), + error); +} + /****************************************************************/ /* Object Initialization */ /****************************************************************/ diff --git a/libnm/nm-client.h b/libnm/nm-client.h index 4989800547..f8ffd52508 100644 --- a/libnm/nm-client.h +++ b/libnm/nm-client.h @@ -475,6 +475,17 @@ gboolean nm_client_checkpoint_adjust_rollback_timeout_finish (NMClient *client, GAsyncResult *result, GError **error); +NM_AVAILABLE_IN_1_22 +void nm_client_reload (NMClient *client, + NMManagerReloadFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +NM_AVAILABLE_IN_1_22 +gboolean nm_client_reload_finish (NMClient *client, + GAsyncResult *result, + GError **error); + G_END_DECLS #endif /* __NM_CLIENT_H__ */ diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c index de1fa04e40..b4111cd040 100644 --- a/libnm/nm-manager.c +++ b/libnm/nm-manager.c @@ -1684,6 +1684,64 @@ nm_manager_checkpoint_adjust_rollback_timeout_finish (NMManager *manager, return !g_simple_async_result_propagate_error (simple, error); } +static void +reload_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + gs_unref_object GSimpleAsyncResult *simple = user_data; + GError *error = NULL; + + if (nmdbus_manager_call_reload_finish (NMDBUS_MANAGER (object), + result, + &error)) + g_simple_async_result_set_op_res_gboolean (simple, TRUE); + else { + g_dbus_error_strip_remote_error (error); + g_simple_async_result_take_error (simple, error); + } + g_simple_async_result_complete (simple); +} + +void +nm_manager_reload (NMManager *manager, + NMManagerReloadFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + + g_return_if_fail (NM_IS_MANAGER (manager)); + + simple = g_simple_async_result_new (G_OBJECT (manager), callback, user_data, + nm_manager_reload); + if (cancellable) + g_simple_async_result_set_check_cancellable (simple, cancellable); + + nmdbus_manager_call_reload (NM_MANAGER_GET_PRIVATE (manager)->proxy, + flags, + cancellable, + reload_cb, + simple); + +} + +gboolean +nm_manager_reload_finish (NMManager *manager, + GAsyncResult *result, + GError **error) +{ + GSimpleAsyncResult *simple; + + g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (manager), + nm_manager_reload), + FALSE); + + simple = G_SIMPLE_ASYNC_RESULT (result); + return !g_simple_async_result_propagate_error (simple, error); +} + /*****************************************************************************/ static void diff --git a/libnm/nm-manager.h b/libnm/nm-manager.h index 0970c2e382..9bbbe53af4 100644 --- a/libnm/nm-manager.h +++ b/libnm/nm-manager.h @@ -224,4 +224,13 @@ void _nm_activate_result_free (_NMActivateResult *result); /*****************************************************************************/ +void nm_manager_reload (NMManager *manager, + NMManagerReloadFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean nm_manager_reload_finish (NMManager *manager, + GAsyncResult *result, + GError **error); + #endif /* __NM_MANAGER_H__ */ diff --git a/src/main.c b/src/main.c index 8267a16670..86b87dc971 100644 --- a/src/main.c +++ b/src/main.c @@ -89,7 +89,7 @@ _init_nm_debug (NMConfig *config) debug = nm_config_data_get_value (nm_config_get_data_orig (config), NM_CONFIG_KEYFILE_GROUP_MAIN, NM_CONFIG_KEYFILE_KEY_MAIN_DEBUG, - NM_MANAGER_RELOAD_FLAGS_NONE); + NM_CONFIG_GET_VALUE_NONE); flags = nm_utils_parse_debug_string (env, keys, G_N_ELEMENTS (keys)); flags |= nm_utils_parse_debug_string (debug, keys, G_N_ELEMENTS (keys)); diff --git a/src/nm-config-data.h b/src/nm-config-data.h index 57f97020d0..76d4432ce9 100644 --- a/src/nm-config-data.h +++ b/src/nm-config-data.h @@ -25,25 +25,6 @@ #define NM_CONFIG_DATA_NO_AUTO_DEFAULT "no-auto-default" #define NM_CONFIG_DATA_DNS_MODE "dns" -/* The flags for Reload. Currently these are internal defines, - * only their numeric value matters and must be stable as - * they are public API! Also, the enum must fit in uint32. */ -enum { /*< skip >*/ - NM_MANAGER_RELOAD_FLAGS_NONE = 0, - - /* reload the configuration from disk */ - NM_MANAGER_RELOAD_FLAGS_CONF = (1LL << 0), - - /* write DNS configuration to resolv.conf */ - NM_MANAGER_RELOAD_FLAGS_DNS_RC = (1LL << 1), - - /* restart the DNS plugin (includes DNS_RC) */ - NM_MANAGER_RELOAD_FLAGS_DNS_FULL = (1LL << 2), - - _NM_MANAGER_RELOAD_FLAGS_ALL, - NM_MANAGER_RELOAD_FLAGS_ALL = ((_NM_MANAGER_RELOAD_FLAGS_ALL - 1) << 1) - 1, -}; - typedef enum { /*< flags >*/ NM_CONFIG_GET_VALUE_NONE = 0, diff --git a/src/nm-manager.c b/src/nm-manager.c index 6d4fb0f55d..6a01426753 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -1155,16 +1155,16 @@ _reload_auth_cb (NMAuthChain *chain, NM_MANAGER_ERROR_PERMISSION_DENIED, "Not authorized to reload configuration"); } else { - if (NM_FLAGS_ANY (flags, ~NM_MANAGER_RELOAD_FLAGS_ALL)) { + if (NM_FLAGS_ANY (flags, ~NM_MANAGER_RELOAD_FLAG_ALL)) { /* invalid flags */ } else if (flags == 0) reload_type = NM_CONFIG_CHANGE_CAUSE_SIGHUP; else { - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_CONF)) + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_CONF)) reload_type |= NM_CONFIG_CHANGE_CAUSE_CONF; - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_DNS_RC)) + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_DNS_RC)) reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_RC; - if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAGS_DNS_FULL)) + if (NM_FLAGS_HAS (flags, NM_MANAGER_RELOAD_FLAG_DNS_FULL)) reload_type |= NM_CONFIG_CHANGE_CAUSE_DNS_FULL; } |