3
# This program is free software: you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License version 3,
5
# as published by the Free Software Foundation.
7
# This program is distributed in the hope that it will be useful,
8
# but WITHOUT ANY WARRANTY; without even the implied warranty of
9
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
# GNU General Public License for more details.
12
# You should have received a copy of the GNU General Public License
13
# along with this program; if not, write to the Free Software Foundation,
14
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
# Parts of this are based on the example python code that ships with
18
# http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/examples/python
20
# Copyright (C) 2012 Canonical, Ltd.
22
from subprocess import check_output, CalledProcessError, STDOUT
27
from checkbox_support.parsers.modinfo import ModinfoParser
28
from checkbox_support.parsers.udevadm import UdevadmParser
31
# This example lists basic information about network interfaces known to NM
32
devtypes = {1: "Ethernet",
39
states = {0: "Unknown",
53
attributes = ("category", "interface", "product", "vendor", "driver", "path")
60
def addDevice(self, device):
62
udev_devices.append(device)
65
class NetworkingDevice():
66
def __init__(self, devtype, props, dev_proxy, bus):
67
self._devtype = devtype
69
self._interface = props['Interface']
71
self._interface = "Unknown"
74
self._ip = self._int_to_ip(props['Ip4Address'])
79
self._driver = props['Driver']
81
self._driver = "Unknown"
82
self._driver_ver = "Unknown"
84
if self._driver != "Unknown":
85
self._modinfo = self._modinfo_parser(props['Driver'])
87
self._driver_ver = self._find_driver_ver()
89
self._driver_ver = "Unknown"
92
self._firmware_missing = props['FirmwareMissing']
94
self._firmware_missing = False
97
self._state = states[props['State']]
99
self._state = "Unknown"
102
ret = "Category: %s\n" % self._devtype
103
ret += "Interface: %s\n" % self._interface
104
ret += "IP: %s\n" % self._ip
105
ret += "Driver: %s (ver: %s)\n" % (self._driver, self._driver_ver)
106
if self._firmware_missing:
107
ret += "Warning: Required Firmware Missing for device\n"
108
ret += "State: %s\n" % self._state
117
def _bitrate_to_mbps(self, bitrate):
120
return str(intbr / 1000)
124
def _modinfo_parser(self, driver):
125
cmd = ['/sbin/modinfo', driver]
127
stream = check_output(cmd, stderr=STDOUT, universal_newlines=True)
128
except CalledProcessError as err:
129
print("Error running %s:" % ' '.join(cmd), file=sys.stderr)
130
print(err.output, file=sys.stderr)
134
print("Error: modinfo returned nothing", file=sys.stderr)
137
parser = ModinfoParser(stream)
138
modinfo = parser.get_all()
142
def _find_driver_ver(self):
143
# try the version field first, then vermagic second, some audio
144
# drivers don't report version if the driver is in-tree
145
if self._modinfo['version'] and self._modinfo['version'] != 'in-tree:':
146
return self._modinfo['version']
148
# vermagic will look like this (below) and we only care about the
150
# "3.2.0-29-generic SMP mod_unload modversions"
151
return self._modinfo['vermagic'].split()[0]
153
def _int_to_ip(self, int_ip):
155
ip[0] = int_ip & 0xff
156
ip[1] = (int_ip >> 8) & 0xff
157
ip[2] = (int_ip >> 16) & 0xff
158
ip[3] = (int_ip >> 24) & 0xff
159
return "%d.%d.%d.%d" % (ip[0], ip[1], ip[2], ip[3])
162
def get_nm_devices():
164
bus = dbus.SystemBus()
166
# Get a proxy for the base NetworkManager object
167
proxy = bus.get_object("org.freedesktop.NetworkManager",
168
"/org/freedesktop/NetworkManager")
169
manager = dbus.Interface(proxy, "org.freedesktop.NetworkManager")
171
# Get all devices known to NM and print their properties
172
nm_devices = manager.GetDevices()
174
dev_proxy = bus.get_object("org.freedesktop.NetworkManager", d)
175
prop_iface = dbus.Interface(dev_proxy,
176
"org.freedesktop.DBus.Properties")
177
props = prop_iface.GetAll("org.freedesktop.NetworkManager.Device")
179
devtype = devtypes[props['DeviceType']]
183
# only return WiFi, Ethernet and Modem devices
184
if devtype in ("WiFi", "Ethernet", "Modem"):
185
devices.append(NetworkingDevice(devtype, props, dev_proxy, bus))
189
def match_counts(nm_devices, udev_devices, devtype):
191
Ensures that the count of devices matching devtype is the same for the
192
two passed in lists, devices from Network Manager and devices from lspci.
194
# now check that the count (by type) matches
195
nm_type_devices = [dev for dev in nm_devices if dev.gettype() in devtype]
196
udevtype = 'WIRELESS' if devtype == 'WiFi' else 'NETWORK'
197
udev_type_devices = [
199
for udev in udev_devices
200
if udev.category == udevtype]
201
if len(nm_type_devices) != len(udev_type_devices):
202
print("ERROR: devices missing - udev showed %d %s devices, but "
203
"NetworkManager saw %d devices in %s" % (len(udev_type_devices),
204
udevtype, len(nm_type_devices), devtype), file=sys.stderr)
212
output = check_output(['udevadm', 'info', '--export-db'])
213
except CalledProcessError as err:
214
raise SystemExit(err)
216
output = output.decode("UTF-8", errors='ignore')
217
except UnicodeDecodeError as err:
218
raise SystemExit("udevadm output is not valid UTF-8")
219
udev = UdevadmParser(output)
220
result = UdevResult()
224
print("[ Devices found by udev ]".center(80, '-'))
225
for device in udev_devices:
226
for attribute in attributes:
227
value = getattr(device, attribute)
228
if value is not None:
229
if attribute == 'driver':
231
props['Driver'] = value
232
network_dev = NetworkingDevice(None, props, None, None)
233
print("%s: %s (ver: %s)" % (attribute.capitalize(),
234
value, network_dev._driver_ver))
236
print("%s: %s" % (attribute.capitalize(), value))
241
nm_devices = get_nm_devices()
242
except dbus.exceptions.DBusException as e:
243
# server's don't have network manager installed
244
print("Warning: Exception while talking to Network Manager over dbus."
245
" Skipping the remainder of this test. If this is a server, this"
246
" is expected.", file=sys.stderr)
247
print("The Error Generated was:\n %s" % e, file=sys.stderr)
250
print("[ Devices found by Network Manager ]".center(80, '-'))
251
for nm_dev in nm_devices:
254
if not match_counts(nm_devices, udev_devices, "WiFi"):
256
elif not match_counts(nm_devices, udev_devices, ("Ethernet","Modem")):
261
if __name__ == "__main__":
262
sys.exit(main(sys.argv[1:]))