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

How to programatically configure Wicked using DBus? #958

Open
Sinihopea opened this issue Mar 22, 2023 · 1 comment
Open

How to programatically configure Wicked using DBus? #958

Sinihopea opened this issue Mar 22, 2023 · 1 comment

Comments

@Sinihopea
Copy link

Hello,

my apologies if this isn't the correct forum to present programming questions but I'm writing a "for fun" Wicked configuration utility for my personal use that would allow me to make quick adjustments to my interfaces through a Qt-based GUI without having to invoke YaST as well as also monitor status of my interfaces. I know how to write programs using Qt but I don't have a very strong background in using DBus. I'm mostly using this to learn little bit more about Dbus and QDbus and how it is used to talk to programs in the desktop bus.

I studied the basic DBus examples and now I'm trying to put together a "real world program" that would do "something useful". I've so far managed to extract the current Wicked configuration through DBus as a one giant blob of maps and arrays and parse through it. It roughly matches with what would come out when I do "wicked show-xml all". I've done it by just making a basic call to "/org/opensuse/Network/org.freedesktop.DBus.ObjectManager" by invoking "GetManagedObjects()" method.

Next I'd like to learn how to make simple changes to the current in-memory configuration of eth0 for example or If possible I'd like to monitor the status of my interface and various properties it has. I'm having bit of a trouble with both goals.

I probably have a configuration issue since I don't see using qdbusviewer program e.g. "/org/opensuse/Network/Interfaces/" in the bus that is mentioned by the Wicked's documentation. However it is mentioned in the list of stuff that comes from "GetManagedObjects()" method. But attempts to introspect it end in failure as if it doesn't exist.

Also it doesn't seem to be possible to call Wicked through DBus and save the configuration as a file in to /etc/wicked/ifconfig/ as an XML. It seems like I have to get my small program eventually to write the configuration there myself. This also seems to be one of the fundamental differences between the Wicked and NetworkManager in sense that Wicked doesn't provide any kind of "helper" library like NetworkManagerQt package does for Qt programmers for making adjustments to the in-memory network configuration.

I'm aware of the various factories for configuration such as the "org.opensuse.Network.Ethernet.Factory" but that as well doesn't seem to exist or I'm making a wrong kind of calls to it or Wicked on my system isn't configured to allow creation of new interface configurations that way.

I've attempted to do other stuff based on Wicked's documentation by browsing "wicked/doc/schema/*.html" but it's quite overwhelming to be honest. I'm still in the beginning so maybe at some point it will "hit me" better.

So without making this too long...

Is there an example that shows how to configure Wicked to assign a static address to an Ethernet interface through DBus? This could be shown through use of "busctl" utility for example here. It would help me improve my understanding how this thing works.

I understand that since I'm doing this "for fun" you guys might not be interested in helping. But seeing how there are tickets open for Wicked status bar icons and "wicked-gui" this might help the person who really will write that GUI applet if there was little bit more explanation of this stuff.

As for my OS I have OpenSUSE Leap 15.3 installation which I haven't had time to upgrade yet.

Thank you and it might take some time before I reply back.

@cfconrad
Copy link
Collaborator

Hello Sinihopea,

sorry for the late response! It's a great Idea and we are happy to hear you will try that out!

Unfortunately, the current implementation of wicked doesn't have an official DBus interface.

This is how the wicked ecosystem works from a very high level:

[wicked] <----------------> [wickedd-nanny] <------------------> [wickedd]
  • wicked: Is the client utility, reads config files (ifcfg, xml,...) translates them to xml-config (as in /etc/wicked/ifconfig/), sends them enveloped as policies via DBus to nanny and monitors the setup progress events (DBus signals) from nanny.
  • wickedd-nanny: Executes wickedd methods via DBus to apply the configuration to the interface tree and handles hotplug and other events it receives from wickedd.
  • wickedd: This daemon executed the methods called by nanny, configures the kernel and others like wpa_supplicant, wickedd-dhcp*,... and collects events like rtnetlink to forward them to nanny.

See also this detailed view wicked-component-flow.pdf

A Configuration program should use the DBus interface of the wickedd-nanny daemon.
We cannot provide here other documentation then the code it self, but I will try to point you in the correct direction.

Example:

This example should illustrate how to use policies to configure an interface.
Policies are the "configurations" which are needed by wickedd-nanny.
Wicked internal configuration format is in XML, same as we use for policies.
Let's start from the ifcfg-format, translate it to xml-policy and send it via
DBus to nanny. Afterwards we simply change the IP to demonstrate a configuration
change.

Let's assume this simple static network configuration of eth0:

ifc=eth0
cat > "ifcfg-$ifc" << 'EOT'
STARTAUTO=auto                                                                                                                                                                                                                            
BOOTPROTO=static                                                                                                                                                                                                                          
IPADDR=192.168.0.2/24
EOT

then we can translate it to a policy,

wicked show-policy --ifconfig compat:suse:./ "$ifc" > "policy__$ifc.xml"

A policy is an envelope around the config:

<policy>
  <match>..</match>
  <$action>${config}</$action>
<policy>

where ${config} is the content of the <interface/> node from show-config and actions are merge or replace.

Then let's send the policy to wickedd-nanny using DBus,

dbus-send --system --print-reply --dest=org.opensuse.Network.Nanny \
  /org/opensuse/Network/Nanny org.opensuse.Network.Nanny.createPolicy \
  "string:$(cat "policy__$ifc.xml")"

calling org.opensuse.Network.Nanny.recheck on the interface and
let wickedd-nanny does it's job.

dbus-send --system --print-reply --dest=org.opensuse.Network.Nanny \
  /org/opensuse/Network/Nanny org.opensuse.Network.Nanny.recheck \
  array:string:"$ifc"

After some time the interface should become up and an IPAddress assigned. Simply verify the IP via ip a s dev "$ifc" or wicked ifstatus "$ifc".

Now changing the IPAddress to something different,

sed -i 's/192.168.0.2/192.168.0.42/' "policy__$ifc.xml"

update our previous policy,

dbus-send --system --print-reply --dest=org.opensuse.Network.Nanny \
  "/org/opensuse/Network/Nanny/Policy/policy__$ifc" org.opensuse.Network.ManagedPolicy.update \
  "string:$(cat "policy__$ifc.xml")"

and calling recheck() again to trigger update by wickedd-nanny.

dbus-send --system --print-reply --dest=org.opensuse.Network.Nanny \
  /org/opensuse/Network/Nanny org.opensuse.Network.Nanny.recheck \
  array:string:"$ifc"

Pitfalls

That's looks actually quite straight-forward, but we know that there are pitfalls here and there.

For instance the ifdown isn't implemented that way and the wicked client does some work which actually belongs into the wickedd-nanny (we are working on this).

Also, as you already noticed, almost all Introspectable interfaces need some love.

Policy names cannot contain a . (dot), so a policy name like policy__eth0.42 will result in an invalid DBus path.


Thx for your interest and let me know whats missing. Next time I try to be faster in response!
Best regards
Clemens

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