~shanepatrickfagan/ubuntu-sso-client/nm-state-bug-fix

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# -*- coding: utf-8 -*-
#
# networkstate - detect the current state of the network
#
# Author: Alejandro J. Cura <alecu@canonical.com>
#
# Copyright 2010 Canonical Ltd.
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 3, as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranties of
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
# PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program.  If not, see <http://www.gnu.org/licenses/>.
"""Implementation of network state detection."""

import dbus

from ubuntu_sso.logger import setup_logging
logger = setup_logging("ubuntu_sso.networkstate")

# Values returned by the callback
ONLINE, OFFLINE, UNKNOWN = object(), object(), object()

NM_STATE_NAMES = {
    ONLINE: "online",
    OFFLINE: "offline",
    UNKNOWN: "unknown",
}

NM_DBUS_INTERFACE = "org.freedesktop.NetworkManager"
NM_DBUS_OBJECTPATH = "/org/freedesktop/NetworkManager"
DBUS_UNKNOWN_SERVICE = "org.freedesktop.DBus.Error.ServiceUnknown"


class NetworkManagerState(object):
    """Checks the state of NetworkManager thru DBus."""

    def __init__(self, result_cb, dbus_module=dbus):
        """Initialize this instance with a result and error callbacks."""
        self.result_cb = result_cb
        self.dbus = dbus_module
        self.state_signal = None

    def call_result_cb(self, state):
        """Return the state thru the result callback."""
        if self.state_signal:
            self.state_signal.remove()
        self.result_cb(state)

    def got_state(self, state):
        """Called by DBus when the state is retrieved from NM."""
        if state == self.NM_STATE_CONNECTED:
            self.call_result_cb(ONLINE)
        elif state == self.NM_STATE_CONNECTING:
            logger.debug("Currently connecting, waiting for signal")
        else:
            self.call_result_cb(OFFLINE)

    def got_error(self, error):
        """Called by DBus when the state is retrieved from NM."""
        if isinstance(error, self.dbus.exceptions.DBusException) and \
                error.get_dbus_name() == DBUS_UNKNOWN_SERVICE:
            logger.debug("Network Manager not present")
            self.call_result_cb(UNKNOWN)
        else:
            logger.error("Error contacting NetworkManager: %s" % \
                             str(error))
            self.call_result_cb(UNKNOWN)

    def state_changed(self, state):
        """Called when a signal is emmited by Network Manager."""
        if int(state) == self.NM_STATE_CONNECTED:
            self.call_result_cb(ONLINE)
        elif int(state) == self.NM_STATE_DISCONNECTED:
            self.call_result_cb(OFFLINE)
        else:
            logger.debug("Not yet connected: continuing to wait")

    def find_online_state(self):
        """Get the network state and return it thru the set callback."""
        try:
            sysbus = self.dbus.SystemBus()
            nm_proxy = sysbus.get_object(NM_DBUS_INTERFACE,
                                         NM_DBUS_OBJECTPATH,
                                         follow_name_owner_changes=True)
            nm_if = self.dbus.Interface(nm_proxy, NM_DBUS_INTERFACE)
            self.check_nm_state_version(nm_proxy)
            self.state_signal = nm_if.connect_to_signal(
                        signal_name="StateChanged",
                        handler_function=self.state_changed,
                        dbus_interface=NM_DBUS_INTERFACE)
            nm_proxy.Get(NM_DBUS_INTERFACE, "State",
                         reply_handler=self.got_state,
                         error_handler=self.got_error)
        except Exception, e:  # pylint: disable=W0703
            self.got_error(e)

    def check_nm_state_version(self, nm_proxy):
        """ detect the version and choose the correct values"""
        version = str(nm_proxy.Get(NM_DBUS_INTERFACE,
                    "Version")).split(".")
        new_state_version = False
        print "checking nm version for state API"
        print version
        print int(version[1])
        if int(version[0]) == 0 and int(version[1]) <= 8:
            print "below version 8"
            if int(version[1]) == 8 and version[2].startswith("99"):
                    new_state_version = True
        else:
            new_state_version = True
        if new_state_version == True:
            print "New state version"
            self.NM_STATE_ASLEEP = 10
            self.NM_STATE_DISCONNECTED = 20
            self.NM_STATE_CONNECTING = 40
            self.NM_STATE_CONNECTED = 70
        else:
            print "old state version"
            self.NM_STATE_ASLEEP = 1
            self.NM_STATE_CONNECTING = 2
            self.NM_STATE_CONNECTED = 3
            self.NM_STATE_DISCONNECTED = 4    
        self.NM_STATE_UNKNOWN = 0