Merge "Fixed a couple Fuchsia Device excemptions and add get_info to attenuator"
diff --git a/acts/framework/acts/controllers/attenuator.py b/acts/framework/acts/controllers/attenuator.py
index aa84801..9d99c2d 100644
--- a/acts/framework/acts/controllers/attenuator.py
+++ b/acts/framework/acts/controllers/attenuator.py
@@ -48,17 +48,16 @@
logging.error('Attempt %s to open connection to attenuator '
'failed: %s' % (attempt_number, e))
if attempt_number == _ATTENUATOR_OPEN_RETRIES:
- ping_output = job.run(
- 'ping %s -c 1 -w 1' % ip_address, ignore_status=True)
+ ping_output = job.run('ping %s -c 1 -w 1' % ip_address,
+ ignore_status=True)
if ping_output.exit_status == 1:
- logging.error(
- 'Unable to ping attenuator at %s' % ip_address)
+ logging.error('Unable to ping attenuator at %s' %
+ ip_address)
else:
- logging.error(
- 'Able to ping attenuator at %s' % ip_address)
- job.run(
- 'echo "q" | telnet %s %s' % (ip_address, port),
- ignore_status=True)
+ logging.error('Able to ping attenuator at %s' %
+ ip_address)
+ job.run('echo "q" | telnet %s %s' % (ip_address, port),
+ ignore_status=True)
raise
for i in range(inst_cnt):
attn = Attenuator(attn_inst, idx=i)
@@ -72,13 +71,31 @@
return objs
+def get_info(attenuators):
+ """Get information on a list of Attenuator objects.
+
+ Args:
+ attenuators: A list of Attenuator objects.
+
+ Returns:
+ A list of dict, each representing info for Attenuator objects.
+ """
+ device_info = []
+ for attenuator in attenuators:
+ info = {
+ "Address": attenuator.instrument.address,
+ "Attenuator_Port": attenuator.idx
+ }
+ device_info.append(info)
+ return device_info
+
+
def destroy(objs):
for attn in objs:
attn.instrument.close()
-def get_attenuators_for_device(device_attenuator_configs,
- attenuators,
+def get_attenuators_for_device(device_attenuator_configs, attenuators,
attenuator_key):
"""Gets the list of attenuators associated to a specified device and builds
a list of the attenuator objects associated to the ip address in the
@@ -139,11 +156,12 @@
for attenuator_port in device_attenuator_config[attenuator_key]:
for attenuator in attenuators:
if (attenuator.instrument.address ==
- device_attenuator_config['Address'] and
- attenuator.idx is attenuator_port):
+ device_attenuator_config['Address']
+ and attenuator.idx is attenuator_port):
attenuator_list.append(attenuator)
return attenuator_list
+
"""Classes for accessing, managing, and manipulating attenuators.
Users will instantiate a specific child class, but almost all operation should
@@ -244,7 +262,6 @@
the physical implementation and allows the user to think only of attenuators
regardless of their location.
"""
-
def __init__(self, instrument, idx=0, offset=0):
"""This is the constructor for Attenuator
@@ -313,7 +330,6 @@
convenience to the user and avoid re-implementation of helper functions and
small loops scattered throughout user code.
"""
-
def __init__(self, name=''):
"""This constructor for AttenuatorGroup
diff --git a/acts/framework/acts/controllers/fuchsia_device.py b/acts/framework/acts/controllers/fuchsia_device.py
index fd4aecd..998927d 100644
--- a/acts/framework/acts/controllers/fuchsia_device.py
+++ b/acts/framework/acts/controllers/fuchsia_device.py
@@ -14,6 +14,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import backoff
import json
import logging
import platform
@@ -22,6 +23,7 @@
import re
import requests
import subprocess
+import socket
import time
from acts import context
@@ -146,7 +148,6 @@
log: A logger object.
port: The TCP port number of the Fuchsia device.
"""
-
def __init__(self, fd_conf_data):
"""
Args:
@@ -230,13 +231,13 @@
# Init server
self.init_server_connection()
- def init_server_connection(self, retry_count=3):
- """Initializes HTTP connection with SL4F server.
-
- Args:
- retry_count: How many time to retry connecting assuming a
- known error.
- """
+ @backoff.on_exception(
+ backoff.constant,
+ (ConnectionRefusedError, requests.exceptions.ConnectionError),
+ interval=1.5,
+ max_tries=4)
+ def init_server_connection(self):
+ """Initializes HTTP connection with SL4F server."""
self.log.debug("Initialziing server connection")
init_data = json.dumps({
"jsonrpc": "2.0",
@@ -246,28 +247,8 @@
"client_id": self.client_id
}
})
- retry_counter = 0
- while retry_counter < retry_count:
- try:
- requests.get(url=self.init_address, data=init_data)
- retry_counter = retry_count + 1
- except ConnectionRefusedError:
- self.log.info('Connection Refused Error. '
- 'Retrying in 1 second.')
- e = ConnectionRefusedError('Connection Refused Error.')
- retry_counter += 1
- time.sleep(1)
- except requests.exceptions.ConnectionError:
- self.log.info('Requests ConnectionError. '
- 'Retrying in 1 second.')
- e = requests.exceptions.ConnectionError('Requests '
- 'ConnectionError')
- retry_counter += 1
- time.sleep(1)
- except Exception as e:
- raise e
- if retry_counter is retry_count:
- raise e
+
+ requests.get(url=self.init_address, data=init_data)
self.test_counter += 1
def build_id(self, test_id):
@@ -315,7 +296,8 @@
elif os_type == 'Linux':
timeout_flag = '-W'
else:
- raise ValueError('Invalid OS. Only Linux and MacOS are supported.')
+ raise ValueError(
+ 'Invalid OS. Only Linux and MacOS are supported.')
ping_command = ['ping', '%s' % timeout_flag, '1', '-c', '1', self.ip]
self.clean_up()
self.log.info('Rebooting FuchsiaDevice %s' % self.ip)
@@ -331,7 +313,7 @@
self.log.info('Waiting for FuchsiaDevice %s to come back up.' %
self.ip)
self.log.debug('Waiting for FuchsiaDevice %s to stop responding'
- ' to pings.' % self.ip)
+ ' to pings.' % self.ip)
while True:
initial_ping_status_code = subprocess.call(
ping_command,
@@ -340,28 +322,26 @@
if initial_ping_status_code != 1:
break
else:
- initial_ping_elapsed_time = (
- time.time() - initial_ping_start_time)
+ initial_ping_elapsed_time = (time.time() -
+ initial_ping_start_time)
if initial_ping_elapsed_time > timeout:
try:
uptime = (int(
self.send_command_ssh(
'clock --monotonic',
- timeout=
- FUCHSIA_RECONNECT_AFTER_REBOOT_TIME).stdout)
- / FUCHSIA_TIME_IN_NANOSECONDS)
+ timeout=FUCHSIA_RECONNECT_AFTER_REBOOT_TIME).
+ stdout) / FUCHSIA_TIME_IN_NANOSECONDS)
except Exception as e:
- self.log.debug('Unable to retrieve uptime from device.')
+ self.log.info('Unable to retrieve uptime from device.')
# Device failed to restart within the specified period.
# Restart the services so other tests can continue.
self.start_services()
self.init_server_connection()
- raise TimeoutError('Waited %s seconds, and FuchsiaDevice %s'
- ' never stopped responding to pings.'
- ' Uptime reported as %s' %
- (initial_ping_elapsed_time,
- self.ip,
- str(uptime)))
+ raise TimeoutError(
+ 'Waited %s seconds, and FuchsiaDevice %s'
+ ' never stopped responding to pings.'
+ ' Uptime reported as %s' %
+ (initial_ping_elapsed_time, self.ip, str(uptime)))
start_time = time.time()
self.log.debug('Waiting for FuchsiaDevice %s to start responding '
@@ -377,8 +357,8 @@
raise TimeoutError('Waited %s seconds, and FuchsiaDevice %s'
'did not repond to a ping.' %
(elapsed_time, self.ip))
- self.log.debug('Received a ping back in %s seconds.'
- % str(time.time() - start_time))
+ self.log.debug('Received a ping back in %s seconds.' %
+ str(time.time() - start_time))
# Wait 5 seconds after receiving a ping packet to just to let
# the OS get everything up and running.
time.sleep(10)
@@ -656,15 +636,17 @@
disconnect_response.get("error"))
return False
- def start_services(self, skip_sl4f=False, retry_count=3):
+ @backoff.on_exception(backoff.constant,
+ (FuchsiaSyslogError, socket.timeout),
+ interval=1.5,
+ max_tries=4)
+ def start_services(self, skip_sl4f=False):
"""Starts long running services on the Fuchsia device.
1. Start SL4F if not skipped.
Args:
skip_sl4f: Does not attempt to start SL4F if True.
- retry_count: How many time to retry connecting assuming a
- known error.
"""
self.log.debug("Attempting to start Fuchsia device services on %s." %
self.ip)
@@ -672,24 +654,9 @@
self.log_process = start_syslog(self.serial, self.log_path,
self.ip, self.ssh_username,
self.ssh_config)
- retry_counter = 0
- while retry_counter < retry_count:
- if ENABLE_LOG_LISTENER:
- try:
- self.log_process.start()
- retry_counter = retry_count + 1
- except FuchsiaSyslogError:
- self.log.info('Fuchsia Syslog Error. '
- 'Retrying in 1 second.')
- e = FuchsiaSyslogError('Fuchsia Syslog Error')
- retry_counter += 1
- time.sleep(1)
- except Exception as e:
- raise e
- else:
- retry_counter = retry_count + 1
- if retry_counter is retry_count:
- raise e
+
+ if ENABLE_LOG_LISTENER:
+ self.log_process.start()
if not skip_sl4f:
self.control_daemon("sl4f.cmx", "start")
diff --git a/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py b/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py
index 6456a08..56fd4c2 100644
--- a/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py
+++ b/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py
@@ -14,9 +14,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import backoff
import os
import logging
import paramiko
+import socket
import time
logging.getLogger("paramiko").setLevel(logging.WARNING)
@@ -51,11 +53,17 @@
raise Exception('No valid ssh key type found', exceptions)
+@backoff.on_exception(
+ backoff.constant,
+ (paramiko.ssh_exception.SSHException,
+ paramiko.ssh_exception.AuthenticationException, socket.timeout,
+ socket.error, ConnectionRefusedError, ConnectionResetError),
+ interval=1.5,
+ max_tries=4)
def create_ssh_connection(ip_address,
ssh_username,
ssh_config,
- connect_timeout=30,
- retry_count=3):
+ connect_timeout=30):
"""Creates and ssh connection to a Fuchsia device
Args:
@@ -63,8 +71,6 @@
ssh_username: Username for ssh server.
ssh_config: ssh_config location for the ssh server.
connect_timeout: Timeout value for connecting to ssh_server.
- retry_count: How many time to retry connecting assuming a
- known error.
Returns:
A paramiko ssh object
@@ -72,31 +78,12 @@
ssh_key = get_private_key(ip_address=ip_address, ssh_config=ssh_config)
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
- retry_counter = 0
- while retry_counter < retry_count:
- try:
- ssh_client.connect(hostname=ip_address,
- username=ssh_username,
- allow_agent=False,
- pkey=ssh_key,
- timeout=connect_timeout,
- banner_timeout=200)
- retry_counter = retry_count + 1
- except paramiko.ssh_exception.SSHException:
- logging.info('Paramiko SSHException. Retrying in 1 second.')
- e = paramiko.ssh_exception.SSHException('Paramiko SSHException')
- time.sleep(1)
- retry_counter =+ 1
- except ConnectionRefusedError:
- logging.info('Connection Refused Error. Retrying in 1 second.')
- e = ConnectionRefusedError('Connection Refused Error')
- time.sleep(1)
- retry_counter =+ 1
- except Exception as e:
- raise e
- if retry_counter is retry_count:
- raise e
-
+ ssh_client.connect(hostname=ip_address,
+ username=ssh_username,
+ allow_agent=False,
+ pkey=ssh_key,
+ timeout=connect_timeout,
+ banner_timeout=200)
return ssh_client
diff --git a/acts/framework/setup.py b/acts/framework/setup.py
index 21b9dfe..59210f9 100755
--- a/acts/framework/setup.py
+++ b/acts/framework/setup.py
@@ -23,6 +23,7 @@
import sys
install_requires = [
+ 'backoff',
# Future needs to have a newer version that contains urllib.
'future>=0.16.0',
'mock',