Merge ~gavin.lin/plainbox-provider-snappy:wifi-client-np into plainbox-provider-snappy:master

Proposed by Gavin Lin
Status: Superseded
Proposed branch: ~gavin.lin/plainbox-provider-snappy:wifi-client-np
Merge into: plainbox-provider-snappy:master
Diff against target: 353 lines (+318/-0)
3 files modified
bin/wifi_client_test_netplan (+172/-0)
units/wireless/jobs.pxu (+114/-0)
units/wireless/test-plan.pxu (+32/-0)
Reviewer Review Type Date Requested Status
Maciej Kisielewski Approve
Review via email: mp+341646@code.launchpad.net

This proposal supersedes a proposal from 2018-03-19.

This proposal has been superseded by a proposal from 2018-04-09.

Description of the change

Add automated wifi client test using netplan, this is the updated version.

To post a comment you must log in.
Revision history for this message
Maciej Kisielewski (kissiel) wrote : Posted in a previous version of this proposal

One big problem is a potential loss of config due to imperative moves on /etc/netplan.

I recommend using ContextManagers to guarantee proper rollback.

As for things that are not dangerous, but could be improved:
ping and connection tests should be functions returning a boolean indicating success, this way nested if/elses would disappear, as only return test_ping() would suffice.

Instead of using shell utilities I recommend using builtin shutil module. It's cleaner, less error prone and more informative when something goes wrong.

Also see inlines.

review: Needs Fixing
Revision history for this message
Gavin Lin (gavin.lin) wrote :

Updated according to Maciej's comments, thanks a lot.

Separated the copy part when backing up configuration file, so if anything goes wrong and unrecoverable, at least the backup is still there.

Also replaced all file manipulation with shutil module, and try to recover when things not going as expected.

Configuration file template and ping test are also updated.

Revision history for this message
Maciej Kisielewski (kissiel) wrote :

Personally I would find it much easier to work with if the wifi_client_test_netplan program had some structure. But this, I guess, can wait for the next rewrite.

Minor typo inline + PEP8 issues. The top-level comment in the script is misfit.
If you've got a minute run flake8 on the script to make it clean. Provisory +1

review: Approve
Revision history for this message
Gavin Lin (gavin.lin) wrote :

I'll update the script base on comments later, thanks a lot for pointing them out!

Unmerged commits

4cc9630... by Gavin Lin

Add automated wifi client test using netplan

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/bin/wifi_client_test_netplan b/bin/wifi_client_test_netplan
0new file mode 1007550new file mode 100755
index 0000000..86b6f01
--- /dev/null
+++ b/bin/wifi_client_test_netplan
@@ -0,0 +1,172 @@
1#!/usr/bin/env python3
2# Copyright 2018 Canonical Ltd.
3# All rights reserved.
4#
5# Written by:
6# Gavin Lin <gavin.lin@canonical.com>
7
8"""
9This script will test Wi-Fi device with netplan automatically.
10
11To see how to use, please run "./wifi_client_test_netplan --help"
12"""
13
14import argparse
15import os
16import subprocess
17import sys
18import time
19import shutil
20
21
22# Configuration file path
23if "SNAP_USER_DATA" in os.environ:
24 TMP_PATH = os.path.join(os.environ["SNAP_USER_DATA"],
25 "WIFI-TEST-NETPLAN-CREATED-BY-CHECKBOX")
26else:
27 TMP_PATH = os.path.join("/tmp", "WIFI-TEST-NETPLAN-CREATED-BY-CHECKBOX")
28CFG_PATH = "/etc/netplan"
29CFG_FILE = "/etc/netplan/99-CREATED-BY-CHECKBOX.yaml"
30
31# Read arguments
32parser = argparse.ArgumentParser(
33 description=("This script will test wireless network with netplan"
34 " in client mode."))
35parser.add_argument(
36 "-i", "--interface", type=str, help=(
37 "The interface which will be tested, default is wlan0"),
38 default="wlan0")
39parser.add_argument(
40 "-s", "--ssid", type=str, help=(
41 "SSID of target network, this is required argument"),
42 required=True)
43parser.add_argument(
44 "-k", "--psk", type=str, help=(
45 "Pre-shared key of target network, this is optional argument,"
46 " only for PSK protected network"))
47parser.add_argument(
48 "-d", "--dhcp", action='store_true', help=(
49 "Enable DHCP for IPv4"),
50 default=False)
51parser.add_argument(
52 "-a", "--address", type=str, help=(
53 "Set ip address for the test interface, optional argument,"
54 " example: 192.168.1.1/24"),
55 default="")
56parser.add_argument(
57 "-p", "--ping", action='store_true', help=(
58 "Enable ping test, will only check link status if not enabled"),
59 default=False)
60parser.add_argument(
61 "-v", "--server", type=str, help=(
62 "Set ip of server which respond to ping, default is default gateway,"
63 " example: 192.168.1.2"),
64 default="")
65args = parser.parse_args()
66
67# Check if executed with root
68if os.geteuid() != 0:
69 raise SystemExit("Error: please run this command as root")
70
71# Backup current network configuration file
72shutil.rmtree(TMP_PATH, ignore_errors=True)
73try:
74 shutil.copytree(CFG_PATH, TMP_PATH, symlinks=True)
75except:
76 shutil.rmtree(TMP_PATH, ignore_errors=True)
77 raise SystemExit("Failed to backup network config files, exiting...")
78
79# Remove configuration file, since backup created successfully,
80# ignore exception while deleting
81for item in os.listdir(CFG_PATH):
82 target_path = os.path.join(CFG_PATH, item)
83 if os.path.isfile(target_path):
84 try:
85 os.remove(target_path)
86 except:
87 pass
88 elif os.path.isdir(target_path):
89 shutil.rmtree(target_path, ignore_errors=True)
90
91# If there's any file left in configuration folder,
92# then there's something not excepted, stop the test
93if os.listdir(CFG_PATH):
94 print("Failed to manipulate network config file")
95 print("Restoring network config file from backup...")
96 try:
97 for item in os.listdir(TMP_PATH):
98 target_path = os.path.join(TMP_PATH, item)
99 shutil.move(target_path, CFG_PATH)
100 except:
101 raise SystemExit("Failed to restore network config file from " +
102 TMP_PATH + ", please check it manually")
103 shutil.rmtree(TMP_PATH, ignore_errors=True)
104 raise SystemExit("Configutation file restored, exiting...")
105
106# Create wireless network test configuration file
107if args.psk:
108 pass_field = "password: " + args.psk
109else:
110 pass_field = ""
111
112# Template
113np_cfg = """# This is the network config written by checkbox
114network:
115 version: 2
116 wifis:
117 {interface}:
118 access-points:
119 {ssid}: {{{password}}}
120 addresses: [{address}]
121 dhcp4: {dhcp}
122 nameservers: {{}}"""
123
124# Fill data and write to file
125cfg_data = {"interface": args.interface, "ssid": args.ssid,
126 "password": pass_field, "address": args.address,
127 "dhcp": str(args.dhcp)}
128with open(CFG_FILE, "w", encoding="utf-8") as wifi_cfg_file:
129 wifi_cfg_file.write(np_cfg.format(**cfg_data))
130
131# Bring up the interface
132subprocess.call(["netplan", "apply"])
133time.sleep(10)
134
135# Check connection by ping or link status
136server_ip = ""
137if args.ping:
138 # Get gateway ip for ping test
139 if args.server == "":
140 route_table = subprocess.check_output(["route", "-n"]).decode()
141 for line in route_table.split("\n"):
142 if args.interface in line and "UG" in line:
143 server_ip = line.split()[1]
144 else:
145 server_ip = args.server
146 # Test connection by ping
147 exit_code = subprocess.call([
148 "ping", "-c", "5", "-I", args.interface, server_ip])
149else:
150 # Test connection by checking if link established
151 test_output = subprocess.check_output([
152 "iw", args.interface, "link"]).decode()
153 if test_output.find("SSID") != -1:
154 print("Connection test passed")
155 exit_code = 0
156 else:
157 print("Connection test failed")
158 exit_code = 1
159
160# Restore configuration file and apply
161os.remove(CFG_FILE)
162try:
163 for item in os.listdir(TMP_PATH):
164 target_path = os.path.join(TMP_PATH, item)
165 shutil.move(target_path, CFG_PATH)
166except:
167 raise SystemExit("Failed to restore network config file from " +
168 TMP_PATH + ", please check it manually")
169shutil.rmtree(TMP_PATH, ignore_errors=True)
170subprocess.call(["netplan", "apply"])
171time.sleep(10)
172sys.exit(exit_code)
diff --git a/units/wireless/jobs.pxu b/units/wireless/jobs.pxu
index dded027..ac8b4da 100644
--- a/units/wireless/jobs.pxu
+++ b/units/wireless/jobs.pxu
@@ -130,6 +130,120 @@ flags: preserve-locale also-after-suspend
130130
131unit: template131unit: template
132template-resource: device132template-resource: device
133template-filter: device.category == 'WIRELESS'
134template-engine: jinja2
135template-unit: job
136id: wireless/wireless_connection_open_ac_np_{{ interface }}
137_summary:
138 Connect to unencrypted 802.11ac Wi-Fi network on {{ interface }} - netplan
139_purpose:
140 Check system can connect to insecure 802.11ac AP using netplan
141plugin: shell
142command:
143 wifi_client_test_netplan -i {{ interface }} -s $OPEN_AC_SSID -dp
144user: root
145environ: LD_LIBRARY_PATH OPEN_AC_SSID
146category_id: wifi
147estimated_duration: 15
148flags: preserve-locale also-after-suspend
149
150unit: template
151template-resource: device
152template-filter: device.category == 'WIRELESS'
153template-engine: jinja2
154template-unit: job
155id: wireless/wireless_connection_open_bg_np_{{ interface }}
156_summary:
157 Connect to unencrypted 802.11b/g Wi-Fi network on {{ interface }} - netplan
158_purpose:
159 Check system can connect to insecure 802.11b/g AP using netplan
160plugin: shell
161command:
162 wifi_client_test_netplan -i {{ interface }} -s $OPEN_BG_SSID -dp
163user: root
164environ: LD_LIBRARY_PATH OPEN_BG_SSID
165category_id: wifi
166estimated_duration: 15
167flags: preserve-locale also-after-suspend
168
169unit: template
170template-resource: device
171template-filter: device.category == 'WIRELESS'
172template-engine: jinja2
173template-unit: job
174id: wireless/wireless_connection_open_n_np_{{ interface }}
175_summary:
176 Connect to unencrypted 802.11n Wi-Fi network on {{ interface }} - netplan
177_purpose:
178 Check system can connect to insecure 802.11n AP using netplan
179plugin: shell
180command:
181 wifi_client_test_netplan -i {{ interface }} -s $OPEN_N_SSID -dp
182user: root
183environ: LD_LIBRARY_PATH OPEN_N_SSID
184category_id: wifi
185estimated_duration: 15
186flags: preserve-locale also-after-suspend
187
188unit: template
189template-resource: device
190template-filter: device.category == 'WIRELESS'
191template-engine: jinja2
192template-unit: job
193id: wireless/wireless_connection_wpa_ac_np_{{ interface }}
194_summary:
195 Connect to WPA-encrypted 802.11ac Wi-Fi network on {{ interface }} - netplan
196_purpose:
197 Check system can connect to 802.11ac AP with wpa security using netplan
198plugin: shell
199command:
200 wifi_client_test_netplan -i {{ interface }} -s $WPA_AC_SSID -k $WPA_AC_PSK -dp
201user: root
202environ: LD_LIBRARY_PATH WPA_AC_SSID WPA_AC_PSK
203category_id: wifi
204estimated_duration: 15
205flags: preserve-locale also-after-suspend
206
207unit: template
208template-resource: device
209template-filter: device.category == 'WIRELESS'
210template-engine: jinja2
211template-unit: job
212id: wireless/wireless_connection_wpa_bg_np_{{ interface }}
213_summary:
214 Connect to WPA-encrypted 802.11b/g Wi-Fi network on {{ interface }} - netplan
215_purpose:
216 Check system can connect to 802.11b/g AP with wpa security using netplan
217plugin: shell
218command:
219 wifi_client_test_netplan -i {{ interface }} -s $WPA_BG_SSID -k $WPA_BG_PSK -dp
220user: root
221environ: LD_LIBRARY_PATH WPA_BG_SSID WPA_BG_PSK
222category_id: wifi
223estimated_duration: 15
224flags: preserve-locale also-after-suspend
225
226unit: template
227template-resource: device
228template-filter: device.category == 'WIRELESS'
229template-engine: jinja2
230template-unit: job
231id: wireless/wireless_connection_wpa_n_np_{{ interface }}
232_summary:
233 Connect to WPA-encrypted 802.11n Wi-Fi network on {{ interface }} - netplan
234_purpose:
235 Check system can connect to 802.11n AP with wpa security using netplan
236plugin: shell
237command:
238 wifi_client_test_netplan -i {{ interface }} -s $WPA_N_SSID -k $WPA_N_PSK -dp
239user: root
240environ: LD_LIBRARY_PATH WPA_N_SSID WPA_N_PSK
241category_id: wifi
242estimated_duration: 15
243flags: preserve-locale also-after-suspend
244
245unit: template
246template-resource: device
133template-filter: device.category == 'WIRELESS' and device.mac != 'UNKNOWN'247template-filter: device.category == 'WIRELESS' and device.mac != 'UNKNOWN'
134id: wireless/wowlan_S5_{interface}_wakeonlan248id: wireless/wowlan_S5_{interface}_wakeonlan
135_summary: Wake on Wireless LAN (WoWLAN) test from S5 - {interface} - wakeonlan249_summary: Wake on Wireless LAN (WoWLAN) test from S5 - {interface} - wakeonlan
diff --git a/units/wireless/test-plan.pxu b/units/wireless/test-plan.pxu
index 0650f97..f7817ce 100644
--- a/units/wireless/test-plan.pxu
+++ b/units/wireless/test-plan.pxu
@@ -40,6 +40,22 @@ include:
40bootstrap_include:40bootstrap_include:
41 device41 device
4242
43id: wireless-netplan-automated
44unit: test plan
45_name: Automated tests for wireless using netplan
46_description:
47 Automated connection tests for unencrypted or WPA-encrypted 802.11 bg, n, ac
48 networks using netplan.
49include:
50 wireless/wireless_connection_open_ac_np_.*
51 wireless/wireless_connection_open_bg_np_.*
52 wireless/wireless_connection_open_n_np_.*
53 wireless/wireless_connection_wpa_ac_np_.*
54 wireless/wireless_connection_wpa_bg_np_.*
55 wireless/wireless_connection_wpa_n_np_.*
56bootstrap_include:
57 device
58
43id: wireless-wifi-master-mode59id: wireless-wifi-master-mode
44unit: test plan60unit: test plan
45_name: QA tests for wifi master mode61_name: QA tests for wifi master mode
@@ -124,6 +140,22 @@ include:
124bootstrap_include:140bootstrap_include:
125 device141 device
126142
143id: after-suspnend-wireless-netplan-automated
144unit: test plan
145_name: Automated tests for wireless using netplan (after suspend)
146_description:
147 Automated connection tests for unencrypted or WPA-encrypted 802.11 bg, n, ac
148 networks using netplan.
149include:
150 after-suspend-wireless/wireless_connection_open_ac_np_.*
151 after-suspend-wireless/wireless_connection_open_bg_np_.*
152 after-suspend-wireless/wireless_connection_open_n_np_.*
153 after-suspend-wireless/wireless_connection_wpa_ac_np_.*
154 after-suspend-wireless/wireless_connection_wpa_bg_np_.*
155 after-suspend-wireless/wireless_connection_wpa_n_np_.*
156bootstrap_include:
157 device
158
127id: after-suspend-wireless-wifi-master-mode159id: after-suspend-wireless-wifi-master-mode
128unit: test plan160unit: test plan
129_name: QA tests for wifi master mode (after suspend)161_name: QA tests for wifi master mode (after suspend)

Subscribers

People subscribed via source and target branches

to all changes: