1. 16 Jul, 2019 1 commit
    • Thomas Haller's avatar
      settings: rework tracking settings connections and settings plugins · d35d3c46
      Thomas Haller authored
      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
      d35d3c46
  2. 13 Jun, 2019 1 commit
  3. 11 Jun, 2019 1 commit
    • Thomas Haller's avatar
      all: drop emacs file variables from source files · c0e075c9
      Thomas Haller authored
      We no longer add these. If you use Emacs, configure it yourself.
      
      Also, due to our "smart-tab" usage the editor anyway does a subpar
      job handling our tabs. However, on the upside every user can choose
      whatever tab-width he/she prefers. If "smart-tabs" are used properly
      (like we do), every tab-width will work.
      
      No manual changes, just ran commands:
      
          F=($(git grep -l -e '-\*-'))
          sed '1 { /\/\* *-\*-  *[mM]ode.*\*\/$/d }'     -i "${F[@]}"
          sed '1,4 { /^\(#\|--\|dnl\) *-\*- [mM]ode/d }' -i "${F[@]}"
      
      Check remaining lines with:
      
          git grep -e '-\*-'
      
      The ultimate purpose of this is to cleanup our files and eventually use
      SPDX license identifiers. For that, first get rid of the boilerplate lines.
      c0e075c9
  4. 06 Sep, 2018 2 commits
    • Thomas Haller's avatar
      settings: make NMSettingsPlugin a regular GObject instance and not an interface · 657b0714
      Thomas Haller authored
      NMSettingsPlugin was a glib interface, not a regular GObject
      instance. Accordingly, settings plugins would implement this interface
      instead of subclassing a parent type.
      
      Refactor the code, and make NMSettingsPlugin a GObject type. Plugins
      are now required to subclass this type.
      
      Glib interfaces are more cumbersome than helpful. At least, unless
      there is a good reason for using them.
      
      Our settings plugins are all internal API and are entirely under
      our control. It also means, this change is fine, as there are no
      implementations outside of this source tree.
      
      Using interfaces do would allow more flexibility in implementing the
      settings plugin.
      For example, the plugin would be able to derive from any other GObject
      type, like NMKimchiRefrigerator. But why would we even? Let's not add monster
      classes that implement house appliances beside NMSettingsPluginInterface.
      The settings plugin should have one purpose only: being a settings plugin.
      Hence, requiring it to subclass NMSettingsPlugin is more than resonable. We
      don't need interfaces for this.
      
      Now that NMSettingsPlugin is a regular object instance, it may also have
      state, and potentially could provide common functionality for the plugin
      implementation -- if that turns out to be useful. Arguably, an interface can
      have state too, for example by attaching the state somewhere else (like
      NMConnection does). But let's just say no.
      
      On a minor note, this also avoids some tiny overhead that comes with
      glib interfaces.
      657b0714
    • Thomas Haller's avatar
      settings: rename NMSettingsPluginInterface.init() to initialize() · 194e7f8d
      Thomas Haller authored
      The virtual function init() naturally leads to calling the wrapper
      function nm_settings_plugin_init(). However, such ${TYPE}_init() functions
      are generated by G_DEFINE_TYPE().
      
      Rename to avoid the naming conflict, which will matter next, when the
      interface will be converted to a regular GObject class.
      
      Note that while these are settings plugin, there is no public
      or stable API which we need to preserve.
      194e7f8d
  5. 31 May, 2018 1 commit
  6. 27 Oct, 2017 1 commit
  7. 03 Mar, 2016 1 commit
  8. 19 Feb, 2016 1 commit
    • Thomas Haller's avatar
      all: cleanup includes and let "nm-default.h" include "config.h" · 8bace23b
      Thomas Haller authored
      - All internal source files (except "examples", which are not internal)
        should include "config.h" first. As also all internal source
        files should include "nm-default.h", let "config.h" be included
        by "nm-default.h" and include "nm-default.h" as first in every
        source file.
        We already wanted to include "nm-default.h" before other headers
        because it might contains some fixes (like "nm-glib.h" compatibility)
        that is required first.
      
      - After including "nm-default.h", we optinally allow for including the
        corresponding header file for the source file at hand. The idea
        is to ensure that each header file is self contained.
      
      - Don't include "config.h" or "nm-default.h" in any header file
        (except "nm-sd-adapt.h"). Public headers anyway must not include
        these headers, and internal headers are never included after
        "nm-default.h", as of the first previous point.
      
      - Include all internal headers with quotes instead of angle brackets.
        In practice it doesn't matter, because in our public headers we must
        include other headers with angle brackets. As we use our public
        headers also to compile our interal source files, effectively the
        result must be the same. Still do it for consistency.
      
      - Except for <config.h> itself. Include it with angle brackets as suggested by
        https://www.gnu.org/software/autoconf/manual/autoconf.html#Configuration-Headers
      8bace23b
  9. 10 Sep, 2015 3 commits
    • Dan Winship's avatar
      core: fix interface type names · 8e9f7820
      Dan Winship authored
      A GObject interface, like a class, has two different C types
      associated with it; the type of the "class" struct (eg, GObjectClass,
      GFileIface), and the type of instances of that class/interface (eg,
      GObject, GFile).
      
      NetworkManager was doing this wrong though, and using the same C type
      to point to both the interface's class struct and to instances of the
      interface. This ends up not actually breaking anything, since for
      interface types, the instance type is a non-dereferenceable dummy type
      anyway. But it's wrong, since if, eg, NMDeviceFactory is a struct type
      containing members "start", "device_added", etc, then you should not
      be using an NMDeviceFactory* to point to an object that does not
      contain those members.
      
      Fix this by splitting NMDeviceFactory into NMDeviceFactoryInterface
      and NMDeviceFactory; by splitting NMConnectionProvider into
      NMConnectionProviderInterface and NMConnectionProvider; and by
      splitting NMSettingsPlugin into NMSettingsPluginInterface and
      NMSettingsPlugin; and then use the right types in the right places.
      
      As a bonus, this also lets us now use G_DEFINE_INTERFACE.
      8e9f7820
    • Dan Winship's avatar
      settings: remove some NMSettingsPlugin cruft · b3d56e48
      Dan Winship authored
      b3d56e48
    • Dan Winship's avatar
      settings: trivial: rename NMSystemConfigInterface to NMSettingsPlugin · dfb77e3b
      Dan Winship authored
      Since there have not been separate system and user settings services
      since 0.8, the "system" in NMSystemConfigInterface is kind of
      meaningless. Rename it to NMSettingsPlugin, which describes what it
      does better.
      
      This is just:
      
          git mv src/settings/nm-system-config-interface.h src/settings/nm-settings-plugin.h
          git mv src/settings/nm-system-config-interface.c src/settings/nm-settings-plugin.c
          perl -pi -e 's/SystemConfigInterface/SettingsPlugin/g;' \
                   -e 's/system_config_interface/settings_plugin/g;' \
                   -e 's/system-config-interface/settings-plugin/g;' \
                   -e 's/SYSTEM_CONFIG_INTERFACE/SETTINGS_PLUGIN/g;' \
                   -e 's/sc_plugin/settings_plugin/g;' \
                   -e 's/SC_PLUGIN/SETTINGS_PLUGIN/g;' \
                   -e 's/SC_IS_PLUGIN/SETTINGS_IS_PLUGIN/g;' \
                   -e 's/SC_TYPE_PLUGIN/SETTINGS_TYPE_PLUGIN/g;' \
                   -e 's/SCPlugin/SettingsPlugin/g;' \
                   -e 's/nm_system_config_factory/nm_settings_plugin_factory/g;' \
               $(find src/settings -type f)
      
      (followed by some whitespace fixups in nm-settings-plugin.c, and a
      Makefile.am fix for the rename)
      dfb77e3b