device: fix taking over device after modifying external connection

For externally managed interfaces, we create an in-memory connection
and keep the device with sys-iface-state=external.

When the user actively modifies the connection, we persist it to
storage. But we also must take over managing the device.

One problem is that nm_device_reapply() errors out if the device
is still activating. It's unclear how to reapply the connection
while the device is in the process of activation. So, if the user
modifies the created connection very quickly, reapplying the settings
will fail.

https://bugzilla.redhat.com/show_bug.cgi?id=1462223
This commit is contained in:
Thomas Haller
2017-06-16 13:06:26 +02:00
parent b84da25713
commit 10c0632df0
3 changed files with 32 additions and 5 deletions

View File

@@ -9099,10 +9099,12 @@ check_and_reapply_connection (NMDevice *self,
NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS,
&diffs); &diffs);
if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ())) if (audit_args) {
*audit_args = nm_utils_format_con_diff_for_audit (diffs); if (diffs && nm_audit_manager_audit_enabled (nm_audit_manager_get ()))
else *audit_args = nm_utils_format_con_diff_for_audit (diffs);
*audit_args = NULL; else
*audit_args = NULL;
}
/************************************************************************** /**************************************************************************
* check for unsupported changes and reject to reapply * check for unsupported changes and reject to reapply
@@ -9204,6 +9206,20 @@ check_and_reapply_connection (NMDevice *self,
return TRUE; return TRUE;
} }
gboolean
nm_device_reapply (NMDevice *self,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_DEVICE (self), FALSE);
return check_and_reapply_connection (self,
connection,
0,
NULL,
error);
}
typedef struct { typedef struct {
NMConnection *connection; NMConnection *connection;
guint64 version_id; guint64 version_id;

View File

@@ -700,6 +700,9 @@ const NMPlatformIP6Route *nm_device_get_ip6_default_route (NMDevice *self, gbool
void nm_device_spawn_iface_helper (NMDevice *self); void nm_device_spawn_iface_helper (NMDevice *self);
gboolean nm_device_reapply (NMDevice *self,
NMConnection *connection,
GError **error);
void nm_device_reapply_settings_immediately (NMDevice *self); void nm_device_reapply_settings_immediately (NMDevice *self);
void nm_device_update_firewall_zone (NMDevice *self); void nm_device_update_firewall_zone (NMDevice *self);

View File

@@ -793,6 +793,8 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection,
GParamSpec *param, GParamSpec *param,
NMActiveConnection *self) NMActiveConnection *self)
{ {
GError *error = NULL;
nm_assert (NM_IS_ACTIVE_CONNECTION (self)); nm_assert (NM_IS_ACTIVE_CONNECTION (self));
nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection)); nm_assert (NM_IS_SETTINGS_CONNECTION (settings_connection));
nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL); nm_assert (nm_active_connection_get_activation_type (self) == NM_ACTIVATION_TYPE_EXTERNAL);
@@ -802,7 +804,13 @@ _settings_connection_notify_flags (NMSettingsConnection *settings_connection,
return; return;
_set_activation_type_managed (self); _set_activation_type_managed (self);
nm_device_reapply_settings_immediately (nm_active_connection_get_device (self)); if (!nm_device_reapply (nm_active_connection_get_device (self),
NM_CONNECTION (nm_active_connection_get_settings_connection (self)),
&error)) {
_LOGW ("failed to reapply new device settings on previously externally managed device: %s",
error->message);
g_error_free (error);
}
} }
/*****************************************************************************/ /*****************************************************************************/