Showing posts with label introspection. Show all posts
Showing posts with label introspection. Show all posts

Saturday, September 22, 2012

Dbus Tutorial - Fun with Network Manager

Introduction
Introspection: figuring out the rules 
Fun with Network Manager
Create a service 
Gobject Introspection


Let's figure out how to use  dbus to get detailed information out of Network Manager (NM), and then to plug our own information back into NM.

Example #1: This script determines if a specific network is the active connection. This is handy for, say, mapping network printers or networked drives, or setting the time, or automating backups, or lots of other stuff.

#!/bin/sh
# What network am I on?

# Get the Active Connection path
# Result should be like: /org/freedesktop/NetworkManager/ActiveConnection/187
active_connection_path=$( dbus-send --system --print-reply \
                          --dest=org.freedesktop.NetworkManager \
                          /org/freedesktop/NetworkManager \
                          org.freedesktop.DBus.Properties.Get \
                          string:"org.freedesktop.NetworkManager" \
                          string:"ActiveConnections" \
                          | grep ActiveConnection/ | cut -d'"' -f2 )

# Get the Access Point path
# Result should be like: /org/freedesktop/NetworkManager/AccessPoint/194
access_point_path=$( dbus-send --system --print-reply \
                     --dest=org.freedesktop.NetworkManager \
                     "$active_connection_path" \
                     org.freedesktop.DBus.Properties.Get \
                     string:"org.freedesktop.NetworkManager.Connection.Active" \
                     string:"SpecificObject" \
                     | grep variant | cut -d'"' -f2 )

# Get the Access Point ESSID
# Result should be something like "NETGEAR"
essid=$( dbus-send --system --print-reply \
                   --dest=org.freedesktop.NetworkManager \
                   "$access_point_path" \
                   org.freedesktop.DBus.Properties.Get \
                   string:"org.freedesktop.NetworkManager.AccessPoint" \
                   string:"Ssid" \
                   | grep variant | cut -d'"' -f2 )



# If we are on the HOME network
if [ "$essid"=="MyHomeNet" ]; then
   # Do network-specific changes here

elif [ "$essid"=="WorkCorporateNet" ]
   # Do network-specific changes here

else
   # Do changes for unrecognized network or no network at all here

fi
exit 0


Example #2: Disable networking

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.Set \
            string:"org.freedesktop.NetworkManager" \
            string:"NetworkingEnabled" \
            variant:boolean:false


Example #3: Enable networking. It's exactly the same as the previous example, except for the last line.

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.Set \
            string:"org.freedesktop.NetworkManager" \
            string:"NetworkingEnabled" \
            variant:boolean:true


Example #4: Check networking status

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager" \
            string:"NetworkingEnabled"

method return sender=:1.4 -> dest=:1.325 reply_serial=2
   variant       boolean true


Example #5: Disable Wireless

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.Set \
            string:"org.freedesktop.NetworkManager" \
            string:"WirelessEnabled" \
            variant:boolean:false


Example #6: Enable Wireless

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.Set \
            string:"org.freedesktop.NetworkManager" \
            string:"WirelessEnabled" \
            variant:boolean:true


Example #7: Check Wireless Status

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager" \
            string:"WirelessEnabled"

method return sender=:1.4 -> dest=:1.326 reply_serial=2
   variant       boolean true


Example #8:




Example #9: List all active network connections

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager" \
            string:"ActiveConnections"

method return sender=:1.4 -> dest=:1.328 reply_serial=2
   variant       array [
         object path "/org/freedesktop/NetworkManager/ActiveConnection/18"
      ]


Example #10: Which interface is the active connection using?

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/ActiveConnection/18 \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager.Connection.Active" \
            string:"Devices"

method return sender=:1.4 -> dest=:1.331 reply_serial=2
   variant       array [
         object path "/org/freedesktop/NetworkManager/Devices/0"

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/Devices/0 \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager.Device" \
            string:"Interface"

method return sender=:1.4 -> dest=:1.332 reply_serial=2
   variant       string "wlan0"


Example #11: Get the current wireless access point

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/ActiveConnection/18 \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager.Connection.Active" \
            string:"SpecificObject"

method return sender=:1.4 -> dest=:1.334 reply_serial=2
   variant       object path "/org/freedesktop/NetworkManager/AccessPoint/209"


Example #12: Get the list of all visible wireless access points

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager 
            /org/freedesktop/NetworkManager/Devices/0 \
            org.freedesktop.NetworkManager.Device.Wireless.GetAccessPoints

method return sender=:1.4 -> dest=:1.333 reply_serial=2
   array [
      object path "/org/freedesktop/NetworkManager/AccessPoint/209"
      object path "/org/freedesktop/NetworkManager/AccessPoint/208"
      object path "/org/freedesktop/NetworkManager/AccessPoint/207"
      object path "/org/freedesktop/NetworkManager/AccessPoint/206"
   ]


Example #13: Read the SSID of the active wireless access point

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/AccessPoint/209 \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager.AccessPoint" \
            string:"Ssid"

method return sender=:1.4 -> dest=:1.335 reply_serial=2
   variant       array of bytes "NETGEAR"


Example #14: Read the signal strength of the active wireless point

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/AccessPoint/209 \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager.AccessPoint" \
            string:"Strength"

method return sender=:1.4 -> dest=:1.340 reply_serial=2
   variant       byte 54
# 54 in byte (hexadecimal) = 84 in decimal. Strength = 84%


Example #15: Read the stored NM connection that is currently active

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/ActiveConnection/18 \
            org.freedesktop.DBus.Properties.Get \
            string:"org.freedesktop.NetworkManager.Connection.Active" \
            string:"Connection"

method return sender=:1.4 -> dest=:1.379 reply_serial=2
   variant       object path "/org/freedesktop/NetworkManager/Settings/10"


Example #16: Disconnect from the current network connection (auto-reconnect)

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager \
            org.freedesktop.NetworkManager.DeactivateConnection \
            objpath:"/org/freedesktop/NetworkManager/ActiveConnection/18"

method return sender=:1.4 -> dest=:1.370 reply_serial=2


Example #17: Disconnect from the current network connection and stay disconnected

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/Devices/0 \
            org.freedesktop.NetworkManager.Device.Disconnect

method return sender=:1.4 -> dest=:1.354 reply_serial=2


Example #18: Connect to a specific wireless network

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            org/freedesktop/NetworkManager \
            org.freedesktop.NetworkManager.ActivateConnection \
            objpath:"/org/freedesktop/NetworkManager/Settings/10" \
            objpath:"/org/freedesktop/NetworkManager/Devices/0" \
            objpath:"/org/freedesktop/NetworkManager/AccessPoint/209"

method return sender=:1.4 -> dest=:1.382 reply_serial=2
   object path "/org/freedesktop/NetworkManager/ActiveConnection/20"


Example #19: Dump all information about an access point

$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            /org/freedesktop/NetworkManager/Settings/10 \
            org.freedesktop.NetworkManager.Settings.Connection.GetSettings

method return sender=:1.4 -> dest=:1.386 reply_serial=2
   array [## EDITED - it's really long]


Thursday, August 2, 2012

Dbus Tutorial - Introspection: Figuring Out The Rules

Introduction
Introspection
Network Manager 
Create a Service
Gobject Introspection


Last time, we discussed what to use dbus for and the basics of structuring a dbus command. We went over how to structure the grammar of a command so it makes sense (mapping the destination, path, method, and message elements), and we went over the syntax (stringing together those elements in a coherent way).

This lesson is about figuring out what methods are available and how to use them.


Introspection

dbus is introspectable. That means you can ask dbus what commands are available.

Here's an introspection example. You can see that the return is XML wrapped inside a string (you don't need to read it all):

$ dbus-send --system --print-reply --dest=org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.4 -> dest=:1.441 reply_serial=2
   string "
<node>
  <interface name="org.freedesktop.DBus.Introspectable">
    <method name="Introspect">
      <arg direction="out" name="data" type="s">
    </arg></method>
  <interface name="org.freedesktop.DBus.Properties">
    <method name="Get">
      <arg direction="in" name="interface" type="s">
      <arg direction="in" name="propname" type="s">
      <arg direction="out" name="value" type="v">
    </arg></arg></arg></method>
    <method name="Set">
      <arg direction="in" name="interface" type="s">
      <arg direction="in" name="propname" type="s">
      <arg direction="in" name="value" type="v">
    </arg></arg></arg></method>
    <method name="GetAll">
      <arg direction="in" name="interface" type="s">
      <arg direction="out" name="props" type="a{sv}">
    </arg></arg></method>
  </interface>
  <interface name="org.freedesktop.NetworkManager">
    <method name="state">
      <arg direction="out" name="state" type="u">
    </arg></method>
    <method name="SetLogging">
      <arg direction="in" name="level" type="s">
      <arg direction="in" name="domains" type="s">
    </arg></arg></method>
    <method name="GetPermissions">
      <arg direction="out" name="permissions" type="a{ss}">
    </arg></method>
    <method name="Enable">
      <arg direction="in" name="enable" type="b">
    </arg></method>
    <method name="Sleep">
      <arg direction="in" name="sleep" type="b">
    </arg></method>
    <method name="DeactivateConnection">
      <arg direction="in" name="active_connection" type="o">
    </arg></method>
    <method name="AddAndActivateConnection">
      <arg direction="in" name="connection" type="a{sa{sv}}">
      <arg direction="in" name="device" type="o">
      <arg direction="in" name="specific_object" type="o">
      <arg direction="out" name="path" type="o">
      <arg direction="out" name="active_connection" type="o">
    </arg></arg></arg></arg></arg></method>
    <method name="ActivateConnection">
      <arg direction="in" name="connection" type="o">
      <arg direction="in" name="device" type="o">
      <arg direction="in" name="specific_object" type="o">
      <arg direction="out" name="active_connection" type="o">
    </arg></arg></arg></arg></method>
    <method name="GetDeviceByIpIface">
      <arg direction="in" name="iface" type="s">
      <arg direction="out" name="device" type="o">
    </arg></arg><<method>
    <method name="GetDevices">
      <arg direction="out" name="devices" type="ao">
    </arg></method>
     <signal name="DeviceRemoved">
       <arg type="o">
     </arg> </signal>
     <signal name="DeviceAdded">
       <arg type="o">
     </arg> </signal>
     <signal name="PropertiesChanged">
       <arg type="a{sv}">
     </arg> </signal>
     <signal name="StateChanged">
       <arg type="u">
     </arg> </signal>
     <signal name="CheckPermissions">
     </signal>
     <property access="read" name="State" type="u">
     <property access="read" name="Version" type="s">
     <property access="read" name="ActiveConnections" type="ao">
     <property access="read" name="WimaxHardwareEnabled" type="b">
     <property access="readwrite" name="WimaxEnabled" type="b">
     <property access="read" name="WwanHardwareEnabled" type="b">
     <property access="readwrite" name="WwanEnabled" type="b">
     <property access="read" name="WirelessHardwareEnabled" type="b">
     <property access="readwrite" name="WirelessEnabled" type="b">
     <property access="read" name="NetworkingEnabled" type="b">
   </property> </property> </property> </property> </property> </property> </property> </property> </property> </property>
   <node name="AccessPoint">
   <node name="ActiveConnection">
   <node name="AgentManager">
   <node name="DHCP4Config">
   <node name="Devices">
   <node name="IP4Config">
   <node name="Settings">
 </node>
" </node> </node> </node> </node> </node> </node>

 
Let's see if we can translate this into something more human readable.

For example,

<node>
  <interface name="org.freedesktop.DBus.Introspectable">
    <method name="Introspect">
      <arg direction="out" name="data" type="s">
    </arg&gt;&lt;/method> 
  ... 
</node>

is the method we used for introspection (remember?).

See the org.freedesktop.DBus.Introspectable.Introspect?  The arg direction "out" means the the response, and type "d" means data string).


How to use introspection to create a dbus query or command

Here's a slightly more complex example of an introspection response:

  <interface name="org.freedesktop.DBus.Properties">
    ...
    <method name="GetAll">
      <arg direction="in" name="interface" type="s">
      <arg direction="out" name="props" type="a{sv}">
    </arg> </arg> </method>
    ...
  <interface name="org.freedesktop.NetworkManager"> 

This generic method, org.freedesktop.DBus.Properties.GetAll, returns a complete dump of all of some other interface's properties.

Let's go back to grammar (destination, path, method, message) and say that again:

I want to see a dump of Network manager's top-level properties.
"Hey Network Manager, please give me a printout of all of Network Manager's top-level properties."

Destination: "Hey, Network Manager": org.freedesktop.NetworkManager

Path:  "Network Manager's": org/freedesktop/NetworkManager

Method: "Give me a printout of properties": org.freedesktop.DBus.Properties.GetAll

Message: "top-level": org.freedesktop.NetworkManager

You probably noticed that this example has some duplication. When working with dbus, get used to it.


Now let's put it into the right syntax:

dbus-send   [ --system| --session] --print-reply --dest=DEST PATH METHOD [MESSAGE]


$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            org/freedesktop/NetworkManager \
            org.freedesktop.DBus.Properties.GetAll \
            string:"org.freedesktop.NetworkManager"


Let's do one more slightly different example:

<interface name="org.freedesktop.NetworkManager">
    ...
    <method name="ActivateConnection">
      <arg direction="in" name="connection" type="o">
      <arg direction="in" name="device" type="o">
      <arg direction="in" name="specific_object" type="o">
      <arg direction="out" name="active_connection" type="o">
    </arg> </arg> </arg> </arg> </method>

 </node>
" </node> </node> </node> </node> </node> </node>

This method, ActivateConnection, makes a known connection into the active network connection. For example, when switching from one access point to another. There are three extra pieces of information needed, and network manager returns one piece of information in the response.

Let's go back to grammar (destination, path, method, message) and say that again:

"Hey Network Manager, make Access Point Foo (using wireless device 0 and network password settings 67) the active connection."

Destination: "Hey, Network Manager": org.freedesktop.NetworkManager

Path:  "Network Manager": org/freedesktop/NetworkManager

Method: "Make...the active connection": org.freedesktop.NetworkManager.ActivateConnection

Message 1: "Access Point Foo": org/freedesktop/NetworkManager/AccessPoint/220

Message 2: "wireless device 0": org/freedesktop/NetworkManager/Device/0

Message 3: "network password info 67": org/freedesktop/NetworkManager/Settings/67

Now let's put it into the right syntax:

dbus-send   [ --system| --session] --print-reply --dest=DEST PATH METHOD [MESSAGE]


$ dbus-send --system --print-reply \
            --dest=org.freedesktop.NetworkManager \
            org/freedesktop/NetworkManager \
            org.freedesktop.NetworkManager/ActivateConnection \
            objpath:"org/freedesktop/NetworkManager/AccessPoint/220" \
            objpath:"org/freedesktop/NetworkManager/Device/0" \
            objpath:"org/freedesktop/NetworkManager/Settings/67"

Obviously, this example won't work for you unless you do the introspection to find valid Access Points, Devices, and Settings that work together. dbus will tell you a lot of it...if you ask...but it's not a user-friendly graphical user interface. You need to ask the right questions and use your own logic.

Making introspection easier is where d-feet comes in.


d-feet makes introspection easy

d-feet is a python application (part of the d-feet package in Debian and Ubuntu) that does introspection for you while you write your program.


In this screenshot, you can see lots of the same introspection information that we retrieved before. Easier to read and understand, isn't it? See how the Interfaces and Methods are listed for each Object Path?

Without d-feet, use the following dbus-send command to find out what's available on the bus:

$ dbus-send --session --print-reply --dest="org.freedesktop.DBus" /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames


Now you know how to find the information you need to use dbus properly.