NetworkManager/src/settings/nm-settings.c

3549 lines
122 KiB
C
Raw Normal View History

/* NetworkManager system settings service
*
* Søren Sandmann <sandmann@daimi.au.dk>
* Dan Williams <dcbw@redhat.com>
* Tambet Ingo <tambet@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* (C) Copyright 2007 - 2011 Red Hat, Inc.
* (C) Copyright 2008 Novell, Inc.
*/
#include "nm-default.h"
#include "nm-settings.h"
#include <unistd.h>
#include <sys/stat.h>
#include <gmodule.h>
#include <pwd.h>
#if HAVE_SELINUX
#include <selinux/selinux.h>
#endif
shared: build helper "libnm-libnm-core-{intern|aux}.la" library for libnm-core "libnm-core" implements common functionality for "NetworkManager" and "libnm". Note that clients like "nmcli" cannot access the internal API provided by "libnm-core". So, if nmcli wants to do something that is also done by "libnm-core", , "libnm", or "NetworkManager", the code would have to be duplicated. Instead, such code can be in "libnm-libnm-core-{intern|aux}.la". Note that: 0) "libnm-libnm-core-intern.la" is used by libnm-core itsself. On the other hand, "libnm-libnm-core-aux.la" is not used by libnm-core, but provides utilities on top of it. 1) they both extend "libnm-core" with utlities that are not public API of libnm itself. Maybe part of the code should one day become public API of libnm. On the other hand, this is code for which we may not want to commit to a stable interface or which we don't want to provide as part of the API. 2) "libnm-libnm-core-intern.la" is statically linked by "libnm-core" and thus directly available to "libnm" and "NetworkManager". On the other hand, "libnm-libnm-core-aux.la" may be used by "libnm" and "NetworkManager". Both libraries may be statically linked by libnm clients (like nmcli). 3) it must only use glib, libnm-glib-aux.la, and the public API of libnm-core. This is important: it must not use "libnm-core/nm-core-internal.h" nor "libnm-core/nm-utils-private.h" so the static library is usable by nmcli which couldn't access these. Note that "shared/nm-meta-setting.c" is an entirely different case, because it behaves differently depending on whether linking against "libnm-core" or the client programs. As such, this file must be compiled twice. (cherry picked from commit af07ed01c04867e281cc3982a7ab0d244d4f8e2e)
2019-04-15 09:26:53 +02:00
#include "nm-libnm-core-intern/nm-common-macros.h"
#include "nm-glib-aux/nm-keyfile-aux.h"
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
#include "nm-keyfile-internal.h"
#include "nm-dbus-interface.h"
#include "nm-connection.h"
#include "nm-setting-8021x.h"
#include "nm-setting-bluetooth.h"
#include "nm-setting-cdma.h"
#include "nm-setting-connection.h"
#include "nm-setting-gsm.h"
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
#include "nm-setting-olpc-mesh.h"
#include "nm-setting-ppp.h"
#include "nm-setting-pppoe.h"
#include "nm-setting-serial.h"
#include "nm-setting-vpn.h"
#include "nm-setting-wired.h"
#include "nm-setting-adsl.h"
#include "nm-setting-wireless.h"
#include "nm-setting-wireless-security.h"
#include "nm-setting-proxy.h"
#include "nm-setting-bond.h"
#include "nm-utils.h"
#include "nm-core-internal.h"
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
#include "nm-std-aux/c-list-util.h"
#include "nm-glib-aux/nm-c-list.h"
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
#include "nm-dbus-object.h"
#include "devices/nm-device-ethernet.h"
#include "nm-settings-connection.h"
#include "nm-settings-plugin.h"
#include "nm-dbus-manager.h"
#include "nm-auth-utils.h"
#include "nm-auth-subject.h"
#include "nm-session-monitor.h"
#include "plugins/keyfile/nms-keyfile-plugin.h"
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
#include "plugins/keyfile/nms-keyfile-storage.h"
#include "nm-agent-manager.h"
#include "nm-config.h"
2015-07-15 14:44:45 +02:00
#include "nm-audit-manager.h"
#include "NetworkManagerUtils.h"
#include "nm-dispatcher.h"
#include "nm-hostname-manager.h"
/*****************************************************************************/
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
static NM_CACHED_QUARK_FCN ("default-wired-connection", _default_wired_connection_quark)
/*****************************************************************************/
typedef struct _StorageData {
CList sd_lst;
NMSettingsStorage *storage;
NMConnection *connection;
bool prioritize:1;
} StorageData;
static StorageData *
_storage_data_new_stale (NMSettingsStorage *storage,
NMConnection *connection)
{
StorageData *sd;
sd = g_slice_new (StorageData);
sd->storage = g_object_ref (storage);
sd->connection = nm_g_object_ref (connection);
sd->prioritize = FALSE;
return sd;
}
static void
_storage_data_destroy (StorageData *sd)
{
c_list_unlink_stale (&sd->sd_lst);
g_object_unref (sd->storage);
nm_g_object_unref (sd->connection);
g_slice_free (StorageData, sd);
}
static StorageData *
_storage_data_find_in_lst (CList *head,
NMSettingsStorage *storage)
{
StorageData *sd;
nm_assert (head);
nm_assert (NM_IS_SETTINGS_STORAGE (storage));
c_list_for_each_entry (sd, head, sd_lst) {
if (sd->storage == storage)
return sd;
}
return NULL;
}
static void
nm_assert_storage_data_lst (CList *head)
{
#if NM_MORE_ASSERTS > 5
const char *uuid = NULL;
StorageData *sd;
CList *iter;
nm_assert (head);
if (c_list_is_empty (head))
return;
c_list_for_each_entry (sd, head, sd_lst) {
const char *u;
nm_assert (NM_IS_SETTINGS_STORAGE (sd->storage));
nm_assert (!sd->connection || NM_IS_CONNECTION (sd->connection));
u = nm_settings_storage_get_uuid (sd->storage);
if (!uuid) {
uuid = u;
nm_assert (nm_utils_is_uuid (uuid));
} else
nm_assert (nm_streq0 (uuid, u));
}
/* assert that all storages are unique. */
c_list_for_each_entry (sd, head, sd_lst) {
for (iter = sd->sd_lst.next; iter != head; iter = iter->next)
nm_assert (c_list_entry (iter, StorageData, sd_lst)->storage != sd->storage);
}
#endif
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
static gboolean
_storage_data_is_alive (StorageData *sd)
{
if (sd->connection)
return TRUE;
if (nm_settings_storage_is_keyfile_tombstone (sd->storage)) {
/* entry does not have a profile, but it's here as a tombstone to
* hide/shadow other connections. That's also relevant. */
return TRUE;
}
return FALSE;
}
/*****************************************************************************/
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
typedef struct {
const char *uuid;
NMSettingsConnection *sett_conn;
NMSettingsStorage *storage;
CList sd_lst_head;
CList dirty_sd_lst_head;
CList sce_dirty_lst;
char _uuid_data[];
} SettConnEntry;
static SettConnEntry *
_sett_conn_entry_new (const char *uuid)
{
SettConnEntry *sett_conn_entry;
gsize l_p_1;
nm_assert (nm_utils_is_uuid (uuid));
l_p_1 = strlen (uuid) + 1;
sett_conn_entry = g_malloc (sizeof (SettConnEntry) + l_p_1);
sett_conn_entry->uuid = sett_conn_entry->_uuid_data;
sett_conn_entry->sett_conn = NULL;
sett_conn_entry->storage = NULL;
c_list_init (&sett_conn_entry->sd_lst_head);
c_list_init (&sett_conn_entry->dirty_sd_lst_head);
c_list_init (&sett_conn_entry->sce_dirty_lst);
memcpy (sett_conn_entry->_uuid_data, uuid, l_p_1);
return sett_conn_entry;
}
static void
_sett_conn_entry_free (SettConnEntry *sett_conn_entry)
{
c_list_unlink_stale (&sett_conn_entry->sce_dirty_lst);
nm_c_list_free_all (&sett_conn_entry->sd_lst_head, StorageData, sd_lst, _storage_data_destroy);
nm_c_list_free_all (&sett_conn_entry->dirty_sd_lst_head, StorageData, sd_lst, _storage_data_destroy);
nm_g_object_unref (sett_conn_entry->sett_conn);
nm_g_object_unref (sett_conn_entry->storage);
g_free (sett_conn_entry);
}
static NMSettingsConnection *
_sett_conn_entry_get_conn (SettConnEntry *sett_conn_entry)
{
return sett_conn_entry ? sett_conn_entry->sett_conn : NULL;
}
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE (NMSettings,
PROP_UNMANAGED_SPECS,
PROP_HOSTNAME,
PROP_CAN_MODIFY,
PROP_CONNECTIONS,
PROP_STARTUP_COMPLETE,
);
enum {
CONNECTION_ADDED,
CONNECTION_UPDATED,
CONNECTION_REMOVED,
CONNECTION_FLAGS_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
2008-04-07 Dan Williams <dcbw@redhat.com> * introspection/nm-settings-system.xml introspection/Makefile.am - Define the unmanaged devices interface for the system settings service * system-settings/src/nm-system-config-hal-manager.c system-settings/src/nm-system-config-hal-manager.h system-settings/src/nm-system-config-hal-manager-private.h system-settings/src/Makefile.am - Add a lightweight HAL manager object for tracking network devices for the purpose of determining unmanaged devices and which devices need the default DHCP connections * system-settings/src/nm-system-config-interface.c system-settings/src/nm-system-config-interface.h - (nm_system_config_interface_init): add the HAL manager as an argument - (nm_system_config_interface_get_unmanaged_devices): implement - Define 'unmanaged-devices-changed' signal * system-settings/src/dbus-settings.c system-settings/src/dbus-settings.h - Implement the unmanaged devices interface; some cleanups * system-settings/plugins/ifcfg-suse/plugin.c - Fixup for plugin interface changes * system-settings/plugins/ifcfg-fedora/plugin.c - (get_ether_device_udi): new function; find the device that has a specified MAC address and return its UDI - (get_udi_for_connection): new function; try to find the specific device a connection is locked to, if any - (device_added_cb, device_removed_cb): update unmanaged device list in response to HAL events - (get_unmanaged_devices): new function; return unmanaged device list - (build_one_connection): set the connection's locked device, if any - (write_auto_wired_connection): remove - (kill_old_auto_wired_file): remove the ifcfg-Auto Wired file if found - (handle_connection_changed): alert listeners that the unmanaged device list has changed - (init): fixup for plugin interface changes, implement unmanaged devices * system-settings/plugins/ifcfg-fedora/parser.c system-settings/plugins/ifcfg-fedora/parser.h - (connection_data_free): clean up connection UDI git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3537 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 01:36:39 +00:00
typedef struct {
NMAgentManager *agent_mgr;
NMConfig *config;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMPlatform *platform;
NMHostnameManager *hostname_manager;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMSessionMonitor *session_monitor;
CList auth_lst_head;
NMSKeyfilePlugin *keyfile_plugin;
GSList *plugins;
2018-03-29 14:48:42 +02:00
NMKeyFileDB *kf_db_timestamps;
NMKeyFileDB *kf_db_seen_bssids;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
GHashTable *sce_idx;
CList sce_dirty_lst_head;
2018-03-29 14:48:42 +02:00
CList connections_lst_head;
NMSettingsConnection **connections_cached_list;
GSList *unmanaged_specs;
GSList *unrecognized_specs;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
GHashTable *startup_complete_idx;
NMSettingsConnection *startup_complete_blocked_by;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
gulong startup_complete_platform_change_id;
guint startup_complete_timeout_id;
2018-03-29 14:48:42 +02:00
guint connections_len;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
guint connections_generation;
guint kf_db_flush_idle_id_timestamps;
guint kf_db_flush_idle_id_seen_bssids;
2018-03-29 14:48:42 +02:00
bool started:1;
} NMSettingsPrivate;
2008-04-07 Dan Williams <dcbw@redhat.com> * introspection/nm-settings-system.xml introspection/Makefile.am - Define the unmanaged devices interface for the system settings service * system-settings/src/nm-system-config-hal-manager.c system-settings/src/nm-system-config-hal-manager.h system-settings/src/nm-system-config-hal-manager-private.h system-settings/src/Makefile.am - Add a lightweight HAL manager object for tracking network devices for the purpose of determining unmanaged devices and which devices need the default DHCP connections * system-settings/src/nm-system-config-interface.c system-settings/src/nm-system-config-interface.h - (nm_system_config_interface_init): add the HAL manager as an argument - (nm_system_config_interface_get_unmanaged_devices): implement - Define 'unmanaged-devices-changed' signal * system-settings/src/dbus-settings.c system-settings/src/dbus-settings.h - Implement the unmanaged devices interface; some cleanups * system-settings/plugins/ifcfg-suse/plugin.c - Fixup for plugin interface changes * system-settings/plugins/ifcfg-fedora/plugin.c - (get_ether_device_udi): new function; find the device that has a specified MAC address and return its UDI - (get_udi_for_connection): new function; try to find the specific device a connection is locked to, if any - (device_added_cb, device_removed_cb): update unmanaged device list in response to HAL events - (get_unmanaged_devices): new function; return unmanaged device list - (build_one_connection): set the connection's locked device, if any - (write_auto_wired_connection): remove - (kill_old_auto_wired_file): remove the ifcfg-Auto Wired file if found - (handle_connection_changed): alert listeners that the unmanaged device list has changed - (init): fixup for plugin interface changes, implement unmanaged devices * system-settings/plugins/ifcfg-fedora/parser.c system-settings/plugins/ifcfg-fedora/parser.h - (connection_data_free): clean up connection UDI git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3537 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 01:36:39 +00:00
struct _NMSettings {
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
NMDBusObject parent;
NMSettingsPrivate _priv;
};
2008-04-07 Dan Williams <dcbw@redhat.com> * introspection/nm-settings-system.xml introspection/Makefile.am - Define the unmanaged devices interface for the system settings service * system-settings/src/nm-system-config-hal-manager.c system-settings/src/nm-system-config-hal-manager.h system-settings/src/nm-system-config-hal-manager-private.h system-settings/src/Makefile.am - Add a lightweight HAL manager object for tracking network devices for the purpose of determining unmanaged devices and which devices need the default DHCP connections * system-settings/src/nm-system-config-interface.c system-settings/src/nm-system-config-interface.h - (nm_system_config_interface_init): add the HAL manager as an argument - (nm_system_config_interface_get_unmanaged_devices): implement - Define 'unmanaged-devices-changed' signal * system-settings/src/dbus-settings.c system-settings/src/dbus-settings.h - Implement the unmanaged devices interface; some cleanups * system-settings/plugins/ifcfg-suse/plugin.c - Fixup for plugin interface changes * system-settings/plugins/ifcfg-fedora/plugin.c - (get_ether_device_udi): new function; find the device that has a specified MAC address and return its UDI - (get_udi_for_connection): new function; try to find the specific device a connection is locked to, if any - (device_added_cb, device_removed_cb): update unmanaged device list in response to HAL events - (get_unmanaged_devices): new function; return unmanaged device list - (build_one_connection): set the connection's locked device, if any - (write_auto_wired_connection): remove - (kill_old_auto_wired_file): remove the ifcfg-Auto Wired file if found - (handle_connection_changed): alert listeners that the unmanaged device list has changed - (init): fixup for plugin interface changes, implement unmanaged devices * system-settings/plugins/ifcfg-fedora/parser.c system-settings/plugins/ifcfg-fedora/parser.h - (connection_data_free): clean up connection UDI git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3537 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 01:36:39 +00:00
struct _NMSettingsClass {
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
NMDBusObjectClass parent;
2008-04-07 Dan Williams <dcbw@redhat.com> * introspection/nm-settings-system.xml introspection/Makefile.am - Define the unmanaged devices interface for the system settings service * system-settings/src/nm-system-config-hal-manager.c system-settings/src/nm-system-config-hal-manager.h system-settings/src/nm-system-config-hal-manager-private.h system-settings/src/Makefile.am - Add a lightweight HAL manager object for tracking network devices for the purpose of determining unmanaged devices and which devices need the default DHCP connections * system-settings/src/nm-system-config-interface.c system-settings/src/nm-system-config-interface.h - (nm_system_config_interface_init): add the HAL manager as an argument - (nm_system_config_interface_get_unmanaged_devices): implement - Define 'unmanaged-devices-changed' signal * system-settings/src/dbus-settings.c system-settings/src/dbus-settings.h - Implement the unmanaged devices interface; some cleanups * system-settings/plugins/ifcfg-suse/plugin.c - Fixup for plugin interface changes * system-settings/plugins/ifcfg-fedora/plugin.c - (get_ether_device_udi): new function; find the device that has a specified MAC address and return its UDI - (get_udi_for_connection): new function; try to find the specific device a connection is locked to, if any - (device_added_cb, device_removed_cb): update unmanaged device list in response to HAL events - (get_unmanaged_devices): new function; return unmanaged device list - (build_one_connection): set the connection's locked device, if any - (write_auto_wired_connection): remove - (kill_old_auto_wired_file): remove the ifcfg-Auto Wired file if found - (handle_connection_changed): alert listeners that the unmanaged device list has changed - (init): fixup for plugin interface changes, implement unmanaged devices * system-settings/plugins/ifcfg-fedora/parser.c system-settings/plugins/ifcfg-fedora/parser.h - (connection_data_free): clean up connection UDI git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3537 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 01:36:39 +00:00
};
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
G_DEFINE_TYPE (NMSettings, nm_settings, NM_TYPE_DBUS_OBJECT);
#define NM_SETTINGS_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMSettings, NM_IS_SETTINGS)
/*****************************************************************************/
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
/* FIXME: a lot of logging lines are directly connected to a profile. Set the @con_uuid
* argument for structured logging. */
#define _NMLOG_DOMAIN LOGD_SETTINGS
2016-10-14 15:32:56 +02:00
#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "settings", __VA_ARGS__)
/*****************************************************************************/
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
static const NMDBusInterfaceInfoExtended interface_info_settings;
static const GDBusSignalInfo signal_info_new_connection;
static const GDBusSignalInfo signal_info_connection_removed;
static void default_wired_clear_tag (NMSettings *self,
NMDevice *device,
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMSettingsConnection *sett_conn,
gboolean add_to_no_auto_default);
static void _clear_connections_cached_list (NMSettingsPrivate *priv);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
static void _startup_complete_check (NMSettings *self,
gint64 now_us);
/*****************************************************************************/
2008-04-07 Dan Williams <dcbw@redhat.com> * introspection/nm-settings-system.xml introspection/Makefile.am - Define the unmanaged devices interface for the system settings service * system-settings/src/nm-system-config-hal-manager.c system-settings/src/nm-system-config-hal-manager.h system-settings/src/nm-system-config-hal-manager-private.h system-settings/src/Makefile.am - Add a lightweight HAL manager object for tracking network devices for the purpose of determining unmanaged devices and which devices need the default DHCP connections * system-settings/src/nm-system-config-interface.c system-settings/src/nm-system-config-interface.h - (nm_system_config_interface_init): add the HAL manager as an argument - (nm_system_config_interface_get_unmanaged_devices): implement - Define 'unmanaged-devices-changed' signal * system-settings/src/dbus-settings.c system-settings/src/dbus-settings.h - Implement the unmanaged devices interface; some cleanups * system-settings/plugins/ifcfg-suse/plugin.c - Fixup for plugin interface changes * system-settings/plugins/ifcfg-fedora/plugin.c - (get_ether_device_udi): new function; find the device that has a specified MAC address and return its UDI - (get_udi_for_connection): new function; try to find the specific device a connection is locked to, if any - (device_added_cb, device_removed_cb): update unmanaged device list in response to HAL events - (get_unmanaged_devices): new function; return unmanaged device list - (build_one_connection): set the connection's locked device, if any - (write_auto_wired_connection): remove - (kill_old_auto_wired_file): remove the ifcfg-Auto Wired file if found - (handle_connection_changed): alert listeners that the unmanaged device list has changed - (init): fixup for plugin interface changes, implement unmanaged devices * system-settings/plugins/ifcfg-fedora/parser.c system-settings/plugins/ifcfg-fedora/parser.h - (connection_data_free): clean up connection UDI git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3537 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
2008-04-08 01:36:39 +00:00
static void
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_emit_connection_added (NMSettings *self,
NMSettingsConnection *sett_conn)
{
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
g_signal_emit (self, signals[CONNECTION_ADDED], 0, sett_conn);
}
static void
_emit_connection_updated (NMSettings *self,
NMSettingsConnection *sett_conn,
NMSettingsConnectionUpdateReason update_reason)
{
_nm_settings_connection_emit_signal_updated_internal (sett_conn, update_reason);
g_signal_emit (self, signals[CONNECTION_UPDATED], 0, sett_conn, (guint) update_reason);
}
static void
_emit_connection_removed (NMSettings *self,
NMSettingsConnection *sett_conn)
{
g_signal_emit (self, signals[CONNECTION_REMOVED], 0, sett_conn);
}
static void
_emit_connection_flags_changed (NMSettings *self,
NMSettingsConnection *sett_conn)
{
g_signal_emit (self, signals[CONNECTION_FLAGS_CHANGED], 0, sett_conn);
}
/*****************************************************************************/
typedef struct {
NMSettingsConnection *sett_conn;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
gint64 start_at;
gint64 timeout;
} StartupCompleteData;
static void
_startup_complete_data_destroy (StartupCompleteData *scd)
{
g_object_unref (scd->sett_conn);
g_slice_free (StartupCompleteData, scd);
}
static gboolean
_startup_complete_check_is_ready (NMPlatform *platform,
NMSettingsConnection *sett_conn)
{
const NMPlatformLink *plink;
const char *ifname;
/* FIXME: instead of just looking for the interface name, it would be better
* to wait for a device that is compatible with the profile. */
ifname = nm_connection_get_interface_name (nm_settings_connection_get_connection (sett_conn));
if (!ifname)
return TRUE;
plink = nm_platform_link_get_by_ifname (platform, ifname);
return plink && plink->initialized;
}
static gboolean
_startup_complete_timeout_cb (gpointer user_data)
{
NMSettings *self = user_data;
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
priv->startup_complete_timeout_id = 0;
_startup_complete_check (self, 0);
return G_SOURCE_REMOVE;
}
static void
_startup_complete_platform_change_cb (NMPlatform *platform,
int obj_type_i,
int ifindex,
const NMPlatformLink *link,
int change_type_i,
NMSettings *self)
{
const NMPlatformSignalChangeType change_type = change_type_i;
NMSettingsPrivate *priv;
const char *ifname;
if (change_type == NM_PLATFORM_SIGNAL_REMOVED)
return;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (!link->initialized)
return;
priv = NM_SETTINGS_GET_PRIVATE (self);
ifname = nm_connection_get_interface_name (nm_settings_connection_get_connection (priv->startup_complete_blocked_by));
if ( ifname
&& !nm_streq (ifname, link->name))
return;
nm_assert (priv->startup_complete_timeout_id > 0);
nm_clear_g_source (&priv->startup_complete_timeout_id);
priv->startup_complete_timeout_id = g_idle_add (_startup_complete_timeout_cb, self);
}
static void
_startup_complete_check (NMSettings *self,
gint64 now_us)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gint64 next_expiry;
StartupCompleteData *scd;
NMSettingsConnection *next_sett_conn = NULL;
GHashTableIter iter;
if (!priv->started) {
/* before we are started, we don't setup the timers... */
return;
}
if (!priv->startup_complete_idx)
goto ready;
if (!now_us)
now_us = nm_utils_get_monotonic_timestamp_us ();
next_expiry = 0;
g_hash_table_iter_init (&iter, priv->startup_complete_idx);
while (g_hash_table_iter_next (&iter, (gpointer *) &scd, NULL)) {
gint64 expiry;
if (scd->start_at == 0) {
/* once ready, the decision is remembered and there is nothing
* left to check. */
continue;
}
expiry = scd->start_at + scd->timeout;
if (expiry <= now_us) {
scd->start_at = 0;
continue;
}
if (_startup_complete_check_is_ready (priv->platform, scd->sett_conn)) {
scd->start_at = 0;
continue;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
next_expiry = expiry;
next_sett_conn = scd->sett_conn;
/* we found one timeout for which to wait. that's good enough. */
break;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_clear_g_source (&priv->startup_complete_timeout_id);
nm_g_object_ref_set (&priv->startup_complete_blocked_by, next_sett_conn);
if (next_expiry > 0) {
nm_assert (priv->startup_complete_blocked_by);
if (priv->startup_complete_platform_change_id == 0) {
priv->startup_complete_platform_change_id = g_signal_connect (priv->platform,
NM_PLATFORM_SIGNAL_LINK_CHANGED,
G_CALLBACK (_startup_complete_platform_change_cb),
self);
}
priv->startup_complete_timeout_id = g_timeout_add (NM_MIN (3600u*1000u, (next_expiry - now_us) / 1000u),
_startup_complete_timeout_cb,
self);
_LOGT ("startup-complete: wait for device \"%s\" due to connection %s (%s)",
nm_connection_get_interface_name (nm_settings_connection_get_connection (priv->startup_complete_blocked_by)),
nm_settings_connection_get_uuid (priv->startup_complete_blocked_by),
nm_settings_connection_get_id (priv->startup_complete_blocked_by));
return;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
nm_clear_g_signal_handler (priv->platform, &priv->startup_complete_platform_change_id);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
ready:
_LOGT ("startup-complete: ready, no profiles to wait for");
nm_assert (priv->started);
nm_assert (!priv->startup_complete_blocked_by);
nm_assert (!priv->startup_complete_idx);
nm_assert (priv->startup_complete_timeout_id == 0);
nm_assert (priv->startup_complete_platform_change_id == 0);
_notify (self, PROP_STARTUP_COMPLETE);
}
static void
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_startup_complete_notify_connection (NMSettings *self,
NMSettingsConnection *sett_conn,
gboolean forget)
{
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gint64 timeout;
gint64 now_us = 0;
nm_assert ( !priv->started
|| priv->startup_complete_idx);
timeout = 0;
if (!forget) {
NMSettingConnection *s_con;
gint32 v;
s_con = nm_connection_get_setting_connection (nm_settings_connection_get_connection (sett_conn));
v = nm_setting_connection_get_wait_device_timeout (s_con);
if (v > 0) {
nm_assert (nm_setting_connection_get_interface_name (s_con));
timeout = ((gint64) v) * 1000;
}
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (timeout == 0) {
if ( !priv->startup_complete_idx
|| !g_hash_table_remove (priv->startup_complete_idx, &sett_conn))
return;
} else {
StartupCompleteData *scd;
if (!priv->startup_complete_idx) {
nm_assert (!priv->started);
priv->startup_complete_idx = g_hash_table_new_full (nm_pdirect_hash,
nm_pdirect_equal,
NULL,
(GDestroyNotify) _startup_complete_data_destroy);
scd = NULL;
} else
scd = g_hash_table_lookup (priv->startup_complete_idx, &sett_conn);
if (!scd) {
now_us = nm_utils_get_monotonic_timestamp_us ();
scd = g_slice_new (StartupCompleteData);
*scd = (StartupCompleteData) {
.sett_conn = g_object_ref (sett_conn),
.start_at = now_us,
.timeout = timeout,
};
g_hash_table_add (priv->startup_complete_idx, scd);
} else {
if (scd->start_at == 0) {
/* the entry already is ready and no longer relevant. Ignore it. */
return;
}
scd->timeout = timeout;
}
}
_startup_complete_check (self, now_us);
}
const char *
nm_settings_get_startup_complete_blocked_reason (NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
const char *uuid = NULL;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (priv->started) {
if (!priv->startup_complete_idx)
return NULL;
if (priv->startup_complete_blocked_by)
uuid = nm_settings_connection_get_uuid (priv->startup_complete_blocked_by);
}
return uuid ?: "unknown";
}
/*****************************************************************************/
const GSList *
nm_settings_get_unmanaged_specs (NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
return priv->unmanaged_specs;
}
static gboolean
update_specs (NMSettings *self, GSList **specs_ptr,
GSList * (*get_specs_func) (NMSettingsPlugin *))
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
GSList *new = NULL;
GSList *iter;
for (iter = priv->plugins; iter; iter = g_slist_next (iter)) {
GSList *specs;
specs = get_specs_func (iter->data);
while (specs) {
GSList *s = specs;
specs = g_slist_remove_link (specs, s);
if (nm_utils_g_slist_find_str (new, s->data)) {
g_free (s->data);
g_slist_free_1 (s);
continue;
}
s->next = new;
new = s;
}
}
if (nm_utils_g_slist_strlist_cmp (new, *specs_ptr) == 0) {
g_slist_free_full (new, g_free);
return FALSE;
}
g_slist_free_full (*specs_ptr, g_free);
*specs_ptr = new;
return TRUE;
}
static void
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_plugin_unmanaged_specs_changed (NMSettingsPlugin *config,
gpointer user_data)
{
NMSettings *self = NM_SETTINGS (user_data);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
if (update_specs (self, &priv->unmanaged_specs,
nm_settings_plugin_get_unmanaged_specs))
_notify (self, PROP_UNMANAGED_SPECS);
}
static void
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_plugin_unrecognized_specs_changed (NMSettingsPlugin *config,
gpointer user_data)
{
NMSettings *self = NM_SETTINGS (user_data);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
update_specs (self, &priv->unrecognized_specs,
nm_settings_plugin_get_unrecognized_specs);
}
/*****************************************************************************/
static void
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
connection_flags_changed (NMSettingsConnection *sett_conn,
gpointer user_data)
{
_emit_connection_flags_changed (NM_SETTINGS (user_data), sett_conn);
}
/*****************************************************************************/
static SettConnEntry *
_sett_conn_entries_get (NMSettings *self,
const char *uuid)
{
nm_assert (uuid);
return g_hash_table_lookup (NM_SETTINGS_GET_PRIVATE (self)->sce_idx, &uuid);
}
static SettConnEntry *
_sett_conn_entries_create_and_add (NMSettings *self,
const char *uuid)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
SettConnEntry *sett_conn_entry;
sett_conn_entry = _sett_conn_entry_new (uuid);
if (!g_hash_table_add (priv->sce_idx, sett_conn_entry))
nm_assert_not_reached ();
else if (g_hash_table_size (priv->sce_idx) == 1)
g_object_ref (self);
return sett_conn_entry;
}
static void
_sett_conn_entries_remove_and_destroy (NMSettings *self,
SettConnEntry *sett_conn_entry)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
if (!g_hash_table_remove (priv->sce_idx, sett_conn_entry))
nm_assert_not_reached ();
else if (g_hash_table_size (priv->sce_idx) == 0)
g_object_unref (self);
}
/*****************************************************************************/
static int
_sett_conn_entry_sds_update_cmp (const CList *ls_a,
const CList *ls_b,
gconstpointer user_data)
{
settings: write tombstones when deleting connection with duplicate files on disk Create such duplicate files: UUID=0df1bac3-1131-42d4-8893-4492d5424d11 rm -f /etc/NetworkManager/system-connections/x[12] rm -f /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta printf -v C "[connection]\nuuid=$UUID\ntype=ethernet\nautoconnect=false" echo "$C" > /etc/NetworkManager/system-connections/x1 echo "$C" > /etc/NetworkManager/system-connections/x2 chmod 600 /etc/NetworkManager/system-connections/x[12] touch /etc/NetworkManager/system-connections/x2 ls -l --full-time /etc/NetworkManager/system-connections/x[12] /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta 2>/dev/null nmcli connection reload nmcli -f all connection show | grep $UUID Now, we have x2 file loaded, and x1 is shadowed. When we delete x2, we probably don't want to delete the hidden x1 file. What previously happend was that when calling nmcli connection delete $UUID the command would hang because the profile wasn't really deleted: <trace> [1563355597.3671] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563355597.3672] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,91e13003dd84928f/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/x2") <trace> [1563355597.3672] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: updating connection "x1" (2b798d30d43b0daf/keyfile) <debug> [1563355597.3674] ++ connection 'update connection' (0x55a167693ee0/NMSimpleConnection/"802-3-ethernet" < 0x55a16762e580/NMSimpleConnection/"802-3-ethernet") [/org/freedesktop/NetworkManager/Settings/41]: <debug> [1563355597.3675] ++ connection [ 0x55a16782a400 < 0x55a16762c350 ] <debug> [1563355597.3675] ++ connection.id = 'x1' < 'x2' <info> [1563355597.3680] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x1" pid=32077 uid=0 result="success" instead, we need to write a tombstone: <trace> [1563359300.2910] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563359300.2911] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,0c12620295ac7f83/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/> <trace> [1563359300.2912] keyfile: commit: writing nmmeta symlink "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta" (pointing to "/dev/null") succeeded <trace> [1563359300.2912] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0d> <trace> [1563359300.2912] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: delete connection "x2" (02a430e6ee52358d/keyfile) <debug> [1563359300.2914] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (x2) <trace> [1563359300.2915] dbus-object[13d79ec95177f9eb]: unexport: "/org/freedesktop/NetworkManager/Settings/54" <trace> [1563359300.2916] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: update settings-connection flags to none (was visible) <info> [1563359300.2917] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x2" pid=22572 uid=0 result="success" <debug> [1563359300.2918] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: disposing and of course after a `nmcli connection reload` the profile stays hidden: <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,e45535721abb092a/keyfile]: change event with connection "x1" (file "/etc/NetworkManager/system-connections/x1") <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta")
2019-07-17 11:01:07 +02:00
const GSList *plugins = user_data;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
StorageData *sd_a = c_list_entry (ls_a, StorageData, sd_lst);
StorageData *sd_b = c_list_entry (ls_b, StorageData, sd_lst);
/* prioritized entries are sorted first (higher priority). */
NM_CMP_FIELD_UNSAFE (sd_b, sd_a, prioritize);
/* nm_settings_storage_cmp() compares in ascending order. Meaning,
* if the storage has higher priority, it gives a positive number (as one
* would expect).
*
* We want to sort the list in reverse though, with highest priority first. */
settings: write tombstones when deleting connection with duplicate files on disk Create such duplicate files: UUID=0df1bac3-1131-42d4-8893-4492d5424d11 rm -f /etc/NetworkManager/system-connections/x[12] rm -f /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta printf -v C "[connection]\nuuid=$UUID\ntype=ethernet\nautoconnect=false" echo "$C" > /etc/NetworkManager/system-connections/x1 echo "$C" > /etc/NetworkManager/system-connections/x2 chmod 600 /etc/NetworkManager/system-connections/x[12] touch /etc/NetworkManager/system-connections/x2 ls -l --full-time /etc/NetworkManager/system-connections/x[12] /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta 2>/dev/null nmcli connection reload nmcli -f all connection show | grep $UUID Now, we have x2 file loaded, and x1 is shadowed. When we delete x2, we probably don't want to delete the hidden x1 file. What previously happend was that when calling nmcli connection delete $UUID the command would hang because the profile wasn't really deleted: <trace> [1563355597.3671] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563355597.3672] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,91e13003dd84928f/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/x2") <trace> [1563355597.3672] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: updating connection "x1" (2b798d30d43b0daf/keyfile) <debug> [1563355597.3674] ++ connection 'update connection' (0x55a167693ee0/NMSimpleConnection/"802-3-ethernet" < 0x55a16762e580/NMSimpleConnection/"802-3-ethernet") [/org/freedesktop/NetworkManager/Settings/41]: <debug> [1563355597.3675] ++ connection [ 0x55a16782a400 < 0x55a16762c350 ] <debug> [1563355597.3675] ++ connection.id = 'x1' < 'x2' <info> [1563355597.3680] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x1" pid=32077 uid=0 result="success" instead, we need to write a tombstone: <trace> [1563359300.2910] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563359300.2911] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,0c12620295ac7f83/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/> <trace> [1563359300.2912] keyfile: commit: writing nmmeta symlink "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta" (pointing to "/dev/null") succeeded <trace> [1563359300.2912] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0d> <trace> [1563359300.2912] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: delete connection "x2" (02a430e6ee52358d/keyfile) <debug> [1563359300.2914] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (x2) <trace> [1563359300.2915] dbus-object[13d79ec95177f9eb]: unexport: "/org/freedesktop/NetworkManager/Settings/54" <trace> [1563359300.2916] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: update settings-connection flags to none (was visible) <info> [1563359300.2917] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x2" pid=22572 uid=0 result="success" <debug> [1563359300.2918] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: disposing and of course after a `nmcli connection reload` the profile stays hidden: <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,e45535721abb092a/keyfile]: change event with connection "x1" (file "/etc/NetworkManager/system-connections/x1") <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta")
2019-07-17 11:01:07 +02:00
return nm_settings_storage_cmp (sd_b->storage, sd_a->storage, plugins);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
}
static void
_sett_conn_entry_sds_update (NMSettings *self,
SettConnEntry *sett_conn_entry)
{
StorageData *sd;
StorageData *sd_safe;
StorageData *sd_dirty;
gboolean reprioritize;
nm_assert_storage_data_lst (&sett_conn_entry->sd_lst_head);
nm_assert_storage_data_lst (&sett_conn_entry->dirty_sd_lst_head);
/* we merge the dirty list with the previous list.
*
* The idea is:
*
* - _connection_changed_track() appends events for the same UUID. Meaning:
* if the storage is new, it get appended (having lower priority).
* If it already exist and is an update for an event that we already
* track it, it keeps the list position in @dirty_sd_lst_head unchanged.
*
* - during merge, we want to preserve the previous order (with higher
* priority first in the list).
*/
/* first go through all storages that we track and check whether they
* got an update...*/
reprioritize = FALSE;
c_list_for_each_entry (sd, &sett_conn_entry->dirty_sd_lst_head, sd_lst) {
if (sd->prioritize) {
reprioritize = TRUE;
break;
}
}
nm_assert_storage_data_lst (&sett_conn_entry->sd_lst_head);
c_list_for_each_entry_safe (sd, sd_safe, &sett_conn_entry->sd_lst_head, sd_lst) {
sd_dirty = _storage_data_find_in_lst (&sett_conn_entry->dirty_sd_lst_head, sd->storage);
if (!sd_dirty) {
/* there is no update for this storage (except maybe reprioritize). */
if (reprioritize)
sd->prioritize = FALSE;
continue;
}
nm_g_object_ref_set (&sd->connection, sd_dirty->connection);
sd->prioritize = sd_dirty->prioritize;
_storage_data_destroy (sd_dirty);
}
nm_assert_storage_data_lst (&sett_conn_entry->sd_lst_head);
/* all remaining (so far unseen) dirty entries are appended to the merged list.
* (append means lower priority). */
c_list_splice (&sett_conn_entry->sd_lst_head, &sett_conn_entry->dirty_sd_lst_head);
nm_assert_storage_data_lst (&sett_conn_entry->sd_lst_head);
/* we drop the entries that are no longer "alive" (meaning, they no longer
* indicate a connection and are not a tombstone). */
c_list_for_each_entry_safe (sd, sd_safe, &sett_conn_entry->sd_lst_head, sd_lst) {
if (!_storage_data_is_alive (sd))
_storage_data_destroy (sd);
}
nm_assert_storage_data_lst (&sett_conn_entry->sd_lst_head);
nm_assert (c_list_is_empty (&sett_conn_entry->dirty_sd_lst_head));
/* as last, we sort the entries. Note that this is a stable-sort... */
c_list_sort (&sett_conn_entry->sd_lst_head,
_sett_conn_entry_sds_update_cmp,
NM_SETTINGS_GET_PRIVATE (self)->plugins);
nm_assert_storage_data_lst (&sett_conn_entry->sd_lst_head);
nm_assert (c_list_is_empty (&sett_conn_entry->dirty_sd_lst_head));
}
/*****************************************************************************/
static NMConnection *
_connection_changed_normalize_connection (NMSettingsStorage *storage,
NMConnection *connection,
GVariant *secrets_to_merge,
NMConnection **out_connection_cloned)
{
gs_unref_object NMConnection *connection_cloned = NULL;
gs_free_error GError *error = NULL;
const char *uuid;
nm_assert (NM_IS_SETTINGS_STORAGE (storage));
nm_assert (out_connection_cloned && !*out_connection_cloned);
if (!connection)
return NULL;
nm_assert (NM_IS_CONNECTION (connection));
uuid = nm_settings_storage_get_uuid (storage);
if (secrets_to_merge) {
connection_cloned = nm_simple_connection_new_clone (connection);
connection = connection_cloned;
nm_connection_update_secrets (connection,
NULL,
secrets_to_merge,
NULL);
}
if (!_nm_connection_ensure_normalized (connection,
!!connection_cloned,
uuid,
FALSE,
connection_cloned ? NULL : &connection_cloned,
&error)) {
/* this is most likely a bug in the plugin. It provided a connection that no longer verifies.
* Well, I guess it could also happen when we merge @secrets_to_merge above. In any case
* somewhere is a bug. */
_LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: plugin provided an invalid connection: %s",
uuid,
NM_SETTINGS_STORAGE_PRINT_ARG (storage),
error->message);
return NULL;
}
if (connection_cloned)
connection = connection_cloned;
*out_connection_cloned = g_steal_pointer (&connection_cloned);
return connection;
}
/*****************************************************************************/
static void
_connection_changed_update (NMSettings *self,
SettConnEntry *sett_conn_entry,
NMConnection *connection,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnectionIntFlags sett_mask,
NMSettingsConnectionUpdateReason update_reason)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gs_unref_object NMConnection *connection_old = NULL;
NMSettingsStorage *storage = sett_conn_entry->storage;
gs_unref_object NMSettingsConnection *sett_conn = g_object_ref (sett_conn_entry->sett_conn);
const char *path;
gboolean is_new;
nm_assert (!NM_FLAGS_ANY (sett_mask, ~_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK));
nm_assert (!NM_FLAGS_ANY (sett_flags, ~sett_mask));
is_new = c_list_is_empty (&sett_conn->_connections_lst);
_LOGT ("update[%s]: %s connection \"%s\" ("NM_SETTINGS_STORAGE_PRINT_FMT")",
nm_settings_storage_get_uuid (storage),
is_new ? "adding" : "updating",
nm_connection_get_id (connection),
NM_SETTINGS_STORAGE_PRINT_ARG (storage));
_nm_settings_connection_set_storage (sett_conn, storage);
_nm_settings_connection_set_connection (sett_conn, connection, &connection_old, update_reason);
if (is_new) {
_nm_settings_connection_register_kf_dbs (sett_conn,
priv->kf_db_timestamps,
priv->kf_db_seen_bssids);
_clear_connections_cached_list (priv);
c_list_link_tail (&priv->connections_lst_head, &sett_conn->_connections_lst);
priv->connections_len++;
priv->connections_generation++;
g_signal_connect (sett_conn, NM_SETTINGS_CONNECTION_FLAGS_CHANGED, G_CALLBACK (connection_flags_changed), self);
}
sett_mask |= NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE;
if (nm_settings_connection_check_visibility (sett_conn, priv->session_monitor))
sett_flags |= NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE;
else
nm_assert (!NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE));
sett_mask |= NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED;
if (nm_settings_storage_is_keyfile_run (storage))
sett_flags |= NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED;
else {
nm_assert (!NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_UNSAVED));
/* Profiles that don't reside in /run, are never nm-generated
* and never volatile. */
sett_mask |= ( NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE);
sett_flags &= ~( NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE);
}
nm_settings_connection_set_flags_full (sett_conn,
sett_mask,
sett_flags);
if (is_new) {
/* FIXME(shutdown): The NMSettings instance can't be disposed
* while there is any exported connection. Ideally we should
* unexport all connections on NMSettings' disposal, but for now
* leak @self on termination when there are connections alive. */
path = nm_dbus_object_export (NM_DBUS_OBJECT (sett_conn));
} else
path = nm_dbus_object_get_path (NM_DBUS_OBJECT (sett_conn));
if ( is_new
|| connection_old) {
nm_utils_log_connection_diff (nm_settings_connection_get_connection (sett_conn),
connection_old,
LOGL_DEBUG,
LOGD_CORE,
is_new ? "new connection" : "update connection",
"++ ",
path);
}
if (is_new) {
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
&interface_info_settings,
&signal_info_new_connection,
"(o)",
path);
_notify (self, PROP_CONNECTIONS);
_emit_connection_added (self, sett_conn);
} else {
_nm_settings_connection_emit_dbus_signal_updated (sett_conn);
_emit_connection_updated (self, sett_conn, update_reason);
}
if ( !priv->started
|| priv->startup_complete_idx) {
if (nm_settings_has_connection (self, sett_conn))
_startup_complete_notify_connection (self, sett_conn, FALSE);
}
}
static void
_connection_changed_delete (NMSettings *self,
NMSettingsStorage *storage,
NMSettingsConnection *sett_conn,
gboolean allow_add_to_no_auto_default)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gs_unref_object NMConnection *connection_for_agents = NULL;
NMDevice *device;
const char *uuid;
nm_assert (NM_IS_SETTINGS_CONNECTION (sett_conn));
nm_assert (c_list_contains (&priv->connections_lst_head, &sett_conn->_connections_lst));
nm_assert (nm_dbus_object_is_exported (NM_DBUS_OBJECT (sett_conn)));
uuid = nm_settings_storage_get_uuid (storage);
_LOGT ("update[%s]: delete connection \"%s\" ("NM_SETTINGS_STORAGE_PRINT_FMT")",
uuid,
nm_settings_connection_get_id (sett_conn),
NM_SETTINGS_STORAGE_PRINT_ARG (storage));
/* When the default wired sett_conn is removed (either deleted or saved to
* a new persistent sett_conn by a plugin), write the MAC address of the
* wired device to the config file and don't create a new default wired
* sett_conn for that device again.
*/
device = nm_settings_connection_default_wired_get_device (sett_conn);
if (device)
default_wired_clear_tag (self, device, sett_conn, allow_add_to_no_auto_default);
g_signal_handlers_disconnect_by_func (sett_conn, G_CALLBACK (connection_flags_changed), self);
_clear_connections_cached_list (priv);
c_list_unlink (&sett_conn->_connections_lst);
priv->connections_len--;
priv->connections_generation++;
/* Tell agents to remove secrets for this connection */
connection_for_agents = nm_simple_connection_new_clone (nm_settings_connection_get_connection (sett_conn));
nm_connection_clear_secrets (connection_for_agents);
nm_agent_manager_delete_secrets (priv->agent_mgr,
nm_dbus_object_get_path (NM_DBUS_OBJECT (self)),
connection_for_agents);
_notify (self, PROP_CONNECTIONS);
_nm_settings_connection_emit_dbus_signal_removed (sett_conn);
nm_dbus_object_emit_signal (NM_DBUS_OBJECT (self),
&interface_info_settings,
&signal_info_connection_removed,
"(o)",
nm_dbus_object_get_path (NM_DBUS_OBJECT (sett_conn)));
nm_dbus_object_unexport (NM_DBUS_OBJECT (sett_conn));
nm_settings_connection_set_flags (sett_conn,
NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE,
FALSE);
_emit_connection_removed (self, sett_conn);
_nm_settings_connection_cleanup_after_remove (sett_conn);
nm_key_file_db_remove_key (priv->kf_db_timestamps, uuid);
nm_key_file_db_remove_key (priv->kf_db_seen_bssids, uuid);
if ( !priv->started
|| priv->startup_complete_idx)
_startup_complete_notify_connection (self, sett_conn, TRUE);
}
static void
_connection_changed_process_one (NMSettings *self,
SettConnEntry *sett_conn_entry,
gboolean allow_add_to_no_auto_default,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnectionIntFlags sett_mask,
gboolean override_sett_flags,
NMSettingsConnectionUpdateReason update_reason)
{
StorageData *sd_best;
c_list_unlink (&sett_conn_entry->sce_dirty_lst);
_sett_conn_entry_sds_update (self, sett_conn_entry);
sd_best = c_list_first_entry (&sett_conn_entry->sd_lst_head, StorageData, sd_lst);;
if ( !sd_best
|| !sd_best->connection) {
gs_unref_object NMSettingsConnection *sett_conn = NULL;
gs_unref_object NMSettingsStorage *storage = NULL;
if (!sett_conn_entry->sett_conn) {
if (!sd_best) {
_sett_conn_entries_remove_and_destroy (self, sett_conn_entry);
return;
}
if (sett_conn_entry->storage != sd_best->storage) {
_LOGT ("update[%s]: shadow UUID ("NM_SETTINGS_STORAGE_PRINT_FMT")",
sett_conn_entry->uuid,
NM_SETTINGS_STORAGE_PRINT_ARG (sd_best->storage));
}
nm_g_object_ref_set (&sett_conn_entry->storage, sd_best->storage);
return;
}
sett_conn = g_steal_pointer (&sett_conn_entry->sett_conn);
if (sd_best) {
storage = g_object_ref (sd_best->storage);
nm_g_object_ref_set (&sett_conn_entry->storage, storage);
nm_assert_valid_settings_storage (NULL, storage);
} else {
storage = g_object_ref (sett_conn_entry->storage);
_sett_conn_entries_remove_and_destroy (self, sett_conn_entry);
}
_connection_changed_delete (self, storage, sett_conn, allow_add_to_no_auto_default);
return;
}
if (override_sett_flags) {
NMSettingsConnectionIntFlags s_f, s_m;
nm_settings_storage_load_sett_flags (sd_best->storage, &s_f, &s_m);
nm_assert (!NM_FLAGS_ANY (s_f, ~s_m));
sett_mask |= s_m;
sett_flags = (sett_flags & ~s_m) | (s_f & s_m);
}
nm_g_object_ref_set (&sett_conn_entry->storage, sd_best->storage);
if (!sett_conn_entry->sett_conn)
sett_conn_entry->sett_conn = nm_settings_connection_new ();
_connection_changed_update (self,
sett_conn_entry,
sd_best->connection,
sett_flags,
sett_mask,
update_reason);
}
static void
_connection_changed_process_all_dirty (NMSettings *self,
gboolean allow_add_to_no_auto_default,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnectionIntFlags sett_mask,
gboolean override_sett_flags,
NMSettingsConnectionUpdateReason update_reason)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
SettConnEntry *sett_conn_entry;
while ((sett_conn_entry = c_list_first_entry (&priv->sce_dirty_lst_head, SettConnEntry, sce_dirty_lst))) {
_connection_changed_process_one (self,
sett_conn_entry,
allow_add_to_no_auto_default,
sett_flags,
sett_mask,
override_sett_flags,
update_reason);
}
}
static SettConnEntry *
_connection_changed_track (NMSettings *self,
NMSettingsStorage *storage,
NMConnection *connection,
gboolean prioritize)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
SettConnEntry *sett_conn_entry;
StorageData *sd;
const char *uuid;
nm_assert_valid_settings_storage (NULL, storage);
uuid = nm_settings_storage_get_uuid (storage);
nm_assert (!connection || NM_IS_CONNECTION (connection));
nm_assert (!connection || (_nm_connection_verify (connection, NULL) == NM_SETTING_VERIFY_SUCCESS));
nm_assert (!connection || nm_streq0 (uuid, nm_connection_get_uuid (connection)));
nmtst_connection_assert_unchanging (connection);
sett_conn_entry = _sett_conn_entries_get (self, uuid)
?: _sett_conn_entries_create_and_add (self, uuid);
if (_LOGT_ENABLED ()) {
const char *filename;
filename = nm_settings_storage_get_filename (storage);
if (connection) {
_LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: change event with connection \"%s\"%s%s%s",
sett_conn_entry->uuid,
NM_SETTINGS_STORAGE_PRINT_ARG (storage),
nm_connection_get_id (connection),
NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
} else if (nm_settings_storage_is_keyfile_tombstone (storage)) {
_LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: change event for hiding profile%s%s%s",
sett_conn_entry->uuid,
NM_SETTINGS_STORAGE_PRINT_ARG (storage),
NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
} else {
_LOGT ("storage[%s,"NM_SETTINGS_STORAGE_PRINT_FMT"]: change event for dropping profile%s%s%s",
sett_conn_entry->uuid,
NM_SETTINGS_STORAGE_PRINT_ARG (storage),
NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
}
}
/* see _sett_conn_entry_sds_update() for why we append the new events
* and leave existing ones at their position. */
sd = _storage_data_find_in_lst (&sett_conn_entry->dirty_sd_lst_head, storage);
if (sd)
nm_g_object_ref_set (&sd->connection, connection);
else {
sd = _storage_data_new_stale (storage, connection);
c_list_link_tail (&sett_conn_entry->dirty_sd_lst_head, &sd->sd_lst);
}
if (prioritize) {
StorageData *sd2;
/* only one entry can be prioritized. */
c_list_for_each_entry (sd2, &sett_conn_entry->dirty_sd_lst_head, sd_lst)
sd2->prioritize = FALSE;
sd->prioritize = TRUE;
}
nm_c_list_move_tail (&priv->sce_dirty_lst_head, &sett_conn_entry->sce_dirty_lst);
return sett_conn_entry;
}
/*****************************************************************************/
static void
_plugin_connections_reload_cb (NMSettingsPlugin *plugin,
NMSettingsStorage *storage,
NMConnection *connection,
gpointer user_data)
{
_connection_changed_track (user_data, storage, connection, FALSE);
}
static void
_plugin_connections_reload (NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
GSList *iter;
for (iter = priv->plugins; iter; iter = iter->next) {
nm_settings_plugin_reload_connections (iter->data,
_plugin_connections_reload_cb,
self);
}
_connection_changed_process_all_dirty (self,
FALSE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
TRUE,
NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS
| NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS);
for (iter = priv->plugins; iter; iter = iter->next)
nm_settings_plugin_load_connections_done (iter->data);
}
/*****************************************************************************/
static gboolean
_add_connection_to_first_plugin (NMSettings *self,
NMConnection *new_connection,
gboolean in_memory,
gboolean is_nm_generated,
gboolean is_volatile,
NMSettingsStorage **out_new_storage,
NMConnection **out_new_connection,
GError **error)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
GError *first_error = NULL;
GSList *iter;
const char *uuid;
uuid = nm_connection_get_uuid (new_connection);
nm_assert (nm_utils_is_uuid (uuid));
for (iter = priv->plugins; iter; iter = iter->next) {
NMSettingsPlugin *plugin = NM_SETTINGS_PLUGIN (iter->data);
gs_unref_object NMSettingsStorage *storage = NULL;
gs_unref_object NMConnection *connection_to_add = NULL;
gs_unref_object NMConnection *connection_to_add_cloned = NULL;
NMConnection *connection_to_add_real = NULL;
gs_unref_variant GVariant *agent_owned_secrets = NULL;
gs_free_error GError *add_error = NULL;
gboolean success;
const char *filename;
if (plugin == (NMSettingsPlugin *) priv->keyfile_plugin) {
success = nms_keyfile_plugin_add_connection (priv->keyfile_plugin,
new_connection,
is_nm_generated,
is_volatile,
in_memory,
&storage,
&connection_to_add,
&add_error);
} else {
if (in_memory)
continue;
nm_assert (!is_nm_generated);
nm_assert (!is_volatile);
success = nm_settings_plugin_add_connection (plugin,
new_connection,
&storage,
&connection_to_add,
&add_error);
}
if (!success) {
_LOGT ("add-connection: failed to add %s/'%s': %s",
nm_connection_get_uuid (new_connection),
nm_connection_get_id (new_connection),
add_error->message);
if (!first_error)
first_error = g_steal_pointer (&add_error);
continue;
}
if (!nm_streq0 (nm_settings_storage_get_uuid (storage), uuid)) {
nm_assert_not_reached ();
continue;
}
agent_owned_secrets = nm_connection_to_dbus (new_connection,
NM_CONNECTION_SERIALIZE_ONLY_SECRETS
| NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED);
connection_to_add_real = _connection_changed_normalize_connection (storage,
connection_to_add,
agent_owned_secrets,
&connection_to_add_cloned);
if (!connection_to_add_real) {
nm_assert_not_reached ();
continue;
}
filename = nm_settings_storage_get_filename (storage);
_LOGT ("add-connection: successfully added connection %s,'%s' ("NM_SETTINGS_STORAGE_PRINT_FMT"%s%s%s",
nm_settings_storage_get_uuid (storage),
nm_connection_get_id (new_connection),
NM_SETTINGS_STORAGE_PRINT_ARG (storage),
NM_PRINT_FMT_QUOTED (filename, ", \"", filename, "\")", ")"));
*out_new_storage = g_steal_pointer (&storage);
*out_new_connection = g_steal_pointer (&connection_to_add_cloned)
?: g_steal_pointer (&connection_to_add);
nm_assert (NM_IS_CONNECTION (*out_new_connection));
return TRUE;
}
nm_assert (first_error);
g_propagate_error (error, first_error);
return FALSE;
}
/**
* nm_settings_add_connection:
* @self: the #NMSettings object
* @connection: the source connection to create a new #NMSettingsConnection from
* @persist_mode: the persist-mode for this profile.
* @sett_flags: the settings flags to set.
* @out_sett_conn: (allow-none) (transfer none): the added settings connection on success.
* @error: on return, a location to store any errors that may occur
*
* Creates a new #NMSettingsConnection for the given source @connection.
* The returned object is owned by @self and the caller must reference
* the object to continue using it.
*
* Returns: TRUE on success.
*/
gboolean
nm_settings_add_connection (NMSettings *self,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnection **out_sett_conn,
GError **error)
{
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
gs_unref_object NMConnection *connection_cloned_1 = NULL;
gs_unref_object NMConnection *new_connection = NULL;
gs_unref_object NMSettingsStorage *new_storage = NULL;
gs_free_error GError *local = NULL;
SettConnEntry *sett_conn_entry;
const char *uuid;
StorageData *sd;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (!NM_FLAGS_ANY (sett_flags, ~_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert ( !NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)
|| persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert ( !NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE)
|| persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NM_SET_OUT (out_sett_conn, NULL);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
uuid = nm_connection_get_uuid (connection);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
/* Make sure a connection with this UUID doesn't already exist */
if (_sett_conn_entry_get_conn (_sett_conn_entries_get (self, uuid))) {
g_set_error_literal (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_UUID_EXISTS,
"a connection with this UUID already exists");
return FALSE;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (!_nm_connection_ensure_normalized (connection,
FALSE,
NULL,
FALSE,
&connection_cloned_1,
&local)) {
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"connection is invalid: %s",
local->message);
return FALSE;
}
if (connection_cloned_1)
connection = connection_cloned_1;
if (!_add_connection_to_first_plugin (self,
connection,
( persist_mode != NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK
|| NM_FLAGS_ANY (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE
| NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE),
&new_storage,
&new_connection,
&local)) {
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FAILED,
"failure adding connection: %s",
local->message);
return FALSE;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
sett_conn_entry = _connection_changed_track (self, new_storage, new_connection, TRUE);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
c_list_for_each_entry (sd, &sett_conn_entry->sd_lst_head, sd_lst) {
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (!nm_settings_storage_is_keyfile_tombstone (sd->storage))
continue;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (nm_settings_storage_is_keyfile_run (sd->storage)) {
/* We remove this file from /run. */
} else {
if (nm_settings_storage_is_keyfile_run (new_storage)) {
/* Don't remove the file from /etc if we just wrote an in-memory connection */
continue;
}
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_settings_plugin_delete_connection (nm_settings_storage_get_plugin (sd->storage),
sd->storage,
NULL);
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (!nm_settings_storage_is_keyfile_tombstone (sd->storage));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_connection_changed_track (self, sd->storage, NULL, FALSE);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_connection_changed_process_all_dirty (self,
FALSE,
sett_flags,
_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK,
FALSE,
NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS
| NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (sett_conn_entry == _sett_conn_entries_get (self, sett_conn_entry->uuid));
nm_assert (NM_IS_SETTINGS_CONNECTION (sett_conn_entry->sett_conn));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NM_SET_OUT (out_sett_conn, _sett_conn_entry_get_conn (sett_conn_entry));
return TRUE;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
/*****************************************************************************/
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
gboolean
nm_settings_update_connection (NMSettings *self,
NMSettingsConnection *sett_conn,
NMConnection *connection,
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
NMSettingsConnectionIntFlags sett_mask,
NMSettingsConnectionUpdateReason update_reason,
const char *log_context_name,
GError **error)
{
NMSettingsPrivate *priv;
gs_unref_object NMConnection *connection_cloned_1 = NULL;
gs_unref_object NMConnection *new_connection_cloned = NULL;
gs_unref_object NMConnection *new_connection = NULL;
NMConnection *new_connection_real;
gs_unref_object NMSettingsStorage *cur_storage = NULL;
gs_unref_object NMSettingsStorage *new_storage = NULL;
gboolean cur_in_memory;
gboolean new_in_memory;
const char *uuid;
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (sett_conn), FALSE);
g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), FALSE);
2018-03-29 14:48:42 +02:00
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (!NM_FLAGS_ANY (sett_mask, ~_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK));
nm_assert (!NM_FLAGS_ANY (sett_flags, ~sett_mask));
nm_assert (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST,
NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY));
2018-03-29 14:48:42 +02:00
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
priv = NM_SETTINGS_GET_PRIVATE (self);
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
cur_storage = g_object_ref (nm_settings_connection_get_storage (sett_conn));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
uuid = nm_settings_storage_get_uuid (cur_storage);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (NM_IS_SETTINGS_STORAGE (cur_storage));
nm_assert (_sett_conn_entry_get_conn (_sett_conn_entries_get (self, uuid)) == sett_conn);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (connection) {
gs_free_error GError *local = NULL;
if (!_nm_connection_ensure_normalized (connection,
FALSE,
uuid,
TRUE,
&connection_cloned_1,
&local)) {
_LOGT ("update[%s]: %s: failed because profile is invalid: %s",
nm_settings_storage_get_uuid (cur_storage),
log_context_name,
local->message);
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"connection is invalid: %s",
local->message);
return FALSE;
}
if (connection_cloned_1)
connection = connection_cloned_1;
} else
connection = nm_settings_connection_get_connection (sett_conn);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
cur_in_memory = nm_settings_storage_is_keyfile_run (cur_storage);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP) {
persist_mode = cur_in_memory
? NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED
: NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if ( NM_FLAGS_HAS (sett_mask, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)
&& !NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) {
NMDevice *device;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
/* The connection has been changed by the user, it should no longer be
* considered a default wired connection, and should no longer affect
* the no-auto-default configuration option.
*/
device = nm_settings_connection_default_wired_get_device (sett_conn);
if (device) {
nm_assert (cur_in_memory);
nm_assert (!NM_FLAGS_ANY (nm_settings_connection_get_flags (sett_conn),
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE));
default_wired_clear_tag (self, device, sett_conn, FALSE);
if (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_KEEP,
NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST)) {
/* making a default-wired-connection a regulard connection implies persisting
* it to disk (unless specified differently). */
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK;
}
}
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if ( persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST
&& NM_FLAGS_ANY (sett_mask, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE)
&& NM_FLAGS_ANY ((sett_flags ^ nm_settings_connection_get_flags (sett_conn)) & sett_mask,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE)) {
/* we update the nm-generated/volatile setting of a profile (which is inherrently
* in-memory. The caller did not request to persist this to disk, however we need
* to store the flags in run. */
nm_assert (cur_in_memory);
persist_mode = NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK)
new_in_memory = FALSE;
else if (NM_IN_SET (persist_mode, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY))
new_in_memory = TRUE;
else {
nm_assert (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST);
new_in_memory = cur_in_memory;
}
if (!new_in_memory) {
/* Persistent connections cannot be volatile nor nm-generated.
*
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
* That is obviously true for volatile, as it is enforced by Update2() API.
*
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
* For nm-generated profiles also, because the nm-generated flag is only stored
* for in-memory profiles. If we would persist the profile to /etc it would loose
* the nm-generated flag after restart/reload, and that cannot be right. If a profile
* ends up on disk, the information who created it gets lost. */
nm_assert (!NM_FLAGS_ANY (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE));
sett_mask |= NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE;
sett_flags &= ~( NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST) {
new_storage = g_object_ref (cur_storage);
new_connection = g_object_ref (connection);
_LOGT ("update[%s]: %s: update profile \"%s\" (not persisted)",
nm_settings_storage_get_uuid (cur_storage),
log_context_name,
nm_connection_get_id (connection));
} else {
gboolean success;
gboolean migrate_storage;
gs_free_error GError *local = NULL;
if (new_in_memory != cur_in_memory)
migrate_storage = TRUE;
else if ( !new_in_memory
&& nm_settings_storage_is_keyfile_lib (cur_storage)) {
/* the profile is a keyfile in /usr/lib. It cannot be overwritten, we must migrate it
* from /usr/lib to /etc. */
migrate_storage = TRUE;
} else
migrate_storage = FALSE;
if (migrate_storage) {
success = _add_connection_to_first_plugin (self,
connection,
new_in_memory,
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE),
&new_storage,
&new_connection,
&local);
} else {
NMSettingsPlugin *plugin;
plugin = nm_settings_storage_get_plugin (cur_storage);
if (plugin == (NMSettingsPlugin *) priv->keyfile_plugin) {
success = nms_keyfile_plugin_update_connection (priv->keyfile_plugin,
cur_storage,
connection,
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE),
NM_FLAGS_HAS (update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_FORCE_RENAME),
&new_storage,
&new_connection,
&local);
} else {
success = nm_settings_plugin_update_connection (nm_settings_storage_get_plugin (cur_storage),
cur_storage,
connection,
&new_storage,
&new_connection,
&local);
}
}
if (!success) {
gboolean ignore_failure;
ignore_failure = NM_FLAGS_ANY (update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_IGNORE_PERSIST_FAILURE);
_LOGT ("update[%s]: %s: %sfailure to %s connection \"%s\" on storage: %s",
nm_settings_storage_get_uuid (cur_storage),
log_context_name,
ignore_failure ? "ignore " : "",
migrate_storage ? "write" : "update",
nm_connection_get_id (connection),
local->message);
if (!ignore_failure) {
g_set_error (error,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"failed to %s connection: %s",
migrate_storage ? "write" : "update",
local->message);
return FALSE;
}
new_storage = g_object_ref (cur_storage);
new_connection = g_object_ref (connection);
} else {
_LOGT ("update[%s]: %s: %s profile \"%s\"",
nm_settings_storage_get_uuid (cur_storage),
log_context_name,
migrate_storage ? "write" : "update",
nm_connection_get_id (connection));
}
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert_valid_settings_storage (NULL, new_storage);
nm_assert (NM_IS_CONNECTION (new_connection));
nm_assert (nm_streq (uuid, nm_settings_storage_get_uuid (new_storage)));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST)
new_connection_real = new_connection;
else {
gs_unref_variant GVariant *agent_owned_secrets = NULL;
agent_owned_secrets = nm_connection_to_dbus (connection,
NM_CONNECTION_SERIALIZE_ONLY_SECRETS
| NM_CONNECTION_SERIALIZE_WITH_SECRETS_AGENT_OWNED);
new_connection_real = _connection_changed_normalize_connection (new_storage,
new_connection,
agent_owned_secrets,
&new_connection_cloned);
if (!new_connection_real) {
nm_assert_not_reached ();
new_connection_real = new_connection;
}
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (NM_IS_CONNECTION (new_connection_real));
_connection_changed_track (self, new_storage, new_connection_real, TRUE);
if (new_storage != cur_storage) {
gs_free_error GError *local = NULL;
gboolean remove_from_disk;
if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_DETACHED)
remove_from_disk = FALSE;
else if (nm_settings_storage_is_keyfile_lib (cur_storage))
remove_from_disk = FALSE;
else
remove_from_disk = TRUE;
if (remove_from_disk) {
if (!nm_settings_plugin_delete_connection (nm_settings_storage_get_plugin (cur_storage),
cur_storage,
&local)) {
const char *filename;
filename = nm_settings_storage_get_filename (cur_storage);
_LOGW ("update[%s]: failed to delete moved storage "NM_SETTINGS_STORAGE_PRINT_FMT"%s%s%s: %s",
nm_settings_storage_get_uuid (cur_storage),
NM_SETTINGS_STORAGE_PRINT_ARG (cur_storage),
local->message,
NM_PRINT_FMT_QUOTED (filename, " (file \"", filename, "\")", ""));
}
_connection_changed_track (self, cur_storage, NULL, FALSE);
}
}
2018-03-29 14:48:42 +02:00
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_connection_changed_process_all_dirty (self,
FALSE,
sett_flags,
sett_mask,
FALSE,
update_reason);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
return TRUE;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
void
nm_settings_delete_connection (NMSettings *self,
NMSettingsConnection *sett_conn,
gboolean allow_add_to_no_auto_default)
{
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMSettingsPrivate *priv;
NMSettingsStorage *cur_storage;
gs_free_error GError *local = NULL;
settings: write tombstones when deleting connection with duplicate files on disk Create such duplicate files: UUID=0df1bac3-1131-42d4-8893-4492d5424d11 rm -f /etc/NetworkManager/system-connections/x[12] rm -f /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta printf -v C "[connection]\nuuid=$UUID\ntype=ethernet\nautoconnect=false" echo "$C" > /etc/NetworkManager/system-connections/x1 echo "$C" > /etc/NetworkManager/system-connections/x2 chmod 600 /etc/NetworkManager/system-connections/x[12] touch /etc/NetworkManager/system-connections/x2 ls -l --full-time /etc/NetworkManager/system-connections/x[12] /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta 2>/dev/null nmcli connection reload nmcli -f all connection show | grep $UUID Now, we have x2 file loaded, and x1 is shadowed. When we delete x2, we probably don't want to delete the hidden x1 file. What previously happend was that when calling nmcli connection delete $UUID the command would hang because the profile wasn't really deleted: <trace> [1563355597.3671] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563355597.3672] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,91e13003dd84928f/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/x2") <trace> [1563355597.3672] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: updating connection "x1" (2b798d30d43b0daf/keyfile) <debug> [1563355597.3674] ++ connection 'update connection' (0x55a167693ee0/NMSimpleConnection/"802-3-ethernet" < 0x55a16762e580/NMSimpleConnection/"802-3-ethernet") [/org/freedesktop/NetworkManager/Settings/41]: <debug> [1563355597.3675] ++ connection [ 0x55a16782a400 < 0x55a16762c350 ] <debug> [1563355597.3675] ++ connection.id = 'x1' < 'x2' <info> [1563355597.3680] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x1" pid=32077 uid=0 result="success" instead, we need to write a tombstone: <trace> [1563359300.2910] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563359300.2911] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,0c12620295ac7f83/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/> <trace> [1563359300.2912] keyfile: commit: writing nmmeta symlink "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta" (pointing to "/dev/null") succeeded <trace> [1563359300.2912] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0d> <trace> [1563359300.2912] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: delete connection "x2" (02a430e6ee52358d/keyfile) <debug> [1563359300.2914] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (x2) <trace> [1563359300.2915] dbus-object[13d79ec95177f9eb]: unexport: "/org/freedesktop/NetworkManager/Settings/54" <trace> [1563359300.2916] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: update settings-connection flags to none (was visible) <info> [1563359300.2917] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x2" pid=22572 uid=0 result="success" <debug> [1563359300.2918] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: disposing and of course after a `nmcli connection reload` the profile stays hidden: <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,e45535721abb092a/keyfile]: change event with connection "x1" (file "/etc/NetworkManager/system-connections/x1") <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta")
2019-07-17 11:01:07 +02:00
SettConnEntry *sett_conn_entry;
const char *uuid;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
gboolean delete;
gboolean tombstone_in_memory = FALSE;
gboolean tombstone_on_disk = FALSE;
gs_unref_object NMSettingsStorage *tombstone_1_storage = NULL;
gs_unref_object NMSettingsStorage *tombstone_2_storage = NULL;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
g_return_if_fail (NM_IS_SETTINGS (self));
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (sett_conn));
g_return_if_fail (nm_settings_has_connection (self, sett_conn));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
priv = NM_SETTINGS_GET_PRIVATE (self);
cur_storage = nm_settings_connection_get_storage (sett_conn);
nm_assert (NM_IS_SETTINGS_STORAGE (cur_storage));
uuid = nm_settings_storage_get_uuid (cur_storage);
nm_assert (nm_utils_is_uuid (uuid));
sett_conn_entry = _sett_conn_entries_get (self, uuid);
g_return_if_fail (sett_conn_entry);
nm_assert (sett_conn_entry->sett_conn == sett_conn);
settings: write tombstones when deleting connection with duplicate files on disk Create such duplicate files: UUID=0df1bac3-1131-42d4-8893-4492d5424d11 rm -f /etc/NetworkManager/system-connections/x[12] rm -f /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta printf -v C "[connection]\nuuid=$UUID\ntype=ethernet\nautoconnect=false" echo "$C" > /etc/NetworkManager/system-connections/x1 echo "$C" > /etc/NetworkManager/system-connections/x2 chmod 600 /etc/NetworkManager/system-connections/x[12] touch /etc/NetworkManager/system-connections/x2 ls -l --full-time /etc/NetworkManager/system-connections/x[12] /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta 2>/dev/null nmcli connection reload nmcli -f all connection show | grep $UUID Now, we have x2 file loaded, and x1 is shadowed. When we delete x2, we probably don't want to delete the hidden x1 file. What previously happend was that when calling nmcli connection delete $UUID the command would hang because the profile wasn't really deleted: <trace> [1563355597.3671] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563355597.3672] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,91e13003dd84928f/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/x2") <trace> [1563355597.3672] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: updating connection "x1" (2b798d30d43b0daf/keyfile) <debug> [1563355597.3674] ++ connection 'update connection' (0x55a167693ee0/NMSimpleConnection/"802-3-ethernet" < 0x55a16762e580/NMSimpleConnection/"802-3-ethernet") [/org/freedesktop/NetworkManager/Settings/41]: <debug> [1563355597.3675] ++ connection [ 0x55a16782a400 < 0x55a16762c350 ] <debug> [1563355597.3675] ++ connection.id = 'x1' < 'x2' <info> [1563355597.3680] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x1" pid=32077 uid=0 result="success" instead, we need to write a tombstone: <trace> [1563359300.2910] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563359300.2911] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,0c12620295ac7f83/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/> <trace> [1563359300.2912] keyfile: commit: writing nmmeta symlink "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta" (pointing to "/dev/null") succeeded <trace> [1563359300.2912] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0d> <trace> [1563359300.2912] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: delete connection "x2" (02a430e6ee52358d/keyfile) <debug> [1563359300.2914] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (x2) <trace> [1563359300.2915] dbus-object[13d79ec95177f9eb]: unexport: "/org/freedesktop/NetworkManager/Settings/54" <trace> [1563359300.2916] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: update settings-connection flags to none (was visible) <info> [1563359300.2917] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x2" pid=22572 uid=0 result="success" <debug> [1563359300.2918] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: disposing and of course after a `nmcli connection reload` the profile stays hidden: <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,e45535721abb092a/keyfile]: change event with connection "x1" (file "/etc/NetworkManager/system-connections/x1") <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta")
2019-07-17 11:01:07 +02:00
g_return_if_fail (sett_conn_entry->storage == cur_storage);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (NMS_IS_KEYFILE_STORAGE (cur_storage)) {
NMSKeyfileStorage *s = NMS_KEYFILE_STORAGE (cur_storage);
if (NM_IN_SET (s->storage_type, NMS_KEYFILE_STORAGE_TYPE_RUN,
NMS_KEYFILE_STORAGE_TYPE_ETC))
delete = TRUE;
else {
tombstone_on_disk = TRUE;
delete = FALSE;
}
} else
delete = TRUE;
if (delete) {
settings: write tombstones when deleting connection with duplicate files on disk Create such duplicate files: UUID=0df1bac3-1131-42d4-8893-4492d5424d11 rm -f /etc/NetworkManager/system-connections/x[12] rm -f /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta printf -v C "[connection]\nuuid=$UUID\ntype=ethernet\nautoconnect=false" echo "$C" > /etc/NetworkManager/system-connections/x1 echo "$C" > /etc/NetworkManager/system-connections/x2 chmod 600 /etc/NetworkManager/system-connections/x[12] touch /etc/NetworkManager/system-connections/x2 ls -l --full-time /etc/NetworkManager/system-connections/x[12] /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta 2>/dev/null nmcli connection reload nmcli -f all connection show | grep $UUID Now, we have x2 file loaded, and x1 is shadowed. When we delete x2, we probably don't want to delete the hidden x1 file. What previously happend was that when calling nmcli connection delete $UUID the command would hang because the profile wasn't really deleted: <trace> [1563355597.3671] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563355597.3672] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,91e13003dd84928f/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/x2") <trace> [1563355597.3672] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: updating connection "x1" (2b798d30d43b0daf/keyfile) <debug> [1563355597.3674] ++ connection 'update connection' (0x55a167693ee0/NMSimpleConnection/"802-3-ethernet" < 0x55a16762e580/NMSimpleConnection/"802-3-ethernet") [/org/freedesktop/NetworkManager/Settings/41]: <debug> [1563355597.3675] ++ connection [ 0x55a16782a400 < 0x55a16762c350 ] <debug> [1563355597.3675] ++ connection.id = 'x1' < 'x2' <info> [1563355597.3680] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x1" pid=32077 uid=0 result="success" instead, we need to write a tombstone: <trace> [1563359300.2910] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563359300.2911] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,0c12620295ac7f83/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/> <trace> [1563359300.2912] keyfile: commit: writing nmmeta symlink "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta" (pointing to "/dev/null") succeeded <trace> [1563359300.2912] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0d> <trace> [1563359300.2912] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: delete connection "x2" (02a430e6ee52358d/keyfile) <debug> [1563359300.2914] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (x2) <trace> [1563359300.2915] dbus-object[13d79ec95177f9eb]: unexport: "/org/freedesktop/NetworkManager/Settings/54" <trace> [1563359300.2916] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: update settings-connection flags to none (was visible) <info> [1563359300.2917] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x2" pid=22572 uid=0 result="success" <debug> [1563359300.2918] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: disposing and of course after a `nmcli connection reload` the profile stays hidden: <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,e45535721abb092a/keyfile]: change event with connection "x1" (file "/etc/NetworkManager/system-connections/x1") <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta")
2019-07-17 11:01:07 +02:00
StorageData *sd;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (!nm_settings_plugin_delete_connection (nm_settings_storage_get_plugin (cur_storage),
cur_storage,
&local)) {
_LOGW ("delete-connection: failed to delete storage "NM_SETTINGS_STORAGE_PRINT_FMT": %s",
NM_SETTINGS_STORAGE_PRINT_ARG (cur_storage),
local->message);
g_clear_error (&local);
/* there is no aborting back form this. We must get rid of the connection and
* cannot do better than warn. Proceed... */
tombstone_in_memory = TRUE;
}
settings: write tombstones when deleting connection with duplicate files on disk Create such duplicate files: UUID=0df1bac3-1131-42d4-8893-4492d5424d11 rm -f /etc/NetworkManager/system-connections/x[12] rm -f /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta printf -v C "[connection]\nuuid=$UUID\ntype=ethernet\nautoconnect=false" echo "$C" > /etc/NetworkManager/system-connections/x1 echo "$C" > /etc/NetworkManager/system-connections/x2 chmod 600 /etc/NetworkManager/system-connections/x[12] touch /etc/NetworkManager/system-connections/x2 ls -l --full-time /etc/NetworkManager/system-connections/x[12] /{etc,run}/NetworkManager/system-connections/"$UUID".nmmeta 2>/dev/null nmcli connection reload nmcli -f all connection show | grep $UUID Now, we have x2 file loaded, and x1 is shadowed. When we delete x2, we probably don't want to delete the hidden x1 file. What previously happend was that when calling nmcli connection delete $UUID the command would hang because the profile wasn't really deleted: <trace> [1563355597.3671] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563355597.3672] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,91e13003dd84928f/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/x2") <trace> [1563355597.3672] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: updating connection "x1" (2b798d30d43b0daf/keyfile) <debug> [1563355597.3674] ++ connection 'update connection' (0x55a167693ee0/NMSimpleConnection/"802-3-ethernet" < 0x55a16762e580/NMSimpleConnection/"802-3-ethernet") [/org/freedesktop/NetworkManager/Settings/41]: <debug> [1563355597.3675] ++ connection [ 0x55a16782a400 < 0x55a16762c350 ] <debug> [1563355597.3675] ++ connection.id = 'x1' < 'x2' <info> [1563355597.3680] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x1" pid=32077 uid=0 result="success" instead, we need to write a tombstone: <trace> [1563359300.2910] keyfile: commit: deleted "/etc/NetworkManager/system-connections/x2", profile 0df1bac3-1131-42d4-8893-4492d5424d11 (deleted from disk) <trace> [1563359300.2911] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,0c12620295ac7f83/keyfile]: change event for dropping profile (file "/etc/NetworkManager/system-connections/> <trace> [1563359300.2912] keyfile: commit: writing nmmeta symlink "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta" (pointing to "/dev/null") succeeded <trace> [1563359300.2912] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0d> <trace> [1563359300.2912] settings: update[0df1bac3-1131-42d4-8893-4492d5424d11]: delete connection "x2" (02a430e6ee52358d/keyfile) <debug> [1563359300.2914] Deleting secrets for connection /org/freedesktop/NetworkManager/Settings (x2) <trace> [1563359300.2915] dbus-object[13d79ec95177f9eb]: unexport: "/org/freedesktop/NetworkManager/Settings/54" <trace> [1563359300.2916] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: update settings-connection flags to none (was visible) <info> [1563359300.2917] audit: op="connection-delete" uuid="0df1bac3-1131-42d4-8893-4492d5424d11" name="x2" pid=22572 uid=0 result="success" <debug> [1563359300.2918] settings-connection[13d79ec95177f9eb,0df1bac3-1131-42d4-8893-4492d5424d11]: disposing and of course after a `nmcli connection reload` the profile stays hidden: <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,e45535721abb092a/keyfile]: change event with connection "x1" (file "/etc/NetworkManager/system-connections/x1") <trace> [1563359412.0355] settings: storage[0df1bac3-1131-42d4-8893-4492d5424d11,02a430e6ee52358d/keyfile]: change event for hiding profile (file "/etc/NetworkManager/system-connections/0df1bac3-1131-42d4-8893-4492d5424d11.nmmeta")
2019-07-17 11:01:07 +02:00
sett_conn_entry = _connection_changed_track (self, cur_storage, NULL, FALSE);
c_list_for_each_entry (sd, &sett_conn_entry->sd_lst_head, sd_lst) {
if (sd->storage == cur_storage)
continue;
if (nm_settings_storage_is_keyfile_tombstone (sd->storage))
continue;
if (!_storage_data_is_alive (sd))
continue;
/* we have still conflicting storages. We need to hide them with tombstones. */
if (nm_settings_storage_is_keyfile_run (sd->storage)) {
tombstone_in_memory = TRUE;
continue;
}
tombstone_on_disk = TRUE;
}
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (tombstone_on_disk) {
if (!nms_keyfile_plugin_set_nmmeta_tombstone (priv->keyfile_plugin,
FALSE,
uuid,
FALSE,
TRUE,
&tombstone_1_storage,
NULL))
tombstone_in_memory = TRUE;
if (tombstone_1_storage)
_connection_changed_track (self, tombstone_1_storage, NULL, FALSE);
}
if (tombstone_in_memory) {
if (!nms_keyfile_plugin_set_nmmeta_tombstone (priv->keyfile_plugin,
FALSE,
uuid,
TRUE,
TRUE,
&tombstone_2_storage,
NULL)) {
nms_keyfile_plugin_set_nmmeta_tombstone (priv->keyfile_plugin,
TRUE,
uuid,
TRUE,
TRUE,
&tombstone_2_storage,
NULL);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_connection_changed_track (self, tombstone_2_storage, NULL, FALSE);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_connection_changed_process_all_dirty (self,
allow_add_to_no_auto_default,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
FALSE,
NM_SETTINGS_CONNECTION_UPDATE_REASON_NONE);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
/*****************************************************************************/
static void
send_agent_owned_secrets (NMSettings *self,
NMSettingsConnection *sett_conn,
NMAuthSubject *subject)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gs_unref_object NMConnection *for_agent = NULL;
/* Dupe the connection so we can clear out non-agent-owned secrets,
* as agent-owned secrets are the only ones we send back to be saved.
* Only send secrets to agents of the same UID that called update too.
*/
for_agent = nm_simple_connection_new_clone (nm_settings_connection_get_connection (sett_conn));
_nm_connection_clear_secrets_by_secret_flags (for_agent,
NM_SETTING_SECRET_FLAG_AGENT_OWNED);
nm_agent_manager_save_secrets (priv->agent_mgr,
nm_dbus_object_get_path (NM_DBUS_OBJECT (sett_conn)),
for_agent,
subject);
}
static void
pk_add_cb (NMAuthChain *chain,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMSettings *self = NM_SETTINGS (user_data);
NMAuthCallResult result;
gs_free_error GError *error = NULL;
NMConnection *connection = NULL;
gs_unref_object NMSettingsConnection *added = NULL;
NMSettingsAddCallback callback;
gpointer callback_data;
NMAuthSubject *subject;
const char *perm;
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
c_list_unlink (nm_auth_chain_parent_lst_list (chain));
perm = nm_auth_chain_get_data (chain, "perm");
nm_assert (perm);
result = nm_auth_chain_get_result (chain, perm);
if (result != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Insufficient privileges.");
} else {
/* Authorized */
connection = nm_auth_chain_get_data (chain, "connection");
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (NM_IS_CONNECTION (connection));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_settings_add_connection (self,
connection,
GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "persist-mode")),
GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "sett-flags")),
&added,
&error);
/* The callback may remove the connection from the settings manager (e.g.
* because it's found to be incompatible with the device on AddAndActivate).
* But we need to keep it alive for a bit longer, precisely to check wehther
* it's still known to the setting manager. */
nm_g_object_ref (added);
}
callback = nm_auth_chain_get_data (chain, "callback");
callback_data = nm_auth_chain_get_data (chain, "callback-data");
subject = nm_auth_chain_get_data (chain, "subject");
callback (self, added, error, context, subject, callback_data);
/* Send agent-owned secrets to the agents */
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if ( added
&& nm_settings_has_connection (self, added))
send_agent_owned_secrets (self, added, subject);
}
void
nm_settings_add_connection_dbus (NMSettings *self,
NMConnection *connection,
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMSettingsConnectionPersistMode persist_mode,
NMSettingsConnectionIntFlags sett_flags,
NMAuthSubject *subject,
GDBusMethodInvocation *context,
NMSettingsAddCallback callback,
gpointer user_data)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMSettingConnection *s_con;
NMAuthChain *chain;
GError *error = NULL, *tmp_error = NULL;
const char *perm;
g_return_if_fail (NM_IS_CONNECTION (connection));
g_return_if_fail (NM_IS_AUTH_SUBJECT (subject));
g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (context));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (!NM_FLAGS_ANY (sett_flags, ~_NM_SETTINGS_CONNECTION_INT_FLAGS_PERSISTENT_MASK));
/* Connection must be valid, of course */
if (_nm_connection_verify (connection, &tmp_error) != NM_SETTING_VERIFY_SUCCESS) {
error = g_error_new (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"The connection was invalid: %s",
tmp_error->message);
g_error_free (tmp_error);
goto done;
}
/* FIXME: The kernel doesn't support Ad-Hoc WPA connections well at this time,
* and turns them into open networks. It's been this way since at least
* 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
*/
if (nm_utils_connection_is_adhoc_wpa (connection)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"WPA Ad-Hoc disabled due to kernel bugs");
goto done;
}
if (!nm_auth_is_subject_in_acl_set_error (connection,
subject,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
&error))
goto done;
/* If the caller is the only user in the connection's permissions, then
* we use the 'modify.own' permission instead of 'modify.system'. If the
* request affects more than just the caller, require 'modify.system'.
*/
s_con = nm_connection_get_setting_connection (connection);
nm_assert (s_con);
if (nm_setting_connection_get_num_permissions (s_con) == 1)
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
else
perm = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
/* Validate the user request */
chain = nm_auth_chain_new_subject (subject, context, pk_add_cb, self);
if (!chain) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Unable to authenticate the request.");
goto done;
}
c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain));
nm_auth_chain_set_data (chain, "perm", (gpointer) perm, NULL);
nm_auth_chain_set_data (chain, "connection", g_object_ref (connection), g_object_unref);
nm_auth_chain_set_data (chain, "callback", callback, NULL);
nm_auth_chain_set_data (chain, "callback-data", user_data, NULL);
nm_auth_chain_set_data (chain, "subject", g_object_ref (subject), g_object_unref);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_auth_chain_set_data (chain, "persist-mode", GUINT_TO_POINTER (persist_mode), NULL);
nm_auth_chain_set_data (chain, "sett-flags", GUINT_TO_POINTER (sett_flags), NULL);
nm_auth_chain_add_call_unsafe (chain, perm, TRUE);
return;
done:
nm_assert (error);
callback (self, NULL, error, context, subject, user_data);
g_error_free (error);
}
static void
settings_add_connection_add_cb (NMSettings *self,
NMSettingsConnection *connection,
GError *error,
GDBusMethodInvocation *context,
NMAuthSubject *subject,
gpointer user_data)
{
if (error) {
g_dbus_method_invocation_return_gerror (context, error);
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, NULL, FALSE, NULL, subject, error->message);
} else {
g_dbus_method_invocation_return_value (context,
g_variant_new ("(o)",
nm_dbus_object_get_path (NM_DBUS_OBJECT (connection))));
nm_audit_log_connection_op (NM_AUDIT_OP_CONN_ADD, connection, TRUE, NULL,
subject, NULL);
}
}
static void
settings_add_connection_helper (NMSettings *self,
GDBusMethodInvocation *context,
GVariant *settings,
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMSettingsConnectionPersistMode persist_mode)
{
gs_unref_object NMConnection *connection = NULL;
GError *error = NULL;
gs_unref_object NMAuthSubject *subject = NULL;
connection = _nm_simple_connection_new_from_dbus (settings,
NM_SETTING_PARSE_FLAGS_STRICT
| NM_SETTING_PARSE_FLAGS_NORMALIZE,
&error);
if ( !connection
|| !nm_connection_verify_secrets (connection, &error)) {
g_dbus_method_invocation_take_error (context, error);
return;
}
subject = nm_auth_subject_new_unix_process_from_context (context);
if (!subject) {
g_dbus_method_invocation_return_error_literal (context,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Unable to determine UID of request.");
return;
}
nm_settings_add_connection_dbus (self,
connection,
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
persist_mode,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
subject,
context,
settings_add_connection_add_cb,
NULL);
}
static void
impl_settings_add_connection (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
GDBusConnection *connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettings *self = NM_SETTINGS (obj);
gs_unref_variant GVariant *settings = NULL;
g_variant_get (parameters, "(@a{sa{sv}})", &settings);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
settings_add_connection_helper (self, invocation, settings, NM_SETTINGS_CONNECTION_PERSIST_MODE_DISK);
}
static void
impl_settings_add_connection_unsaved (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
GDBusConnection *connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettings *self = NM_SETTINGS (obj);
gs_unref_variant GVariant *settings = NULL;
g_variant_get (parameters, "(@a{sa{sv}})", &settings);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
settings_add_connection_helper (self, invocation, settings, NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
/*****************************************************************************/
static void
impl_settings_load_connections (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
GDBusConnection *dbus_connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettings *self = NM_SETTINGS (obj);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gs_unref_ptrarray GPtrArray *failures = NULL;
gs_free const char **filenames = NULL;
gs_free char *op_result_str = NULL;
g_variant_get (parameters, "(^a&s)", &filenames);
/* The permission is already enforced by the D-Bus daemon, but we ensure
* that the caller is still alive so that clients are forced to wait and
* we'll be able to switch to polkit without breaking behavior.
*/
if (!nm_dbus_manager_ensure_uid (nm_dbus_object_get_manager (obj),
invocation,
G_MAXULONG,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED))
return;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if ( filenames
&& filenames[0]) {
NMSettingsPluginConnectionLoadEntry *entries;
gsize n_entries;
gsize i;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
GSList *iter;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
entries = nm_settings_plugin_create_connection_load_entries (filenames, &n_entries);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
for (iter = priv->plugins; iter; iter = iter->next) {
NMSettingsPlugin *plugin = iter->data;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_settings_plugin_load_connections (plugin,
entries,
n_entries,
_plugin_connections_reload_cb,
self);
}
for (i = 0; i < n_entries; i++) {
NMSettingsPluginConnectionLoadEntry *entry = &entries[i];
if (!entry->handled)
_LOGW ("load: no settings plugin could load \"%s\"", entry->filename);
else if (entry->error) {
_LOGW ("load: failure to load \"%s\": %s", entry->filename, entry->error->message);
g_clear_error (&entry->error);
} else
continue;
if (!failures)
failures = g_ptr_array_new ();
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
g_ptr_array_add (failures, (char *) entry->filename);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_clear_g_free (&entries);
_connection_changed_process_all_dirty (self,
TRUE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
NM_SETTINGS_CONNECTION_INT_FLAGS_NONE,
TRUE,
NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_SYSTEM_SECRETS
| NM_SETTINGS_CONNECTION_UPDATE_REASON_RESET_AGENT_SECRETS);
for (iter = priv->plugins; iter; iter = iter->next)
nm_settings_plugin_load_connections_done (iter->data);
}
if (failures)
g_ptr_array_add (failures, NULL);
nm_audit_log_connection_op (NM_AUDIT_OP_CONNS_LOAD,
NULL,
!failures,
(op_result_str = g_strjoinv (",", (char **) filenames)),
invocation,
NULL);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(b^as)",
(gboolean) (!failures),
failures
? (const char **) failures->pdata
: NM_PTRARRAY_EMPTY (const char *)));
}
static void
impl_settings_reload_connections (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
GDBusConnection *connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettings *self = NM_SETTINGS (obj);
/* The permission is already enforced by the D-Bus daemon, but we ensure
* that the caller is still alive so that clients are forced to wait and
* we'll be able to switch to polkit without breaking behavior.
*/
if (!nm_dbus_manager_ensure_uid (nm_dbus_object_get_manager (obj),
invocation,
G_MAXULONG,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED))
return;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_plugin_connections_reload (self);
nm_audit_log_connection_op (NM_AUDIT_OP_CONNS_RELOAD, NULL, TRUE, NULL, invocation, NULL);
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
}
/*****************************************************************************/
static void
_clear_connections_cached_list (NMSettingsPrivate *priv)
{
if (!priv->connections_cached_list)
return;
nm_assert (priv->connections_len == NM_PTRARRAY_LEN (priv->connections_cached_list));
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
#if NM_MORE_ASSERTS
/* set the pointer to a bogus value. This makes it more apparent
* if somebody has a reference to the cached list and still uses
* it. That is a bug, this code just tries to make it blow up
* more eagerly. */
memset (priv->connections_cached_list,
0xdeaddead,
sizeof (NMSettingsConnection *) * (priv->connections_len + 1));
#endif
nm_clear_g_free (&priv->connections_cached_list);
}
static void
impl_settings_list_connections (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
GDBusConnection *dbus_connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettings *self = NM_SETTINGS (obj);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gs_free const char **strv = NULL;
strv = nm_dbus_utils_get_paths_for_clist (&priv->connections_lst_head,
priv->connections_len,
G_STRUCT_OFFSET (NMSettingsConnection, _connections_lst),
TRUE);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(^ao)", strv));
}
NMSettingsConnection *
nm_settings_get_connection_by_uuid (NMSettings *self, const char *uuid)
{
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
g_return_val_if_fail (uuid != NULL, NULL);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
return _sett_conn_entry_get_conn (_sett_conn_entries_get (self, uuid));
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
const char *
nm_settings_get_dbus_path_for_uuid (NMSettings *self,
const char *uuid)
{
NMSettingsConnection *sett_conn;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
sett_conn = nm_settings_get_connection_by_uuid (self, uuid);
if (!sett_conn)
return NULL;
return nm_dbus_object_get_path (NM_DBUS_OBJECT (sett_conn));
}
static void
impl_settings_get_connection_by_uuid (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
GDBusConnection *dbus_connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
NMSettings *self = NM_SETTINGS (obj);
NMSettingsConnection *sett_conn;
gs_unref_object NMAuthSubject *subject = NULL;
GError *error = NULL;
const char *uuid;
g_variant_get (parameters, "(&s)", &uuid);
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
sett_conn = nm_settings_get_connection_by_uuid (self, uuid);
if (!sett_conn) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_CONNECTION,
"No connection with the UUID was found.");
goto error;
}
subject = nm_auth_subject_new_unix_process_from_context (invocation);
if (!subject) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Unable to determine UID of request.");
goto error;
}
if (!nm_auth_is_subject_in_acl_set_error (nm_settings_connection_get_connection (sett_conn),
subject,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
&error))
goto error;
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(o)",
nm_dbus_object_get_path (NM_DBUS_OBJECT (sett_conn))));
return;
error:
g_dbus_method_invocation_take_error (invocation, error);
}
/**
* nm_settings_get_connections:
* @self: the #NMSettings
* @out_len: (out) (allow-none): returns the number of returned
* connections.
*
* Returns: (transfer none): a list of NMSettingsConnections. The list is
* unsorted and NULL terminated. The result is never %NULL, in case of no
* connections, it returns an empty list.
* The returned list is cached internally, only valid until the next
* NMSettings operation.
*/
NMSettingsConnection *const*
nm_settings_get_connections (NMSettings *self, guint *out_len)
{
NMSettingsPrivate *priv;
NMSettingsConnection **v;
NMSettingsConnection *con;
guint i;
2018-03-29 14:48:42 +02:00
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
priv = NM_SETTINGS_GET_PRIVATE (self);
nm_assert (priv->connections_len == c_list_length (&priv->connections_lst_head));
if (G_UNLIKELY (!priv->connections_cached_list)) {
v = g_new (NMSettingsConnection *, priv->connections_len + 1);
i = 0;
c_list_for_each_entry (con, &priv->connections_lst_head, _connections_lst) {
nm_assert (i < priv->connections_len);
v[i++] = con;
}
nm_assert (i == priv->connections_len);
v[i] = NULL;
priv->connections_cached_list = v;
}
NM_SET_OUT (out_len, priv->connections_len);
return priv->connections_cached_list;
}
/**
* nm_settings_get_connections_clone:
* @self: the #NMSetting
* @out_len: (allow-none): optional output argument
* @func: caller-supplied function for filtering connections
* @func_data: caller-supplied data passed to @func
* @sort_compare_func: (allow-none): optional function pointer for
* sorting the returned list.
* @sort_data: user data for @sort_compare_func.
*
* Returns: (transfer container) (element-type NMSettingsConnection):
* an NULL terminated array of #NMSettingsConnection objects that were
* filtered by @func (or all connections if no filter was specified).
* The order is arbitrary.
* Caller is responsible for freeing the returned array with free(),
* the contained values do not need to be unrefed.
*/
NMSettingsConnection **
nm_settings_get_connections_clone (NMSettings *self,
guint *out_len,
NMSettingsConnectionFilterFunc func,
gpointer func_data,
GCompareDataFunc sort_compare_func,
gpointer sort_data)
{
NMSettingsConnection *const*list_cached;
NMSettingsConnection **list;
guint len, i, j;
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
list_cached = nm_settings_get_connections (self, &len);
#if NM_MORE_ASSERTS
nm_assert (list_cached);
for (i = 0; i < len; i++)
nm_assert (NM_IS_SETTINGS_CONNECTION (list_cached[i]));
nm_assert (!list_cached[i]);
#endif
list = g_new (NMSettingsConnection *, ((gsize) len + 1));
if (func) {
for (i = 0, j = 0; i < len; i++) {
if (func (self, list_cached[i], func_data))
list[j++] = list_cached[i];
}
list[j] = NULL;
len = j;
} else
memcpy (list, list_cached, sizeof (list[0]) * ((gsize) len + 1));
if ( len > 1
&& sort_compare_func) {
g_qsort_with_data (list, len, sizeof (NMSettingsConnection *),
sort_compare_func, sort_data);
}
NM_SET_OUT (out_len, len);
return list;
}
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
NMSettingsConnection *
nm_settings_get_connection_by_path (NMSettings *self, const char *path)
{
NMSettingsPrivate *priv;
NMSettingsConnection *connection;
g_return_val_if_fail (NM_IS_SETTINGS (self), NULL);
g_return_val_if_fail (path, NULL);
priv = NM_SETTINGS_GET_PRIVATE (self);
connection = nm_dbus_manager_lookup_object (nm_dbus_object_get_manager (NM_DBUS_OBJECT (self)),
path);
if ( !connection
|| !NM_IS_SETTINGS_CONNECTION (connection))
return NULL;
nm_assert (c_list_contains (&priv->connections_lst_head, &connection->_connections_lst));
return connection;
}
gboolean
nm_settings_has_connection (NMSettings *self, NMSettingsConnection *connection)
{
gboolean has;
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (connection), FALSE);
has = !c_list_is_empty (&connection->_connections_lst);
nm_assert (has == nm_c_list_contains_entry (&NM_SETTINGS_GET_PRIVATE (self)->connections_lst_head,
connection,
_connections_lst));
nm_assert (({
NMSettingsConnection *candidate = NULL;
const char *path;
path = nm_dbus_object_get_path (NM_DBUS_OBJECT (connection));
if (path)
candidate = nm_settings_get_connection_by_path (self, path);
(has == (connection == candidate));
}));
return has;
}
/*****************************************************************************/
static void
add_plugin (NMSettings *self,
NMSettingsPlugin *plugin,
const char *pname,
const char *path)
{
NMSettingsPrivate *priv;
nm_assert (NM_IS_SETTINGS (self));
nm_assert (NM_IS_SETTINGS_PLUGIN (plugin));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (pname);
nm_assert (nm_streq0 (pname, nm_settings_plugin_get_plugin_name (plugin)));
priv = NM_SETTINGS_GET_PRIVATE (self);
nm_assert (!g_slist_find (priv->plugins, plugin));
priv->plugins = g_slist_append (priv->plugins, g_object_ref (plugin));
nm_shutdown_wait_obj_register_full (G_OBJECT (plugin),
g_strdup_printf ("%s-settings-plugin", pname),
TRUE);
_LOGI ("Loaded settings plugin: %s (%s%s%s)",
pname,
NM_PRINT_FMT_QUOTED (path, "\"", path, "\"", "internal"));
}
static gboolean
add_plugin_load_file (NMSettings *self, const char *pname, GError **error)
{
gs_free char *full_name = NULL;
gs_free char *path = NULL;
gs_unref_object NMSettingsPlugin *plugin = NULL;
GModule *module;
NMSettingsPluginFactoryFunc factory_func;
struct stat st;
int errsv;
full_name = g_strdup_printf ("nm-settings-plugin-%s", pname);
path = g_module_build_path (NMPLUGINDIR, full_name);
if (stat (path, &st) != 0) {
errsv = errno;
_LOGW ("could not load plugin '%s' from file '%s': %s", pname, path, nm_strerror_native (errsv));
return TRUE;
}
if (!S_ISREG (st.st_mode)) {
_LOGW ("could not load plugin '%s' from file '%s': not a file", pname, path);
return TRUE;
}
if (st.st_uid != 0) {
_LOGW ("could not load plugin '%s' from file '%s': file must be owned by root", pname, path);
return TRUE;
}
if (st.st_mode & (S_IWGRP | S_IWOTH | S_ISUID)) {
_LOGW ("could not load plugin '%s' from file '%s': invalid file permissions", pname, path);
return TRUE;
}
module = g_module_open (path, G_MODULE_BIND_LOCAL);
if (!module) {
_LOGW ("could not load plugin '%s' from file '%s': %s",
pname, path, g_module_error ());
return TRUE;
}
/* errors after this point are fatal, because we loaded the shared library already. */
if (!g_module_symbol (module, "nm_settings_plugin_factory", (gpointer) (&factory_func))) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"Could not find plugin '%s' factory function.",
pname);
g_module_close (module);
return FALSE;
}
/* after accessing the plugin we cannot unload it anymore, because the glib
* types cannot be properly unregistered. */
g_module_make_resident (module);
plugin = (*factory_func) ();
if (!NM_IS_SETTINGS_PLUGIN (plugin)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
"plugin '%s' returned invalid settings plugin",
pname);
return FALSE;
}
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
add_plugin (self, NM_SETTINGS_PLUGIN (plugin), pname, path);
return TRUE;
}
static void
add_plugin_keyfile (NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
if (priv->keyfile_plugin)
return;
priv->keyfile_plugin = nms_keyfile_plugin_new ();
add_plugin (self, NM_SETTINGS_PLUGIN (priv->keyfile_plugin), "keyfile", NULL);
}
static gboolean
load_plugins (NMSettings *self, const char *const*plugins, GError **error)
{
const char *const*iter;
gboolean success = TRUE;
for (iter = plugins; iter && *iter; iter++) {
const char *pname = *iter;
if (!*pname || strchr (pname, '/')) {
_LOGW ("ignore invalid plugin \"%s\"", pname);
continue;
}
settings: avoid assertion for LoadConnections D-Bus method with relative paths $ busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager/Settings org.freedesktop.NetworkManager.Settings LoadConnections as 1 relative/filename triggers a g_critical() assertion in nm_utils_file_is_in_path(): ... #3 0x00007ffff7a19e7d in g_return_if_fail_warning (log_domain=log_domain@entry=0x55555586c333 "NetworkManager", pretty_function=pretty_function@entry=0x55555586c0a0 <__FUNCTION__.38585> "nm_utils_file_is_in_path", expression=expression@entry=0x55555586c010 "abs_filename && abs_filename[0] == '/'") at ../glib/gmessages.c:2767 #4 0x00005555555f1128 in nm_utils_file_is_in_path (abs_filename=abs_filename@entry=0x555555b56670 "dfd", abs_path=<optimized out>) at src/NetworkManagerUtils.c:1077 #5 0x00005555555a4779 in load_connection (config=<optimized out>, filename=0x555555b56670 "dfd") at src/settings/plugins/keyfile/nms-keyfile-plugin.c:522 #6 0x00005555557ce291 in nm_settings_plugin_load_connection (self=0x5555559fd400 [NMSKeyfilePlugin], filename=0x555555b56670 "dfd") at src/settings/nm-settings-plugin.c:70 #7 0x000055555559ccdf in impl_settings_load_connections (obj=<optimized out>, interface_info=<optimized out>, method_info=<optimized out>, connection=<optimized out>, sender=<optimized out>, invocation=0x7fffe0015ed0 [GDBusMethodInvocation], parameters=<optimized out>) at src/settings/nm-settings.c:1439 #8 0x00005555555a9bf9 in dbus_vtable_method_call (connection=0x5555559b91b0 [GDBusConnection], sender=sender@entry=0x555555b5c360 ":1.32283", object_path=object_path@entry=0x7fffe0019070 "/org/freedesktop/NetworkManager/Settings", interface_name=<optimized out>, interface_name@entry=0x7fffe002aa70 "org.freedesktop.NetworkManager.Settings", method_name=<optimized out>, method_name@entry=0x7fffe00276b0 "LoadConnections", parameters=parameters@entry=0x555555c4a690, invocation=0x7fffe0015ed0 [GDBusMethodInvocation], user_data=0x5555559a1a00) at src/nm-dbus-manager.c:947 #9 0x00007ffff7c506c4 in call_in_idle_cb (user_data=user_data@entry=0x7fffe0015ed0) at ../gio/gdbusconnection.c:4874 #10 0x00007ffff7a0e8eb in g_idle_dispatch (source=source@entry=0x7fffe00208a0, callback=0x7ffff7c50590 <call_in_idle_cb>, user_data=0x7fffe0015ed0) at ../glib/gmain.c:5627 #11 0x00007ffff7a11fd0 in g_main_dispatch (context=0x555555994d00) at ../glib/gmain.c:3189 #12 0x00007ffff7a11fd0 in g_main_context_dispatch (context=context@entry=0x555555994d00) at ../glib/gmain.c:3854 #13 0x00007ffff7a12368 in g_main_context_iterate (context=0x555555994d00, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:3927 #14 0x00007ffff7a126b3 in g_main_loop_run (loop=0x555555995e60) at ../glib/gmain.c:4123 #15 0x000055555558a741 in main (argc=<optimized out>, argv=<optimized out>) at src/main.c:444 Filter out relative filenames early.
2019-05-10 14:35:52 +02:00
if (NM_IN_STRSET (pname, "ifcfg-suse", "ifnet", "ibft", "no-ibft")) {
_LOGW ("skipping deprecated plugin %s", pname);
continue;
}
/* keyfile plugin is built-in now */
if (nm_streq (pname, "keyfile")) {
add_plugin_keyfile (self);
continue;
}
if (nm_utils_strv_find_first ((char **) plugins,
iter - plugins,
pname) >= 0) {
/* the plugin is already mentioned in the list previously.
* Don't load a duplicate. */
continue;
}
success = add_plugin_load_file (self, pname, error);
if (!success)
break;
}
/* If keyfile plugin was not among configured plugins, add it as the last one */
if (success)
add_plugin_keyfile (self);
return success;
}
/*****************************************************************************/
static void
pk_hostname_cb (NMAuthChain *chain,
2015-04-15 14:53:30 -04:00
GDBusMethodInvocation *context,
gpointer user_data)
{
NMSettings *self = NM_SETTINGS (user_data);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMAuthCallResult result;
GError *error = NULL;
const char *hostname;
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
c_list_unlink (nm_auth_chain_parent_lst_list (chain));
result = nm_auth_chain_get_result (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
/* If our NMSettingsConnection is already gone, do nothing */
if (result != NM_AUTH_CALL_RESULT_YES) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Insufficient privileges.");
} else {
hostname = nm_auth_chain_get_data (chain, "hostname");
if (!nm_hostname_manager_write_hostname (priv->hostname_manager, hostname)) {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_FAILED,
"Saving the hostname failed.");
}
}
if (error)
2015-04-15 14:53:30 -04:00
g_dbus_method_invocation_take_error (context, error);
else
2015-04-15 14:53:30 -04:00
g_dbus_method_invocation_return_value (context, NULL);
}
static void
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
impl_settings_save_hostname (NMDBusObject *obj,
const NMDBusInterfaceInfoExtended *interface_info,
const NMDBusMethodInfoExtended *method_info,
GDBusConnection *connection,
const char *sender,
GDBusMethodInvocation *invocation,
GVariant *parameters)
{
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
NMSettings *self = NM_SETTINGS (obj);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMAuthChain *chain;
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
const char *hostname;
g_variant_get (parameters, "(&s)", &hostname);
/* Minimal validation of the hostname */
if (!nm_hostname_manager_validate_hostname (hostname)) {
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
g_dbus_method_invocation_return_error_literal (invocation,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_INVALID_HOSTNAME,
"The hostname was too long or contained invalid characters.");
return;
}
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
chain = nm_auth_chain_new_context (invocation, pk_hostname_cb, self);
if (!chain) {
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
g_dbus_method_invocation_return_error_literal (invocation,
NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
"Unable to authenticate the request.");
return;
}
c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain));
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, TRUE);
nm_auth_chain_set_data (chain, "hostname", g_strdup (hostname), g_free);
}
/*****************************************************************************/
static void
_hostname_changed_cb (NMHostnameManager *hostname_manager,
GParamSpec *pspec,
gpointer user_data)
{
_notify (user_data, PROP_HOSTNAME);
}
/*****************************************************************************/
static gboolean
have_connection_for_device (NMSettings *self, NMDevice *device)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMSettingWired *s_wired;
const char *setting_hwaddr;
const char *perm_hw_addr;
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
NMSettingsConnection *sett_conn;
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
perm_hw_addr = nm_device_get_permanent_hw_address (device);
/* Find a wired connection locked to the given MAC address, if any */
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
c_list_for_each_entry (sett_conn, &priv->connections_lst_head, _connections_lst) {
NMConnection *connection = nm_settings_connection_get_connection (sett_conn);
NMSettingConnection *s_con = nm_connection_get_setting_connection (connection);
const char *ctype;
const char *iface;
ctype = nm_setting_connection_get_connection_type (s_con);
if (!NM_IN_STRSET (ctype, NM_SETTING_WIRED_SETTING_NAME,
NM_SETTING_PPPOE_SETTING_NAME))
continue;
if (!nm_device_check_connection_compatible (device, connection, NULL))
continue;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (nm_settings_connection_default_wired_get_device (sett_conn))
continue;
if (NM_FLAGS_ANY (nm_settings_connection_get_flags (sett_conn),
NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE))
continue;
iface = nm_setting_connection_get_interface_name (s_con);
if (!nm_streq0 (iface, nm_device_get_iface (device)))
continue;
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
s_wired = nm_connection_get_setting_wired (connection);
if ( !s_wired
&& nm_streq (ctype, NM_SETTING_PPPOE_SETTING_NAME)) {
/* No wired setting; therefore the PPPoE connection applies to any device */
return TRUE;
}
setting_hwaddr = nm_setting_wired_get_mac_address (s_wired);
if (setting_hwaddr) {
/* A connection mac-locked to this device */
if ( perm_hw_addr
&& nm_utils_hwaddr_matches (setting_hwaddr, -1, perm_hw_addr, -1))
return TRUE;
} else {
/* A connection that applies to any wired device */
return TRUE;
}
}
/* See if there's a known non-NetworkManager configuration for the device */
if (nm_device_spec_match_list (device, priv->unrecognized_specs))
return TRUE;
return FALSE;
}
static void
default_wired_clear_tag (NMSettings *self,
NMDevice *device,
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
NMSettingsConnection *sett_conn,
gboolean add_to_no_auto_default)
{
settings: use delegation instead of inheritance for NMSettingsConnection and NMConnection NMConnection is an interface, which is implemented by the types NMSimpleConnection (libnm-core), NMSettingsConnection (src) and NMRemoteConnection (libnm). NMSettingsConnection does a lot of things already: 1) it "is-a" NMDBusObject and exports the API of a connection profile on D-Bus 2) it interacts with NMSettings and contains functionality for tracking the profiles. 3) it is the base-class of types like NMSKeyfileConnection and NMIfcfgConnection. These handle how the profile is persisted on disk. 4) it implements NMConnection interface, to itself track the settings of the profile. 3) and 4) would be better implemented via delegation than inheritance. Address 4) and don't let NMSettingsConnection implemente the NMConnection interface. Instead, a settings-connection references now a NMSimpleConnection instance, to which it delegates for keeping the actual profiles. Advantages: - by delegating, there is a clearer separation of what NMSettingsConnection does. For example, in C we often required casts from NMSettingsConnection to NMConnection. NMConnection is a very trivial object with very little logic. When we have a NMConnection instance at hand, it's good to know that it is *only* that simple instead of also being an entire NMSettingsConnection instance. The main purpose of this patch is to simplify the code by separating the NMConnection from the NMSettingsConnection. We should generally be aware whether we handle a NMSettingsConnection or a trivial NMConnection instance. Now, because NMSettingsConnection no longer "is-a" NMConnection, this distinction is apparent. - NMConnection is implemented as an interface and we create NMSimpleConnection instances whenever we need a real instance. In GLib, interfaces have a performance overhead, that we needlessly pay all the time. With this change, we no longer require NMConnection to be an interface. Thus, in the future we could compile a version of libnm-core for the daemon, where NMConnection is not an interface but a GObject implementation akin to NMSimpleConnection. - In the previous implementation, we cannot treat NMConnection immutable and copy-on-write. For example, when NMDevice needs a snapshot of the activated profile as applied-connection, all it can do is clone the entire NMSettingsConnection as a NMSimpleConnection. Likewise, when we get a NMConnection instance and want to keep a reference to it, we cannot do that, because we never know who also references and modifies the instance. By separating NMSettingsConnection we could in the future have NMConnection immutable and copy-on-write, to avoid all unnecessary clones.
2018-08-11 11:08:17 +02:00
nm_assert (NM_IS_SETTINGS (self));
nm_assert (NM_IS_DEVICE (device));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (NM_IS_SETTINGS_CONNECTION (sett_conn));
nm_assert (device == nm_settings_connection_default_wired_get_device (sett_conn));
nm_assert (sett_conn == g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ()));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_settings_connection_default_wired_set_device (sett_conn, NULL);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
g_object_set_qdata (G_OBJECT (device), _default_wired_connection_quark (), NULL);
if (add_to_no_auto_default)
nm_config_set_no_auto_default_for_device (NM_SETTINGS_GET_PRIVATE (self)->config, device);
}
static void
device_realized (NMDevice *device, GParamSpec *pspec, NMSettings *self)
{
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
gs_unref_object NMConnection *connection = NULL;
NMSettingsConnection *added;
GError *error = NULL;
if (!nm_device_is_real (device))
return;
g_signal_handlers_disconnect_by_func (device,
G_CALLBACK (device_realized),
self);
/* If the device isn't managed or it already has a default wired connection,
* ignore it.
*/
device: remove default-unmanaged and refactor unmanaged flags Get rid of NM_UNMANAGED_DEFAULT and refine the interaction between unmanaged flags, device state and managed property. Previously, the NM_UNMANAGED_DEFAULT was special in that a device was still considered managed if it had solely the NM_UNMANAGED_DEFAULT flag set and its state was managed. Thus, whether the device (state) was managed, depended on the device state too. Now, a device is considered managed (or unmanaged) based on the unmanaged flags and realization state alone. At the same time, the device state directly corresponds to the managed property of the device. Of course, while changing the unmanaged flags, that invariant is shortly violated until the state transistion is complete. Introduce more unmanaged flags whereas some of them are non-authorative. For example, the EXTERNAL_DOWN flag has only effect as long as the user didn't explicitly manage the device (NM_UNMANAGED_USER_EXPLICIT). In other words, certain flags can render other flags ineffective. Whether the device is considered managed depends on the flags but also at the explicitly unset flags. In a way, this is similar to previous where NM_UNMANAGED_DEFAULT was ignored (if no other flags were present). Also, previously a device that was NM_UNMANAGED_DEFAULT and in disconnected state would transition back to unmanaged. No longer do that. Once a device is managed, it stays managed as long as the flags indicate it should be managed. However, the user can also modify the unmanaged flags via the D-Bus API. Also get rid or nm_device_finish_init(). That was previously called by NMManager after add_device(). As we now realize devices (possibly multiple times) this should be handled during realization. https://bugzilla.gnome.org/show_bug.cgi?id=746566
2015-09-15 15:35:16 +02:00
if ( !nm_device_get_managed (device, FALSE)
|| g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ())
|| have_connection_for_device (self, device))
return;
connection = nm_device_new_default_connection (device);
if (!connection)
return;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_settings_add_connection (self,
connection,
NM_SETTINGS_CONNECTION_PERSIST_MODE_IN_MEMORY_ONLY,
NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED,
&added,
&error);
if (!added) {
if (!g_error_matches (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_UUID_EXISTS)) {
_LOGW ("(%s) couldn't create default wired connection: %s",
nm_device_get_iface (device),
error->message);
}
g_clear_error (&error);
return;
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_settings_connection_default_wired_set_device (added, device);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
g_object_set_qdata (G_OBJECT (device), _default_wired_connection_quark (), added);
2016-03-03 09:20:10 +01:00
_LOGI ("(%s): created default wired connection '%s'",
nm_device_get_iface (device),
nm_settings_connection_get_id (added));
}
void
nm_settings_device_added (NMSettings *self, NMDevice *device)
{
if (nm_device_is_real (device))
device_realized (device, NULL, self);
else {
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
/* FIXME(shutdown): we need to disconnect this signal handler during
* shutdown. */
g_signal_connect_after (device, "notify::" NM_DEVICE_REAL,
G_CALLBACK (device_realized),
self);
}
}
void
nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quitting)
{
NMSettingsConnection *connection;
g_signal_handlers_disconnect_by_func (device,
G_CALLBACK (device_realized),
self);
connection = g_object_get_qdata (G_OBJECT (device), _default_wired_connection_quark ());
if (connection) {
default_wired_clear_tag (self, device, connection, FALSE);
/* Don't delete the default wired connection on shutdown, so that it
* remains up and can be assumed if NM starts again.
*/
if (quitting == FALSE)
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_settings_connection_delete (connection, TRUE);
}
}
/*****************************************************************************/
static void
session_monitor_changed_cb (NMSessionMonitor *session_monitor,
NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMSettingsConnection *const*list;
guint i, len;
guint generation;
again:
list = nm_settings_get_connections (self, &len);
generation = priv->connections_generation;
for (i = 0; i < len; i++) {
gboolean is_visible;
is_visible = nm_settings_connection_check_visibility (list[i],
session_monitor);
nm_settings_connection_set_flags (list[i],
NM_SETTINGS_CONNECTION_INT_FLAGS_VISIBLE,
is_visible);
if (generation != priv->connections_generation) {
/* the cached list was invalidated. Start again.
*
* Note that nm_settings_connection_recheck_visibility() will do nothing
* if the visibility didn't change (including emitting no signals,
* and not invalidating the list).
*
* Hence, for this to be an endless loop, the settings would have
* to constantly change the visibility flag and also invalidate the list. */
goto again;
}
}
}
/*****************************************************************************/
G_GNUC_PRINTF (4, 5)
static void
_kf_db_log_fcn (NMKeyFileDB *kf_db,
int syslog_level,
gpointer user_data,
const char *fmt,
...)
{
NMSettings *self = user_data;
NMLogLevel level = nm_log_level_from_syslog (syslog_level);
if (_NMLOG_ENABLED (level)) {
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
gs_free char *msg = NULL;
va_list ap;
const char *prefix;
va_start (ap, fmt);
msg = g_strdup_vprintf (fmt, ap);
va_end (ap);
if (priv->kf_db_timestamps == kf_db)
prefix = "timestamps";
else if (priv->kf_db_seen_bssids == kf_db)
prefix = "seen-bssids";
else {
nm_assert_not_reached ();
prefix = "???";
}
_NMLOG (level, "[%s-keyfile]: %s", prefix, msg);
}
}
static gboolean
_kf_db_got_dirty_flush (NMSettings *self,
gboolean is_timestamps)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
const char *prefix;
NMKeyFileDB *kf_db;
if (is_timestamps) {
prefix = "timestamps";
kf_db = priv->kf_db_timestamps;
priv->kf_db_flush_idle_id_timestamps = 0;
} else {
prefix = "seen-bssids";
kf_db = priv->kf_db_seen_bssids;
priv->kf_db_flush_idle_id_seen_bssids = 0;
}
if (nm_key_file_db_is_dirty (kf_db))
nm_key_file_db_to_file (kf_db, FALSE);
else {
_LOGT ("[%s-keyfile]: skip saving changes to \"%s\"",
prefix,
nm_key_file_db_get_filename (kf_db));
}
return G_SOURCE_REMOVE;
}
static gboolean
_kf_db_got_dirty_flush_timestamps_cb (gpointer user_data)
{
return _kf_db_got_dirty_flush (user_data,
TRUE);
}
static gboolean
_kf_db_got_dirty_flush_seen_bssids_cb (gpointer user_data)
{
return _kf_db_got_dirty_flush (user_data,
FALSE);
}
static void
_kf_db_got_dirty_fcn (NMKeyFileDB *kf_db,
gpointer user_data)
{
NMSettings *self = user_data;
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
GSourceFunc idle_func;
guint *p_id;
const char *prefix;
if (priv->kf_db_timestamps == kf_db) {
prefix = "timestamps";
p_id = &priv->kf_db_flush_idle_id_timestamps;
idle_func = _kf_db_got_dirty_flush_timestamps_cb;
} else if (priv->kf_db_seen_bssids == kf_db) {
prefix = "seen-bssids";
p_id = &priv->kf_db_flush_idle_id_seen_bssids;
idle_func = _kf_db_got_dirty_flush_seen_bssids_cb;
} else {
nm_assert_not_reached ();
return;
}
if (*p_id != 0)
return;
_LOGT ("[%s-keyfile]: schedule flushing changes to disk", prefix);
*p_id = g_idle_add_full (G_PRIORITY_LOW, idle_func, self, NULL);
}
void
nm_settings_kf_db_write (NMSettings *self)
{
NMSettingsPrivate *priv;
g_return_if_fail (NM_IS_SETTINGS (self));
priv = NM_SETTINGS_GET_PRIVATE (self);
if (priv->kf_db_timestamps)
nm_key_file_db_to_file (priv->kf_db_timestamps, TRUE);
if (priv->kf_db_seen_bssids)
nm_key_file_db_to_file (priv->kf_db_seen_bssids, TRUE);
}
/*****************************************************************************/
gboolean
nm_settings_start (NMSettings *self, GError **error)
{
NMSettingsPrivate *priv;
gs_strfreev char **plugins = NULL;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
GSList *iter;
priv = NM_SETTINGS_GET_PRIVATE (self);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (!priv->started);
priv->hostname_manager = g_object_ref (nm_hostname_manager_get ());
priv->kf_db_timestamps = nm_key_file_db_new (NMSTATEDIR "/timestamps",
"timestamps",
_kf_db_log_fcn,
_kf_db_got_dirty_fcn,
self);
priv->kf_db_seen_bssids = nm_key_file_db_new (NMSTATEDIR "/seen-bssids",
"seen-bssids",
_kf_db_log_fcn,
_kf_db_got_dirty_fcn,
self);
nm_key_file_db_start (priv->kf_db_timestamps);
nm_key_file_db_start (priv->kf_db_seen_bssids);
/* Load the plugins; fail if a plugin is not found. */
plugins = nm_config_data_get_plugins (nm_config_get_data_orig (priv->config), TRUE);
if (!load_plugins (self, (const char *const*) plugins, error))
return FALSE;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
for (iter = priv->plugins; iter; iter = iter->next) {
NMSettingsPlugin *plugin = NM_SETTINGS_PLUGIN (iter->data);
g_signal_connect (plugin, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED,
G_CALLBACK (_plugin_unmanaged_specs_changed), self);
g_signal_connect (plugin, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED,
G_CALLBACK (_plugin_unrecognized_specs_changed), self);
}
_plugin_unmanaged_specs_changed (NULL, self);
_plugin_unrecognized_specs_changed (NULL, self);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
_plugin_connections_reload (self);
g_signal_connect (priv->hostname_manager,
"notify::"NM_HOSTNAME_MANAGER_HOSTNAME,
G_CALLBACK (_hostname_changed_cb),
self);
if (nm_hostname_manager_get_hostname (priv->hostname_manager))
_notify (self, PROP_HOSTNAME);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
priv->started = TRUE;
_startup_complete_check (self, 0);
/* FIXME(shutdown): we also need a nm_settings_stop() during shutdown.
*
* In particular, we need to remove all in-memory keyfiles from /run that are nm-generated.
* alternatively, the nm-generated flag must also be persisted and loaded to /run. */
return TRUE;
}
/*****************************************************************************/
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMSettings *self = NM_SETTINGS (object);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
2018-03-29 14:48:42 +02:00
const char **strv;
switch (prop_id) {
case PROP_UNMANAGED_SPECS:
g_value_take_boxed (value,
_nm_utils_slist_to_strv (nm_settings_get_unmanaged_specs (self),
TRUE));
break;
case PROP_HOSTNAME:
g_value_set_string (value,
priv->hostname_manager
? nm_hostname_manager_get_hostname (priv->hostname_manager)
: NULL);
break;
case PROP_CAN_MODIFY:
g_value_set_boolean (value, TRUE);
break;
case PROP_CONNECTIONS:
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
strv = nm_dbus_utils_get_paths_for_clist (&priv->connections_lst_head,
priv->connections_len,
G_STRUCT_OFFSET (NMSettingsConnection, _connections_lst),
TRUE);
g_value_take_boxed (value, nm_utils_strv_make_deep_copied (strv));
break;
case PROP_STARTUP_COMPLETE:
g_value_set_boolean (value, !nm_settings_get_startup_complete_blocked_reason (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_settings_init (NMSettings *self)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
c_list_init (&priv->auth_lst_head);
2018-03-29 14:48:42 +02:00
c_list_init (&priv->connections_lst_head);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
c_list_init (&priv->sce_dirty_lst_head);
priv->sce_idx = g_hash_table_new_full (nm_pstr_hash, nm_pstr_equal,
NULL, (GDestroyNotify) _sett_conn_entry_free);
priv->config = g_object_ref (nm_config_get ());
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
priv->agent_mgr = g_object_ref (nm_agent_manager_get ());
priv->platform = g_object_ref (NM_PLATFORM_GET);
priv->session_monitor = g_object_ref (nm_session_monitor_get ());
g_signal_connect (priv->session_monitor,
NM_SESSION_MONITOR_CHANGED,
G_CALLBACK (session_monitor_changed_cb),
self);
}
NMSettings *
nm_settings_new (void)
{
return g_object_new (NM_TYPE_SETTINGS, NULL);
}
static void
dispose (GObject *object)
{
NMSettings *self = NM_SETTINGS (object);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
CList *iter;
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (c_list_is_empty (&priv->sce_dirty_lst_head));
nm_assert (g_hash_table_size (priv->sce_idx) == 0);
nm_clear_g_source (&priv->startup_complete_timeout_id);
nm_clear_g_signal_handler (priv->platform, &priv->startup_complete_platform_change_id);
nm_clear_pointer (&priv->startup_complete_idx, g_hash_table_destroy);
g_clear_object (&priv->startup_complete_blocked_by);
while ((iter = c_list_first (&priv->auth_lst_head)))
nm_auth_chain_destroy (nm_auth_chain_parent_lst_entry (iter));
if (priv->hostname_manager) {
g_signal_handlers_disconnect_by_func (priv->hostname_manager,
G_CALLBACK (_hostname_changed_cb),
self);
g_clear_object (&priv->hostname_manager);
}
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
if (priv->session_monitor) {
g_signal_handlers_disconnect_by_func (priv->session_monitor,
G_CALLBACK (session_monitor_changed_cb),
self);
g_clear_object (&priv->session_monitor);
}
G_OBJECT_CLASS (nm_settings_parent_class)->dispose (object);
}
static void
finalize (GObject *object)
{
NMSettings *self = NM_SETTINGS (object);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
GSList *iter;
2018-03-29 14:48:42 +02:00
_clear_connections_cached_list (priv);
nm_assert (c_list_is_empty (&priv->connections_lst_head));
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
nm_assert (c_list_is_empty (&priv->sce_dirty_lst_head));
nm_assert (g_hash_table_size (priv->sce_idx) == 0);
nm_clear_pointer (&priv->sce_idx, g_hash_table_destroy);
g_slist_free_full (priv->unmanaged_specs, g_free);
g_slist_free_full (priv->unrecognized_specs, g_free);
while ((iter = priv->plugins)) {
gs_unref_object NMSettingsPlugin *plugin = iter->data;
priv->plugins = g_slist_delete_link (priv->plugins, iter);
g_signal_handlers_disconnect_by_data (plugin, self);
}
g_clear_object (&priv->keyfile_plugin);
g_clear_object (&priv->agent_mgr);
nm_clear_g_source (&priv->kf_db_flush_idle_id_timestamps);
nm_clear_g_source (&priv->kf_db_flush_idle_id_seen_bssids);
nm_key_file_db_to_file (priv->kf_db_timestamps, FALSE);
nm_key_file_db_to_file (priv->kf_db_seen_bssids, FALSE);
nm_key_file_db_destroy (priv->kf_db_timestamps);
nm_key_file_db_destroy (priv->kf_db_seen_bssids);
G_OBJECT_CLASS (nm_settings_parent_class)->finalize (object);
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
g_clear_object (&priv->config);
g_clear_object (&priv->platform);
}
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
static const GDBusSignalInfo signal_info_new_connection = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
"NewConnection",
.args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("connection", "o"),
),
);
static const GDBusSignalInfo signal_info_connection_removed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
"ConnectionRemoved",
.args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("connection", "o"),
),
);
static const NMDBusInterfaceInfoExtended interface_info_settings = {
.parent = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
NM_DBUS_INTERFACE_SETTINGS,
.methods = NM_DEFINE_GDBUS_METHOD_INFOS (
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"ListConnections",
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("connections", "ao"),
),
),
.handle = impl_settings_list_connections,
),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"GetConnectionByUuid",
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("uuid", "s"),
),
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("connection", "o"),
),
),
.handle = impl_settings_get_connection_by_uuid,
),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"AddConnection",
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"),
),
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("path", "o"),
),
),
.handle = impl_settings_add_connection,
),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"AddConnectionUnsaved",
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("connection", "a{sa{sv}}"),
),
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("path", "o"),
),
),
.handle = impl_settings_add_connection_unsaved,
),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"LoadConnections",
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("filenames", "as"),
),
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("status", "b"),
NM_DEFINE_GDBUS_ARG_INFO ("failures", "as"),
),
),
.handle = impl_settings_load_connections,
),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"ReloadConnections",
.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("status", "b"),
),
),
.handle = impl_settings_reload_connections,
),
NM_DEFINE_DBUS_METHOD_INFO_EXTENDED (
NM_DEFINE_GDBUS_METHOD_INFO_INIT (
"SaveHostname",
.in_args = NM_DEFINE_GDBUS_ARG_INFOS (
NM_DEFINE_GDBUS_ARG_INFO ("hostname", "s"),
),
),
.handle = impl_settings_save_hostname,
),
),
.signals = NM_DEFINE_GDBUS_SIGNAL_INFOS (
&nm_signal_info_property_changed_legacy,
&signal_info_new_connection,
&signal_info_connection_removed,
),
.properties = NM_DEFINE_GDBUS_PROPERTY_INFOS (
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Connections", "ao", NM_SETTINGS_CONNECTIONS),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("Hostname", "s", NM_SETTINGS_HOSTNAME),
NM_DEFINE_DBUS_PROPERTY_INFO_EXTENDED_READABLE_L ("CanModify", "b", NM_SETTINGS_CAN_MODIFY),
),
),
.legacy_property_changed = TRUE,
};
static void
nm_settings_class_init (NMSettingsClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
NMDBusObjectClass *dbus_object_class = NM_DBUS_OBJECT_CLASS (class);
dbus_object_class->export_path = NM_DBUS_EXPORT_PATH_STATIC (NM_DBUS_PATH_SETTINGS);
core/dbus: rework D-Bus implementation to use lower layer GDBusConnection API Previously, we used the generated GDBusInterfaceSkeleton types and glued them via the NMExportedObject base class to our NM types. We also used GDBusObjectManagerServer. Don't do that anymore. The resulting code was more complicated despite (or because?) using generated classes. It was hard to understand, complex, had ordering-issues, and had a runtime and memory overhead. This patch refactors this entirely and uses the lower layer API GDBusConnection directly. It replaces the generated code, GDBusInterfaceSkeleton, and GDBusObjectManagerServer. All this is now done by NMDbusObject and NMDBusManager and static descriptor instances of type GDBusInterfaceInfo. This adds a net plus of more then 1300 lines of hand written code. I claim that this implementation is easier to understand. Note that previously we also required extensive and complex glue code to bind our objects to the generated skeleton objects. Instead, now glue our objects directly to GDBusConnection. The result is more immediate and gets rid of layers of code in between. Now that the D-Bus glue us more under our control, we can address issus and bottlenecks better, instead of adding code to bend the generated skeletons to our needs. Note that the current implementation now only supports one D-Bus connection. That was effectively the case already, although there were places (and still are) where the code pretends it could also support connections from a private socket. We dropped private socket support mainly because it was unused, untested and buggy, but also because GDBusObjectManagerServer could not export the same objects on multiple connections. Now, it would be rather straight forward to fix that and re-introduce ObjectManager on each private connection. But this commit doesn't do that yet, and the new code intentionally supports only one D-Bus connection. Also, the D-Bus startup was simplified. There is no retry, either nm_dbus_manager_start() succeeds, or it detects the initrd case. In the initrd case, bus manager never tries to connect to D-Bus. Since the initrd scenario is not yet used/tested, this is good enough for the moment. It could be easily extended later, for example with polling whether the system bus appears (like was done previously). Also, restart of D-Bus daemon isn't supported either -- just like before. Note how NMDBusManager now implements the ObjectManager D-Bus interface directly. Also, this fixes race issues in the server, by no longer delaying PropertiesChanged signals. NMExportedObject would collect changed properties and send the signal out in idle_emit_properties_changed() on idle. This messes up the ordering of change events w.r.t. other signals and events on the bus. Note that not only NMExportedObject messed up the ordering. Also the generated code would hook into notify() and process change events in and idle handle, exhibiting the same ordering issue too. No longer do that. PropertiesChanged signals will be sent right away by hooking into dispatch_properties_changed(). This means, changing a property in quick succession will no longer be combined and is guaranteed to emit signals for each individual state. Quite possibly we emit now more PropertiesChanged signals then before. However, we are now able to group a set of changes by using standard g_object_freeze_notify()/g_object_thaw_notify(). We probably should make more use of that. Also, now that our signals are all handled in the right order, we might find places where we still emit them in the wrong order. But that is then due to the order in which our GObjects emit signals, not due to an ill behavior of the D-Bus glue. Possibly we need to identify such ordering issues and fix them. Numbers (for contrib/rpm --without debug on x86_64): - the patch changes the code size of NetworkManager by - 2809360 bytes + 2537528 bytes (-9.7%) - Runtime measurements are harder because there is a large variance during testing. In other words, the numbers are not reproducible. Currently, the implementation performs no caching of GVariants at all, but it would be rather simple to add it, if that turns out to be useful. Anyway, without strong claim, it seems that the new form tends to perform slightly better. That would be no surprise. $ time (for i in {1..1000}; do nmcli >/dev/null || break; echo -n .; done) - real 1m39.355s + real 1m37.432s $ time (for i in {1..2000}; do busctl call org.freedesktop.NetworkManager /org/freedesktop org.freedesktop.DBus.ObjectManager GetManagedObjects > /dev/null || break; echo -n .; done) - real 0m26.843s + real 0m25.281s - Regarding RSS size, just looking at the processes in similar conditions, doesn't give a large difference. On my system they consume about 19MB RSS. It seems that the new version has a slightly smaller RSS size. - 19356 RSS + 18660 RSS
2018-02-26 13:51:52 +01:00
dbus_object_class->interface_infos = NM_DBUS_INTERFACE_INFOS (&interface_info_settings);
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
obj_properties[PROP_UNMANAGED_SPECS] =
g_param_spec_boxed (NM_SETTINGS_UNMANAGED_SPECS, "", "",
G_TYPE_STRV,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_HOSTNAME] =
g_param_spec_string (NM_SETTINGS_HOSTNAME, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_CAN_MODIFY] =
g_param_spec_boolean (NM_SETTINGS_CAN_MODIFY, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_CONNECTIONS] =
g_param_spec_boxed (NM_SETTINGS_CONNECTIONS, "", "",
G_TYPE_STRV,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
obj_properties[PROP_STARTUP_COMPLETE] =
g_param_spec_boolean (NM_SETTINGS_STARTUP_COMPLETE, "", "",
FALSE,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[CONNECTION_ADDED] =
g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_ADDED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION);
signals[CONNECTION_UPDATED] =
g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_UPDATED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
NULL,
settings: rework tracking settings connections and settings plugins Completely rework how settings plugin handle connections and how NMSettings tracks the list of connections. Previously, settings plugins would return objects of (a subtype of) type NMSettingsConnection. The NMSettingsConnection was tightly coupled with the settings plugin. That has a lot of downsides. Change that. When changing this basic relation how settings connections are tracked, everything falls appart. That's why this is a huge change. Also, since I have to largely rewrite the settings plugins, I also added support for multiple keyfile directories, handle in-memory connections only by keyfile plugin and (partly) use copy-on-write NMConnection instances. I don't want to spend effort rewriting large parts while preserving the old way, that anyway should change. E.g. while rewriting ifcfg-rh, I don't want to let it handle in-memory connections because that's not right long-term. -- If the settings plugins themself create subtypes of NMSettingsConnection instances, then a lot of knowledge about tracking connections moves to the plugins. Just try to follow the code what happend during nm_settings_add_connection(). Note how the logic is spread out: - nm_settings_add_connection() calls plugin's add_connection() - add_connection() creates a NMSettingsConnection subtype - the plugin has to know that it's called during add-connection and not emit NM_SETTINGS_PLUGIN_CONNECTION_ADDED signal - NMSettings calls claim_connection() which hocks up the new NMSettingsConnection instance and configures the instance (like calling nm_settings_connection_added()). This summary does not sound like a lot, but try to follow that code. The logic is all over the place. Instead, settings plugins should have a very simple API for adding, modifying, deleting, loading and reloading connections. All the plugin does is to return a NMSettingsStorage handle. The storage instance is a handle to identify a profile in storage (e.g. a particular file). The settings plugin is free to subtype NMSettingsStorage, but it's not necessary. There are no more events raised, and the settings plugin implements the small API in a straightforward manner. NMSettings now drives all of this. Even NMSettingsConnection has now very little concern about how it's tracked and delegates only to NMSettings. This should make settings plugins simpler. Currently settings plugins are so cumbersome to implement, that we avoid having them. It should not be like that and it should be easy, beneficial and lightweight to create a new settings plugin. Note also how the settings plugins no longer care about duplicate UUIDs. Duplicated UUIDs are a fact of life and NMSettings must handle them. No need to overly concern settings plugins with that. -- NMSettingsConnection is exposed directly on D-Bus (being a subtype of NMDBusObject) but it was also a GObject type provided by the settings plugin. Hence, it was not possible to migrate a profile from one plugin to another. However that would be useful when one profile does not support a connection type (like ifcfg-rh not supporting VPN). Currently such migration is not implemented except for migrating them to/from keyfile's run directory. The problem is that migrating profiles in general is complicated but in some cases it is important to do. For example checkpoint rollback should recreate the profile in the right settings plugin, not just add it to persistent storage. This is not yet properly implemented. -- Previously, both keyfile and ifcfg-rh plugin implemented in-memory (unsaved) profiles, while ifupdown plugin cannot handle them. That meant duplication of code and a ifupdown profile could not be modified or made unsaved. This is now unified and only keyfile plugin handles in-memory profiles (bgo #744711). Also, NMSettings is aware of such profiles and treats them specially. In particular, NMSettings drives the migration between persistent and non-persistent storage. Note that a settings plugins may create truly generated, in-memory profiles. The settings plugin is free to generate and persist the profiles in any way it wishes. But the concept of "unsaved" profiles is now something explicitly handled by keyfile plugin. Also, these "unsaved" keyfile profiles are persisted to file system too, to the /run directory. This is great for two reasons: first of all, all profiles from keyfile storage in fact have a backing file -- even the unsaved ones. It also means you can create "unsaved" profiles in /run and load them with `nmcli connection load`, meaning there is a file based API for creating unsaved profiles. The other advantage is that these profiles now survive restarting NetworkManager. It's paramount that restarting the daemon is as non-disruptive as possible. Persisting unsaved files to /run improves here significantly. -- In the past, NMSettingsConnection also implemented NMConnection interface. That was already changed a while ago and instead users call now nm_settings_connection_get_connection() to delegate to a NMSimpleConnection. What however still happened was that the NMConnection instance gets never swapped but instead the instance was modified with nm_connection_replace_settings_from_connection(), clear-secrets, etc. Change that and treat the NMConnection instance immutable. Instead of modifying it, reference/clone a new instance. This changes that previously when somebody wanted to keep a reference to an NMConnection, then the profile would be cloned. Now, it is supposed to be safe to reference the instance directly and everybody must ensure not to modify the instance. nmtst_connection_assert_unchanging() should help with that. The point is that the settings plugins may keep references to the NMConnection instance, and so does the NMSettingsConnection. We want to avoid cloning the instances as long as they are the same. Likewise, the device's applied connection can now also be referenced instead of cloning it. This is not yet done, and possibly there are further improvements possible. -- Also implement multiple keyfile directores /usr/lib, /etc, /run (rh #1674545, bgo #772414). It was always the case that multiple files could provide the same UUID (both in case of keyfile and ifcfg-rh). For keyfile plugin, if a profile in read-only storage in /usr/lib gets modified, then it gets actually stored in /etc (or /run, if the profile is unsaved). -- While at it, make /etc/network/interfaces profiles for ifupdown plugin reloadable. -- https://bugzilla.gnome.org/show_bug.cgi?id=772414 https://bugzilla.gnome.org/show_bug.cgi?id=744711 https://bugzilla.redhat.com/show_bug.cgi?id=1674545
2019-06-13 17:12:20 +02:00
G_TYPE_NONE, 2, NM_TYPE_SETTINGS_CONNECTION, G_TYPE_UINT);
signals[CONNECTION_REMOVED] =
g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION);
signals[CONNECTION_FLAGS_CHANGED] =
g_signal_new (NM_SETTINGS_SIGNAL_CONNECTION_FLAGS_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
0, NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, NM_TYPE_SETTINGS_CONNECTION);
}