Disconnect a WiFi accespoint using cNetworkManager Python library



Hi,

I’m building an Python application that has to connect and disconnect from Wifi on linux box. It's my very first experience with d-bus and gobject.

I’m using NetworkManager layer, through the nice networkmanager lib found in cnetworkmanager (http://vidner.net/martin/software/cnetworkmanager/ thanx to Martin Vidner), in my daemon (named stationd).

This daemon runs a gobject.MainLoop. Once a timeout_add_seconds awake (triggers by an action of user in GUI), I have to disconnect current running Wifi and connect to a new one:

    from dbus.mainloop.glib import DBusGMainLoop
    DBusGMainLoop(set_as_default=True)

    from networkmanager import NetworkManager
    import networkmanager.applet.settings as settings
    from networkmanager.applet import USER_SERVICE 
    from networkmanager.applet.service import NetworkManagerUserSettings, NetworkManagerSettings
    import time
    import memcache

    import gobject
    loop = gobject.MainLoop()

    nm = NetworkManager()

    dummy_handler = lambda *args: None

    cache = memcache.Client(['127.0.0.1:11211',] )


    def get_device(dev_spec, hint):
        candidates = []
        devs = NetworkManager().GetDevices()
        for dev in devs:
            if dev._settings_type() == hint:
                candidates.append(dev)
        if len(candidates) == 1:
            return candidates[0]
        for dev in devs:
            if dev["Interface"] == dev_spec:
                return dev
        print "Device '%s' not found" % dev_spec
        return None

    def kill_allconnections():
        connections=nm['ActiveConnections']
        for c in connections:
            print c.object_path
            nm.DeactivateConnection(c.object_path)

    class Wifi(object):
        
        def connect(self, ssid, security="open", password=None):
            "Connects to given Wifi network"
            c=None # connection settings
            us = NetworkManagerUserSettings([])
            if security=="open":
                c = settings.WiFi(ssid)
            elif security=="wep":
                c = settings.Wep(ssid, password)
            elif security=="wpa":
                c = settings.WpaPsk(ssid, password)
            else:
                raise AttributeError("invalid security model '%s'"%security)
            svc = USER_SERVICE
            svc_conn = us.addCon(c.conmap)
            hint = svc_conn.settings["connection"]["type"]
            dev = get_device("", hint)
            appath = "/"
            nm.ActivateConnection(svc, svc_conn, dev, appath, reply_handler=dummy_handler, error_handler=dummy_handler)


    def change_network_settings():
        key="station:network:change"
        change=cache.get(key)
        if change is not None:
            print "DISCONNECT"
            kill_allconnections()
            print "CHANGE SETTINGS"
            wifi=cache.get(key+':wifi')
            if wifi is not None:
                ssid=cache.get(key+':wifi:ssid')
                security=cache.get(key+':wifi:security')
                password=cache.get(key+':wifi:password')
                print "SWITCHING TO %s"%ssid
                Wifi().connect(ssid, security, password)
            cache.delete(key)
        return True    

    def mainloop():
       gobject.timeout_add_seconds(1, change_network_settings)
       try:
          loop.run()
       except KeyboardInterrupt:
          loop.quit()

    if __name__=="__main__":
        mainloop()

This runs perfectly for a first connection (read : the box is not connected, daemon is ran and box connects flawlessly to Wifi). Issue is when I try to connect to another Wifi : kill_allconnections() is ran silently, and connect method raises an exception on nm.ActivateConnection:

    Traceback (most recent call last):
      File "stationd.py", line 40, in change_network_settings
        Wifi().connect(ssid, security, password)
      File "/home/biopredictive/station/lib/network.py", line 88, in connect
        us = NetworkManagerUserSettings([])
      File "/home/biopredictive/station/lib/networkmanager/applet/service/__init__.py", line 71, in __init__
        super(NetworkManagerUserSettings, self).__init__(conmaps, USER_SERVICE)
      File "/home/biopredictive/station/lib/networkmanager/applet/service/__init__.py", line 33, in __init__
        dbus.service.Object.__init__(self, bus, opath, bus_name)
      File "/usr/lib/pymodules/python2.6/dbus/service.py", line 480, in __init__
        self.add_to_connection(conn, object_path)
      File "/usr/lib/pymodules/python2.6/dbus/service.py", line 571, in add_to_connection
        self._fallback)
    KeyError: "Can't register the object-path handler for '/org/freedesktop/NetworkManagerSettings': there is already a handler"

It looks like my former connection didn’t release all its resources ? 

Would you please help ?

(I've asked this question on StackOverflow, too : http://stackoverflow.com/q/8938509/532219 )
--

Olivier Deckmyn | olivier deckmyn org | 06 73 40 89 88




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]