Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NetworkManager.Settings.Connection cannot round-trip, calling Update with what GetSettings returned #124

Open
mvidner opened this issue Oct 25, 2022 · 3 comments

Comments

@mvidner
Copy link
Owner

mvidner commented Oct 25, 2022

(reported by @imobachgs)

We would like to use ruby-dbus to interact with NetworkManager through D-Bus. The following example tries to use the method to Update a connection. It basically asks for the current configuration (GetSettings) an tries to apply the same configuration (calling Update).

require "dbus"

bus = ::DBus::SystemBus.instance
service = bus.service("org.freedesktop.NetworkManager")
settings_obj = service.object("/org/freedesktop/NetworkManager/Settings")

# find a settings object (a.k.a. connections)
settings_path, *_others = settings_obj["org.freedesktop.NetworkManager.Settings"].ListConnections.first

# set settings configuration
nm_settings = service.object(settings_path)
conn_settings = nm_settings["org.freedesktop.NetworkManager.Settings.Connection"].GetSettings.first

puts "Current configuration", conn_settings.inspect
nm_settings.Update(conn_settings)

However, it fails because data types for empty values (empty arrays and hashes) are not what NetworkManager expects. Our guess is that there is no typing information available, so ruby-dbus cannot figure out what to send in such cases.

/usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:364:in `block in send_sync_or_async': connection.permissions: wrong type; should be a list of strings.; caused by 3 sender=:1.7 -> dest=:1.499 serial=1943 reply_serial=12 path=; interface=; member= error_name=org.freedesktop.NetworkManager.Settings.Connection.InvalidProperty (DBus::Error)
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:552:in `process'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:486:in `send_sync'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:363:in `send_sync_or_async'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/proxy_object_interface.rb:70:in `block (2 levels) in define_method_from_descriptor'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/proxy_object.rb:113:in `call'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/proxy_object.rb:113:in `block (3 levels) in define_shortcut_methods'
        from a.rb:16:in `<main>'
/usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:364:in `block in send_sync_or_async': connection.permissions: wrong type; should be a list of strings. (DBus::Error)
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:552:in `process'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:486:in `send_sync'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:363:in `send_sync_or_async'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/proxy_object_interface.rb:70:in `block (2 levels) in define_method_from_descriptor'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/proxy_object.rb:113:in `call'
        from /usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/proxy_object.rb:113:in `block (3 levels) in define_shortcut_methods'
        from change-nm.rb:16:in `<main>'

Even if we do not send any empty attribute (cleaning up the settings), we find an additional problem with ipv4.address-data:

/usr/lib64/ruby/gems/3.1.0/gems/ruby-dbus-0.18.1/lib/dbus/bus.rb:364:in `block in send_sync_or_async': ipv4.address-data: can't set property of type 'aa{sv}' from value of type 'av'; caused by 3 sender=:1.7 -> dest=:1.545 serial=2082 reply_serial=12 path=; interface=; member= error_name=org.freedesktop.NetworkManager.Settings.Connection.InvalidProperty (DBus::Error)

Are our assumptions right? Do we have a way to workaround this problem?

Thanks!

@mvidner
Copy link
Owner Author

mvidner commented Oct 25, 2022

I've had success on my machine with applying this transformation between GetSettings and Update

def fix_types(settings)
  types = {
    "connection.permissions" => "as",
    "802-11-wireless.mac-address" => "ay",
    "802-11-wireless.mac-address-blacklist" => "as",
    "802-11-wireless.ssid" => "ay",
    "ipv4.address-data" => "aa{sv}",
    "ipv4.addresses" => "aau",
    "ipv4.dns" => "au",
    "ipv4.dns-search" => "as",
    "ipv4.route-data" => "aa{sv}",
    "ipv4.routes" => "aau",
    "ipv6.address-data" => "aa{sv}",
    "ipv6.addresses" => "a(ayuay)",
    "ipv6.dns" => "aay",
    "ipv6.dns-search" => "as",
    "ipv6.route-data" => "aa{sv}",
    "ipv6.routes" => "a(ayuayu)"
  }

  types.each do |dot_prop, type|
    section, prop = dot_prop.split "."
    settings[section][prop] = ::DBus::Data.make_typed(type, settings[section][prop])
  end
end

fix_types(conn_settings)

See https://www.rubydoc.info/gems/ruby-dbus/0.18.1/DBus/Data#make_typed-class_method

"A-Ayu-Ayu!" is my favorite type from now on!

@mvidner
Copy link
Owner Author

mvidner commented Oct 25, 2022

In general, I'd like to improve the library so that you'll be able to specify that a method call (like GetSettings) should only return DBus::Data values instead of plain Ruby values. They need unwrapping but are the perfect fit for round-tripping like this.

@mvidner mvidner changed the title NetworkManager.Settings.Connection cannot round-trip, calling Update with what GetSettings retured NetworkManager.Settings.Connection cannot round-trip, calling Update with what GetSettings returned Oct 25, 2022
@imobachgs
Copy link

It works just fine. Having an API to do this kind of type annotation is more than enough for us. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants