blob: a05eca455be96fc55d3c607bc880009e8cc1d6ee [file] [log] [blame]
Omar El Ayach32b3afa2017-10-02 15:23:53 -07001#!/usr/bin/env python3.4
2#
3# Copyright 2017 - The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16import splinter
Omar El Ayach7a6e2412018-05-17 20:00:54 -070017import time
18from acts.libs.proc import job
android-build-prod (mdb)dd7347e2018-05-03 23:13:56 -070019from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
Omar El Ayach32b3afa2017-10-02 15:23:53 -070020
21BROWSER_WAIT_SHORT = 1
22BROWSER_WAIT_MED = 3
Omar El Ayachd0c4b942018-01-30 06:02:14 +000023BROWSER_WAIT_LONG = 30
24BROWSER_WAIT_EXTRA_LONG = 60
Omar El Ayach32b3afa2017-10-02 15:23:53 -070025
26
27def create(configs):
Omar El Ayach7a6e2412018-05-17 20:00:54 -070028 """Factory method for retail AP class.
Omar El Ayach32b3afa2017-10-02 15:23:53 -070029
30 Args:
31 configs: list of dicts containing ap settings. ap settings must contain
32 the following: brand, model, ip_address, username and password
33 """
34 SUPPORTED_APS = {
35 ("Netgear", "R7000"): "NetgearR7000AP",
36 ("Netgear", "R7500"): "NetgearR7500AP",
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -070037 ("Netgear", "R7800"): "NetgearR7800AP",
Omar El Ayach32b3afa2017-10-02 15:23:53 -070038 ("Netgear", "R8000"): "NetgearR8000AP"
39 }
40 objs = []
41 for config in configs:
42 try:
43 ap_class_name = SUPPORTED_APS[(config["brand"], config["model"])]
44 ap_class = globals()[ap_class_name]
45 except KeyError:
46 raise KeyError("Invalid retail AP brand and model combination.")
47 objs.append(ap_class(config))
48 return objs
49
50
51def detroy(objs):
52 return
53
54
Omar El Ayach7a6e2412018-05-17 20:00:54 -070055def start_chrome_browser(headless, max_allowed_sessions, timeout):
56 """Method to start chrome browser for retail AP configuration
57
58 This function starts a chrome browser session to interface with the APs
59 web interface. The function attempts to maintain only one chromedriver
60 session by waiting until no chromedriver sessions are running on a machine.
61
62 Args:
63 headless: boolean controlling headless operation
64 max_allowed_sessions: maximum number of concurrent chrome sessions
65 timeout: maximum waiting time to launch chrome session
66 Returns:
67 browser: chrome browser session
68 Raises:
69 TimeoutError: raised when a browser session could not be started
70 withing the specified timeout
71 """
72 chrome_options = splinter.driver.webdriver.chrome.Options()
73 chrome_options.add_argument("--no-proxy-server")
74 chrome_options.add_argument("--no-sandbox")
75 chrome_options.add_argument("--allow-running-insecure-content")
76 chrome_options.add_argument("--ignore-certificate-errors")
77 chrome_capabilities = DesiredCapabilities.CHROME.copy()
78 chrome_capabilities["acceptSslCerts"] = True
79 chrome_capabilities["acceptInsecureCerts"] = True
80 if headless:
81 chrome_options.add_argument("--headless")
82 chrome_options.add_argument("--disable-gpu")
83
84 start_time = time.time()
85 end_time = start_time + timeout
86 while time.time() < end_time:
87 browsers_running = int(job.run('pgrep chromedriver | wc -l').stdout)
88 if browsers_running >= max_allowed_sessions:
89 time.sleep(BROWSER_WAIT_SHORT)
90 else:
91 try:
92 browser = splinter.Browser(
93 "chrome",
94 options=chrome_options,
95 desired_capabilities=chrome_capabilities)
96 return browser
97 except:
98 time.sleep(BROWSER_WAIT_SHORT)
99 raise TimeoutError("Could not start chrome browser in time.")
100
101
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700102def visit_config_page(browser, url, page_load_timeout, num_tries):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700103 """Method to visit Netgear AP webpages.
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700104
105 This function visits a web page and checks the the resulting URL matches
106 the intended URL, i.e. no redirects have happened
107
108 Args:
109 browser: the splinter browser object that will visit the URL
110 url: the intended url
111 num_tries: number of tries before url is declared unreachable
112 """
113 browser.driver.set_page_load_timeout(page_load_timeout)
114 for idx in range(num_tries):
115 try:
116 browser.visit(url)
117 except:
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700118 browser.visit("about:blank")
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700119 if browser.url.split("/")[-1] == url.split("/")[-1]:
120 break
121 if idx == num_tries - 1:
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700122 raise RuntimeError("URL was unreachable.")
123
124
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700125class WifiRetailAP(object):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700126 """Base class implementation for retail ap.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700127
128 Base class provides functions whose implementation is shared by all aps.
129 If some functions such as set_power not supported by ap, checks will raise
130 exceptions.
131 """
132
133 def __init__(self, ap_settings):
134 raise NotImplementedError
135
136 def read_ap_settings(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700137 """Function that reads current ap settings.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700138
139 Function implementation is AP dependent and thus base class raises exception
140 if function not implemented in child class.
141 """
142 raise NotImplementedError
143
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700144 def validate_ap_settings(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700145 """Function to validate ap settings.
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700146
147 This function compares the actual ap settings read from the web GUI
148 with the assumed settings saved in the AP object. When called after AP
149 configuration, this method helps ensure that our configuration was
150 successful.
151
152 Raises:
153 ValueError: If read AP settings do not match stored settings.
154 """
155 assumed_ap_settings = self.ap_settings.copy()
156 actual_ap_settings = self.read_ap_settings()
157 if assumed_ap_settings != actual_ap_settings:
158 raise ValueError(
159 "Discrepancy in AP settings. Potential configuration error.")
160
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700161 def configure_ap(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700162 """Function that configures ap based on values of ap_settings.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700163
164 Function implementation is AP dependent and thus base class raises exception
165 if function not implemented in child class.
166 """
167 raise NotImplementedError
168
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000169 def set_radio_on_off(self, network, status):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700170 """Function that turns the radio on or off.
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000171
172 Args:
173 network: string containing network identifier (2G, 5G_1, 5G_2)
174 status: boolean indicating on or off (0: off, 1: on)
175 """
176 setting_to_update = {"status_{}".format(network): int(status)}
177 self.update_ap_settings(setting_to_update)
178
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700179 def set_ssid(self, network, ssid):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700180 """Function that sets network SSID.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700181
182 Args:
183 network: string containing network identifier (2G, 5G_1, 5G_2)
184 ssid: string containing ssid
185 """
186 setting_to_update = {"ssid_{}".format(network): str(ssid)}
187 self.update_ap_settings(setting_to_update)
188
189 def set_channel(self, network, channel):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700190 """Function that sets network channel.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700191
192 Args:
193 network: string containing network identifier (2G, 5G_1, 5G_2)
194 channel: string or int containing channel
195 """
196 setting_to_update = {"channel_{}".format(network): str(channel)}
197 self.update_ap_settings(setting_to_update)
198
199 def set_bandwidth(self, network, bandwidth):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700200 """Function that sets network bandwidth/mode.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700201
202 Args:
203 network: string containing network identifier (2G, 5G_1, 5G_2)
204 bandwidth: string containing mode, e.g. 11g, VHT20, VHT40, VHT80.
205 """
206 setting_to_update = {"bandwidth_{}".format(network): str(bandwidth)}
207 self.update_ap_settings(setting_to_update)
208
209 def set_power(self, network, power):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700210 """Function that sets network transmit power.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700211
212 Args:
213 network: string containing network identifier (2G, 5G_1, 5G_2)
214 power: string containing power level, e.g., 25%, 100%
215 """
216 setting_to_update = {"power_{}".format(network): str(power)}
217 self.update_ap_settings(setting_to_update)
218
219 def set_security(self, network, security_type, *password):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700220 """Function that sets network security setting and password.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700221
222 Args:
223 network: string containing network identifier (2G, 5G_1, 5G_2)
224 security: string containing security setting, e.g., WPA2-PSK
225 password: optional argument containing password
226 """
227 if (len(password) == 1) and (type(password[0]) == str):
228 setting_to_update = {
229 "security_type_{}".format(network): str(security_type),
230 "password_{}".format(network): str(password[0])
231 }
232 else:
233 setting_to_update = {
234 "security_type_{}".format(network): str(security_type)
235 }
236 self.update_ap_settings(setting_to_update)
237
238 def update_ap_settings(self, *dict_settings, **named_settings):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700239 """Function to update settings of existing AP.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700240
241 Function copies arguments into ap_settings and calls configure_retail_ap
242 to apply them.
243
244 Args:
245 *dict_settings accepts single dictionary of settings to update
246 **named_settings accepts named settings to update
247 Note: dict and named_settings cannot contain the same settings.
248 """
249 settings_to_update = {}
250 if (len(dict_settings) == 1) and (type(dict_settings[0]) == dict):
251 for key, value in dict_settings[0].items():
252 if key in named_settings:
253 raise KeyError("{} was passed twice.".format(key))
254 else:
255 settings_to_update[key] = value
256 elif len(dict_settings) > 1:
257 raise TypeError("Wrong number of positional arguments given")
258 return
259
260 for key, value in named_settings.items():
261 settings_to_update[key] = value
262
Omar El Ayach7331ba82018-01-03 22:52:34 +0000263 updates_requested = False
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700264 for key, value in settings_to_update.items():
265 if (key in self.ap_settings):
Omar El Ayach7331ba82018-01-03 22:52:34 +0000266 if self.ap_settings[key] != value:
267 self.ap_settings[key] = value
268 updates_requested = True
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700269 else:
270 raise KeyError("Invalid setting passed to AP configuration.")
271
Omar El Ayach7331ba82018-01-03 22:52:34 +0000272 if updates_requested:
273 self.configure_ap()
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700274
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000275 def band_lookup_by_channel(self, channel):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700276 """Function that gives band name by channel number.
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000277
278 Args:
279 channel: channel number to lookup
280 Returns:
281 band: name of band which this channel belongs to on this ap
282 """
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700283 for key, value in self.channel_band_map.items():
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000284 if channel in value:
285 return key
286 raise ValueError("Invalid channel passed in argument.")
287
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700288
289class NetgearR7000AP(WifiRetailAP):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700290 """Class that implements Netgear R7500 AP."""
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700291
292 def __init__(self, ap_settings):
293 self.ap_settings = ap_settings.copy()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700294 self.init_gui_data()
295 # Read and update AP settings
296 self.read_ap_settings()
297 if ap_settings.items() <= self.ap_settings.items():
298 return
299 else:
300 self.update_ap_settings(ap_settings)
301
302 def init_gui_data(self):
303 """Function to initialize data used while interacting with web GUI"""
304 self.config_page = "{}://{}:{}@{}:{}/WLG_wireless_dual_band_r10.htm".format(
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700305 self.ap_settings["protocol"], self.ap_settings["admin_username"],
306 self.ap_settings["admin_password"], self.ap_settings["ip_address"],
307 self.ap_settings["port"])
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700308 self.config_page_nologin = "{}://{}:{}/WLG_wireless_dual_band_r10.htm".format(
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700309 self.ap_settings["protocol"], self.ap_settings["ip_address"],
310 self.ap_settings["port"])
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700311 self.config_page_advanced = "{}://{}:{}/WLG_adv_dual_band2.htm".format(
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700312 self.ap_settings["protocol"], self.ap_settings["ip_address"],
313 self.ap_settings["port"])
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700314 self.networks = ["2G", "5G_1"]
315 self.channel_band_map = {
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000316 "2G": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000317 "5G_1": [
318 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120,
319 124, 128, 132, 136, 140, 149, 153, 157, 161, 165
320 ]
321 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700322 self.region_map = {
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000323 "1": "Africa",
324 "2": "Asia",
325 "3": "Australia",
326 "4": "Canada",
327 "5": "Europe",
328 "6": "Israel",
329 "7": "Japan",
330 "8": "Korea",
331 "9": "Mexico",
332 "10": "South America",
333 "11": "United States",
334 "12": "Middle East(Algeria/Syria/Yemen)",
335 "14": "Russia",
336 "16": "China",
337 "17": "India",
338 "18": "Malaysia",
339 "19": "Middle East(Iran/Labanon/Qatar)",
340 "20": "Middle East(Turkey/Egypt/Tunisia/Kuwait)",
341 "21": "Middle East(Saudi Arabia)",
342 "22": "Middle East(United Arab Emirates)",
343 "23": "Singapore",
344 "24": "Taiwan"
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000345 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700346 self.config_page_fields = {
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000347 "region": "WRegion",
348 ("2G", "status"): "enable_ap",
349 ("5G_1", "status"): "enable_ap_an",
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700350 ("2G", "ssid"): "ssid",
351 ("5G_1", "ssid"): "ssid_an",
352 ("2G", "channel"): "w_channel",
353 ("5G_1", "channel"): "w_channel_an",
354 ("2G", "bandwidth"): "opmode",
355 ("5G_1", "bandwidth"): "opmode_an",
356 ("2G", "power"): "enable_tpc",
357 ("5G_1", "power"): "enable_tpc_an",
358 ("2G", "security_type"): "security_type",
359 ("5G_1", "security_type"): "security_type_an",
360 ("2G", "password"): "passphrase",
361 ("5G_1", "password"): "passphrase_an"
362 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700363 self.bw_mode_values = {
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700364 "g and b": "11g",
365 "145Mbps": "VHT20",
366 "300Mbps": "VHT40",
367 "HT80": "VHT80"
368 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700369 self.power_mode_values = {
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700370 "1": "100%",
371 "2": "75%",
372 "3": "50%",
373 "4": "25%"
374 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700375 self.bw_mode_text = {
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700376 "11g": "Up to 54 Mbps",
377 "VHT20": "Up to 289 Mbps",
378 "VHT40": "Up to 600 Mbps",
379 "VHT80": "Up to 1300 Mbps"
380 }
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700381
382 def read_ap_settings(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700383 """Function to read ap settings."""
384 with start_chrome_browser(self.ap_settings["headless_browser"], 1,
385 600) as browser:
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700386 # Visit URL
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700387 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
388 visit_config_page(browser, self.config_page_nologin,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700389 BROWSER_WAIT_MED, 10)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700390
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700391 for key, value in self.config_page_fields.items():
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000392 if "status" in key:
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700393 visit_config_page(browser, self.config_page_advanced,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700394 BROWSER_WAIT_MED, 10)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000395 config_item = browser.find_by_name(value)
396 self.ap_settings["{}_{}".format(key[1], key[0])] = int(
397 config_item.first.checked)
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700398 visit_config_page(browser, self.config_page_nologin,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700399 BROWSER_WAIT_MED, 10)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700400 else:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000401 config_item = browser.find_by_name(value)
402 if "bandwidth" in key:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000403 self.ap_settings["{}_{}".format(key[1], key[
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700404 0])] = self.bw_mode_values[config_item.first.value]
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700405 elif "power" in key:
406 self.ap_settings["{}_{}".format(
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700407 key[1], key[0])] = self.power_mode_values[
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700408 config_item.first.value]
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000409 elif "region" in key:
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700410 self.ap_settings["region"] = self.region_map[
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000411 config_item.first.value]
412 elif "security_type" in key:
413 for item in config_item:
414 if item.checked:
415 self.ap_settings["{}_{}".format(
416 key[1], key[0])] = item.value
417 else:
418 config_item = browser.find_by_name(value)
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700419 self.ap_settings["{}_{}".format(
420 key[1], key[0])] = config_item.first.value
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700421 return self.ap_settings.copy()
422
423 def configure_ap(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700424 """Function to configure ap wireless settings."""
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000425 # Turn radios on or off
426 self.configure_radio_on_off()
427 # Configure radios
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700428 with start_chrome_browser(self.ap_settings["headless_browser"], 1,
429 600) as browser:
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700430 # Visit URL
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700431 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
432 visit_config_page(browser, self.config_page_nologin,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700433 BROWSER_WAIT_MED, 10)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700434
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000435 # Update region, and power/bandwidth for each network
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700436 for key, value in self.config_page_fields.items():
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700437 if "power" in key:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000438 config_item = browser.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700439 config_item.select_by_text(self.ap_settings["{}_{}".format(
440 key[1], key[0])])
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000441 elif "region" in key:
442 config_item = browser.find_by_name(value).first
443 config_item.select_by_text(self.ap_settings["region"])
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700444 elif "bandwidth" in key:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000445 config_item = browser.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700446 config_item.select_by_text(
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700447 self.bw_mode_text[self.ap_settings["{}_{}".format(
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700448 key[1], key[0])]])
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700449
450 # Update security settings (passwords updated only if applicable)
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700451 for key, value in self.config_page_fields.items():
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700452 if "security_type" in key:
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700453 browser.choose(value, self.ap_settings["{}_{}".format(
454 key[1], key[0])])
455 if self.ap_settings["{}_{}".format(key[1],
456 key[0])] == "WPA2-PSK":
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700457 config_item = browser.find_by_name(
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700458 self.config_page_fields[(key[0],
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700459 "password")]).first
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700460 config_item.fill(self.ap_settings["{}_{}".format(
461 "password", key[0])])
462
463 # Update SSID and channel for each network
464 # NOTE: Update ordering done as such as workaround for R8000
465 # wherein channel and SSID get overwritten when some other
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000466 # variables are changed. However, region does have to be set before
467 # channel in all cases.
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700468 for key, value in self.config_page_fields.items():
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700469 if "ssid" in key:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000470 config_item = browser.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700471 config_item.fill(self.ap_settings["{}_{}".format(
472 key[1], key[0])])
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700473 elif "channel" in key:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000474 config_item = browser.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700475 config_item.select(self.ap_settings["{}_{}".format(
476 key[1], key[0])])
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700477 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700478 try:
479 alert = browser.get_alert()
480 alert.accept()
481 except:
482 pass
483
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700484 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700485 browser.find_by_name("Apply").first.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700486 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700487 try:
488 alert = browser.get_alert()
489 alert.accept()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700490 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700491 except:
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700492 time.sleep(BROWSER_WAIT_SHORT)
493 visit_config_page(browser, self.config_page,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700494 BROWSER_WAIT_EXTRA_LONG, 10)
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700495 self.validate_ap_settings()
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700496
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000497 def configure_radio_on_off(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700498 """Helper configuration function to turn radios on/off."""
499 with start_chrome_browser(self.ap_settings["headless_browser"], 1,
500 600) as browser:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000501 # Visit URL
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700502 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
503 visit_config_page(browser, self.config_page_advanced,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700504 BROWSER_WAIT_MED, 10)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000505
506 # Turn radios on or off
507 status_toggled = False
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700508 for key, value in self.config_page_fields.items():
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000509 if "status" in key:
510 config_item = browser.find_by_name(value).first
511 current_status = int(config_item.checked)
512 if current_status != self.ap_settings["{}_{}".format(
513 key[1], key[0])]:
514 status_toggled = True
515 if self.ap_settings["{}_{}".format(key[1], key[0])]:
516 config_item.check()
517 else:
518 config_item.uncheck()
519
520 if status_toggled:
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700521 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000522 browser.find_by_name("Apply").first.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700523 time.sleep(BROWSER_WAIT_EXTRA_LONG)
524 visit_config_page(browser, self.config_page,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700525 BROWSER_WAIT_EXTRA_LONG, 10)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000526
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700527
528class NetgearR7500AP(WifiRetailAP):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700529 """Class that implements Netgear R7500 AP."""
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700530
531 def __init__(self, ap_settings):
532 self.ap_settings = ap_settings.copy()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700533 self.init_gui_data()
534 # Read and update AP settings
535 self.read_ap_settings()
536 if ap_settings.items() <= self.ap_settings.items():
537 return
538 else:
539 self.update_ap_settings(ap_settings)
540
541 def init_gui_data(self):
542 """Function to initialize data used while interacting with web GUI"""
543 self.config_page = "{}://{}:{}@{}:{}/index.htm".format(
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700544 self.ap_settings["protocol"], self.ap_settings["admin_username"],
545 self.ap_settings["admin_password"], self.ap_settings["ip_address"],
546 self.ap_settings["port"])
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700547 self.config_page_nologin = "{}://{}:{}/index.htm".format(
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700548 self.ap_settings["protocol"], self.ap_settings["ip_address"],
549 self.ap_settings["port"])
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700550 self.config_page_advanced = "{}://{}:{}/adv_index.htm".format(
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700551 self.ap_settings["protocol"], self.ap_settings["ip_address"],
552 self.ap_settings["port"])
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700553 self.networks = ["2G", "5G_1"]
554 self.channel_band_map = {
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000555 "2G": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000556 "5G_1": [
557 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120,
558 124, 128, 132, 136, 140, 149, 153, 157, 161, 165
559 ]
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000560 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700561 self.config_page_fields = {
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000562 "region": "WRegion",
563 ("2G", "status"): "enable_ap",
564 ("5G_1", "status"): "enable_ap_an",
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700565 ("2G", "ssid"): "ssid",
566 ("5G_1", "ssid"): "ssid_an",
567 ("2G", "channel"): "w_channel",
568 ("5G_1", "channel"): "w_channel_an",
569 ("2G", "bandwidth"): "opmode",
570 ("5G_1", "bandwidth"): "opmode_an",
571 ("2G", "security_type"): "security_type",
572 ("5G_1", "security_type"): "security_type_an",
573 ("2G", "password"): "passphrase",
574 ("5G_1", "password"): "passphrase_an"
575 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700576 self.region_map = {
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000577 "0": "Africa",
578 "1": "Asia",
579 "2": "Australia",
580 "3": "Canada",
581 "4": "Europe",
582 "5": "Israel",
583 "6": "Japan",
584 "7": "Korea",
585 "8": "Mexico",
586 "9": "South America",
587 "10": "United States",
588 "11": "China",
589 "12": "India",
590 "13": "Malaysia",
591 "14": "Middle East(Algeria/Syria/Yemen)",
592 "15": "Middle East(Iran/Labanon/Qatar)",
593 "16": "Middle East(Turkey/Egypt/Tunisia/Kuwait)",
594 "17": "Middle East(Saudi Arabia)",
595 "18": "Middle East(United Arab Emirates)",
596 "19": "Russia",
597 "20": "Singapore",
598 "21": "Taiwan"
599 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700600 self.bw_mode_text_2g = {
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700601 "11g": "Up to 54 Mbps",
602 "VHT20": "Up to 289 Mbps",
603 "VHT40": "Up to 600 Mbps"
604 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700605 self.bw_mode_text_5g = {
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700606 "VHT20": "Up to 347 Mbps",
607 "VHT40": "Up to 800 Mbps",
608 "VHT80": "Up to 1733 Mbps"
609 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700610 self.bw_mode_values = {
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700611 "1": "11g",
612 "2": "VHT20",
613 "3": "VHT40",
614 "7": "VHT20",
615 "8": "VHT40",
616 "9": "VHT80"
617 }
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700618
619 def read_ap_settings(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700620 """Function to read ap wireless settings."""
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000621 # Get radio status (on/off)
622 self.read_radio_on_off()
623 # Get radio configuration. Note that if both radios are off, the below
624 # code will result in an error
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700625 with start_chrome_browser(self.ap_settings["headless_browser"], 1,
626 600) as browser:
627 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
628 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
629 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700630 wireless_button = browser.find_by_id("wireless").first
631 wireless_button.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700632 time.sleep(BROWSER_WAIT_MED)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700633
634 with browser.get_iframe("formframe") as iframe:
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700635 for key, value in self.config_page_fields.items():
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700636 if "bandwidth" in key:
637 config_item = iframe.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700638 self.ap_settings["{}_{}".format(
639 key[1],
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700640 key[0])] = self.bw_mode_values[config_item.value]
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000641 elif "region" in key:
642 config_item = iframe.find_by_name(value).first
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700643 self.ap_settings["region"] = self.region_map[
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000644 config_item.value]
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700645 elif "password" in key:
646 try:
647 config_item = iframe.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700648 self.ap_settings["{}_{}".format(
649 key[1], key[0])] = config_item.value
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700650 self.ap_settings["{}_{}".format(
651 "security_type", key[0])] = "WPA2-PSK"
652 except:
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700653 self.ap_settings["{}_{}".format(
654 key[1], key[0])] = "defaultpassword"
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700655 self.ap_settings["{}_{}".format(
656 "security_type", key[0])] = "Disable"
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000657 elif ("channel" in key) or ("ssid" in key):
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700658 config_item = iframe.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700659 self.ap_settings["{}_{}".format(
660 key[1], key[0])] = config_item.value
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700661 else:
662 pass
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000663 return self.ap_settings.copy()
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700664
665 def configure_ap(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700666 """Function to configure ap wireless settings."""
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000667 # Turn radios on or off
668 self.configure_radio_on_off()
669 # Configure radios
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700670 with start_chrome_browser(self.ap_settings["headless_browser"], 1,
671 600) as browser:
672 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
673 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
674 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700675 wireless_button = browser.find_by_id("wireless").first
676 wireless_button.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700677 time.sleep(BROWSER_WAIT_MED)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700678
679 with browser.get_iframe("formframe") as iframe:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000680 # Update AP region. Must be done before channel setting
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700681 for key, value in self.config_page_fields.items():
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000682 if "region" in key:
683 config_item = iframe.find_by_name(value).first
684 config_item.select_by_text(self.ap_settings["region"])
685 # Update wireless settings for each network
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700686 for key, value in self.config_page_fields.items():
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700687 if "ssid" in key:
688 config_item = iframe.find_by_name(value).first
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700689 config_item.fill(self.ap_settings["{}_{}".format(
690 key[1], key[0])])
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700691 elif "channel" in key:
692 channel_string = "0" * (int(
693 self.ap_settings["{}_{}".format(key[1], key[0])]
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000694 ) < 10) + str(self.ap_settings["{}_{}".format(
695 key[1], key[0])]) + "(DFS)" * (
696 48 < int(self.ap_settings["{}_{}".format(
697 key[1], key[0])]) < 149)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700698 config_item = iframe.find_by_name(value).first
699 config_item.select_by_text(channel_string)
700 elif key == ("2G", "bandwidth"):
701 config_item = iframe.find_by_name(value).first
702 config_item.select_by_text(
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700703 str(self.bw_mode_text_2g[self.ap_settings[
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700704 "{}_{}".format(key[1], key[0])]]))
705 elif key == ("5G_1", "bandwidth"):
706 config_item = iframe.find_by_name(value).first
707 config_item.select_by_text(
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700708 str(self.bw_mode_text_5g[self.ap_settings[
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700709 "{}_{}".format(key[1], key[0])]]))
710
711 # Update passwords for WPA2-PSK protected networks
712 # (Must be done after security type is selected)
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700713 for key, value in self.config_page_fields.items():
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700714 if "security_type" in key:
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700715 iframe.choose(value, self.ap_settings["{}_{}".format(
716 key[1], key[0])])
717 if self.ap_settings["{}_{}".format(
718 key[1], key[0])] == "WPA2-PSK":
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700719 config_item = iframe.find_by_name(
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700720 self.config_page_fields[(key[0],
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700721 "password")]).first
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700722 config_item.fill(self.ap_settings["{}_{}".format(
723 "password", key[0])])
724
725 apply_button = iframe.find_by_name("Apply")
726 apply_button[0].click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700727 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700728 try:
729 alert = browser.get_alert()
730 alert.accept()
731 except:
732 pass
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700733 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700734 try:
735 alert = browser.get_alert()
736 alert.accept()
737 except:
738 pass
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700739 time.sleep(BROWSER_WAIT_SHORT)
740 time.sleep(BROWSER_WAIT_EXTRA_LONG)
741 visit_config_page(browser, self.config_page,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700742 BROWSER_WAIT_EXTRA_LONG, 10)
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700743 self.validate_ap_settings()
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000744
745 def configure_radio_on_off(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700746 """Helper configuration function to turn radios on/off."""
747 with start_chrome_browser(self.ap_settings["headless_browser"], 1,
748 600) as browser:
749 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
750 visit_config_page(browser, self.config_page_advanced,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700751 BROWSER_WAIT_MED, 10)
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700752 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000753 wireless_button = browser.find_by_id("advanced_bt").first
754 wireless_button.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700755 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000756 wireless_button = browser.find_by_id("wladv").first
757 wireless_button.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700758 time.sleep(BROWSER_WAIT_MED)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000759
760 with browser.get_iframe("formframe") as iframe:
761 # Turn radios on or off
762 status_toggled = False
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700763 for key, value in self.config_page_fields.items():
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000764 if "status" in key:
765 config_item = iframe.find_by_name(value).first
766 current_status = int(config_item.checked)
767 if current_status != self.ap_settings["{}_{}".format(
768 key[1], key[0])]:
769 status_toggled = True
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700770 if self.ap_settings["{}_{}".format(key[1],
771 key[0])]:
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000772 config_item.check()
773 else:
774 config_item.uncheck()
775
776 if status_toggled:
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700777 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000778 browser.find_by_name("Apply").first.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700779 time.sleep(BROWSER_WAIT_EXTRA_LONG)
780 visit_config_page(browser, self.config_page,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700781 BROWSER_WAIT_EXTRA_LONG, 10)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000782
783 def read_radio_on_off(self):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700784 """Helper configuration function to read radio status."""
785 with start_chrome_browser(self.ap_settings["headless_browser"], 1,
786 600) as browser:
787 visit_config_page(browser, self.config_page, BROWSER_WAIT_MED, 10)
788 visit_config_page(browser, self.config_page_advanced,
android-build-prod (mdb)70753e82018-05-02 17:54:37 -0700789 BROWSER_WAIT_MED, 10)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000790 wireless_button = browser.find_by_id("advanced_bt").first
791 wireless_button.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700792 time.sleep(BROWSER_WAIT_SHORT)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000793 wireless_button = browser.find_by_id("wladv").first
794 wireless_button.click()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700795 time.sleep(BROWSER_WAIT_MED)
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000796
797 with browser.get_iframe("formframe") as iframe:
798 # Turn radios on or off
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700799 for key, value in self.config_page_fields.items():
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000800 if "status" in key:
801 config_item = iframe.find_by_name(value).first
802 self.ap_settings["{}_{}".format(key[1], key[0])] = int(
803 config_item.checked)
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700804
805
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700806class NetgearR7800AP(NetgearR7500AP):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700807 """Class that implements Netgear R7800 AP.
808
809 Since most of the class' implementation is shared with the R7500, this
810 class inherits from NetgearR7500AP and simply redifines config parameters
811 """
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700812
813 def __init__(self, ap_settings):
814 self.ap_settings = ap_settings.copy()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700815 self.init_gui_data()
816 # Overwrite minor differences from R7500 AP
817 self.bw_mode_text_2g["VHT20"] = "Up to 347 Mbps"
818 # Read and update AP settings
Omar El Ayachd4bc7ac2018-05-09 19:47:26 -0700819 self.read_ap_settings()
820 if ap_settings.items() <= self.ap_settings.items():
821 return
822 else:
823 self.update_ap_settings(ap_settings)
824
825
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700826class NetgearR8000AP(NetgearR7000AP):
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700827 """Class that implements Netgear R8000 AP.
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700828
829 Since most of the class' implementation is shared with the R7000, this
830 class inherits from NetgearR7000AP and simply redifines config parameters
831 """
832
833 def __init__(self, ap_settings):
834 self.ap_settings = ap_settings.copy()
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700835 self.init_gui_data()
836 # Overwrite minor differences from R7000 AP
837 self.config_page = "{}://{}:{}@{}:{}/WLG_wireless_dual_band_r8000.htm".format(
838 self.ap_settings["protocol"], self.ap_settings["admin_username"],
839 self.ap_settings["admin_password"], self.ap_settings["ip_address"],
840 self.ap_settings["port"])
841 self.config_page_nologin = "{}://{}:{}/WLG_wireless_dual_band_r8000.htm".format(
842 self.ap_settings["protocol"], self.ap_settings["ip_address"],
843 self.ap_settings["port"])
844 self.config_page_advanced = "{}://{}:{}/WLG_adv_dual_band2_r8000.htm".format(
845 self.ap_settings["protocol"], self.ap_settings["ip_address"],
846 self.ap_settings["port"])
847 self.networks = ["2G", "5G_1", "5G_2"]
848 self.channel_band_map = {
Omar El Ayach9be1c3c2017-12-27 19:20:56 +0000849 "2G": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
850 "5G_1": [36, 40, 44, 48],
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000851 "5G_2": [149, 153, 157, 161, 165]
852 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700853 self.config_page_fields = {
Omar El Ayachd0c4b942018-01-30 06:02:14 +0000854 "region": "WRegion",
855 ("2G", "status"): "enable_ap",
856 ("5G_1", "status"): "enable_ap_an",
857 ("5G_2", "status"): "enable_ap_an_2",
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700858 ("2G", "ssid"): "ssid",
859 ("5G_1", "ssid"): "ssid_an",
860 ("5G_2", "ssid"): "ssid_an_2",
861 ("2G", "channel"): "w_channel",
862 ("5G_1", "channel"): "w_channel_an",
863 ("5G_2", "channel"): "w_channel_an_2",
864 ("2G", "bandwidth"): "opmode",
865 ("5G_1", "bandwidth"): "opmode_an",
866 ("5G_2", "bandwidth"): "opmode_an_2",
867 ("2G", "security_type"): "security_type",
868 ("5G_1", "security_type"): "security_type_an",
869 ("5G_2", "security_type"): "security_type_an_2",
870 ("2G", "password"): "passphrase",
871 ("5G_1", "password"): "passphrase_an",
872 ("5G_2", "password"): "passphrase_an_2"
873 }
Omar El Ayach7a6e2412018-05-17 20:00:54 -0700874 # Read and update AP settings
Omar El Ayach32b3afa2017-10-02 15:23:53 -0700875 self.read_ap_settings()
876 if ap_settings.items() <= self.ap_settings.items():
877 return
878 else:
879 self.update_ap_settings(ap_settings)