Merge "Set scipy<1.11 for Python versions below 3.9"
diff --git a/acts/framework/acts/controllers/openwrt_ap.py b/acts/framework/acts/controllers/openwrt_ap.py
index 1d3ad93..797172f 100644
--- a/acts/framework/acts/controllers/openwrt_ap.py
+++ b/acts/framework/acts/controllers/openwrt_ap.py
@@ -3,11 +3,13 @@
import random
import re
import time
+import logging
from acts import logger
from acts import signals
from acts.controllers.ap_lib import hostapd_constants
from acts.controllers.openwrt_lib import network_settings
+from acts.controllers.openwrt_lib import openwrt_authentication
from acts.controllers.openwrt_lib import wireless_config
from acts.controllers.openwrt_lib import wireless_settings_applier
from acts.controllers.openwrt_lib.openwrt_constants import OpenWrtModelMap as modelmap
@@ -110,14 +112,26 @@
def __init__(self, config):
"""Initialize AP."""
- self.ssh_settings = settings.from_config(config["ssh_config"])
- self.ssh = connection.SshConnection(self.ssh_settings)
+ try:
+ self.ssh_settings = settings.from_config(config["ssh_config"])
+ self.ssh = connection.SshConnection(self.ssh_settings)
+ self.ssh.setup_master_ssh()
+ except connection.Error:
+ logging.info("OpenWrt AP instance is not initialized, use SSH Auth...")
+ openwrt_auth = openwrt_authentication.OpenWrtAuth(
+ self.ssh_settings.hostname)
+ openwrt_auth.generate_rsa_key()
+ openwrt_auth.send_public_key_to_remote_host()
+ self.ssh_settings.identity_file = openwrt_auth.private_key_file
+ self.ssh = connection.SshConnection(self.ssh_settings)
+ self.ssh.setup_master_ssh()
self.log = logger.create_logger(
- lambda msg: "[OpenWrtAP|%s] %s" % (self.ssh_settings.hostname, msg))
+ lambda msg: "[OpenWrtAP|%s] %s" % (self.ssh_settings.hostname, msg))
self.wireless_setting = None
self.network_setting = network_settings.NetworkSettings(
self.ssh, self.ssh_settings, self.log)
self.model = self.get_model_name()
+ self.log.info("OpenWrt AP: %s has been initiated." % self.model)
if self.model in modelmap.__dict__:
self.radios = modelmap.__dict__[self.model]
else:
@@ -637,8 +651,10 @@
def close(self):
"""Reset wireless and network settings to default and stop AP."""
- if self.network_setting.config:
+ try:
self.network_setting.cleanup_network_settings()
+ except AttributeError as e:
+ self.log.warning("OpenWrtAP object has no attribute 'network_setting'")
if self.wireless_setting:
self.wireless_setting.cleanup_wireless_settings()
@@ -649,4 +665,3 @@
def reboot(self):
"""Reboot Openwrt."""
self.ssh.run("reboot")
-
diff --git a/acts/framework/acts/controllers/openwrt_lib/openwrt_authentication.py b/acts/framework/acts/controllers/openwrt_lib/openwrt_authentication.py
new file mode 100644
index 0000000..bdc7b97
--- /dev/null
+++ b/acts/framework/acts/controllers/openwrt_lib/openwrt_authentication.py
@@ -0,0 +1,98 @@
+import logging
+import os
+import paramiko
+
+
+_REMOTE_PATH = '/etc/dropbear/authorized_keys'
+
+
+class OpenWrtAuth:
+ """
+ A class for managing SSH authentication for OpenWrt devices.
+ """
+ def __init__(self, hostname, username='root', password='root', port=22):
+ """
+ Initializes a new instance of the OpenWrtAuth class.
+
+ Args:
+ hostname (str): The hostname or IP address of the remote device.
+ username (str): The username for authentication.
+ password (str): The password for authentication.
+ port (int): The port number for SSH.
+
+ Attributes:
+ public_key (str): The generated public key.
+ public_key_file (str): The path to the generated public key file.
+ private_key_file (str): The path to the generated private key file.
+ """
+ self.hostname = hostname
+ self.username = username
+ self.password = password
+ self.port = port
+ self.public_key = None
+ self.public_key_file = None
+ self.private_key_file = None
+
+ def generate_rsa_key(self):
+ """
+ Generates an RSA key pair and saves it to the specified directory.
+
+ Raises:
+ ValueError: If an error occurs while generating the RSA key pair.
+ paramiko.SSHException: If an error occurs while generating the RSA key pair.
+ FileNotFoundError: If the directory for saving the private or public key does not exist.
+ PermissionError: If there is a permission error while creating the directory for saving the keys.
+ Exception: If an unexpected error occurs while generating the RSA key pair.
+ """
+ try:
+ # Generates an RSA key pair in /tmp/openwrt/ directory.
+ logging.info("Generating RSA key pair...")
+ key = paramiko.RSAKey.generate(bits=2048)
+ self.public_key = f"ssh-rsa {key.get_base64()}"
+ logging.info(f"Public key: {self.public_key}")
+
+ # Create /tmp/openwrt/ directory if it doesn't exist.
+ logging.info("Creating /tmp/openwrt/ directory...")
+ os.makedirs('/tmp/openwrt/', exist_ok=True)
+
+ # Saves the private key to a file.
+ self.private_key_file = '/tmp/openwrt/id_rsa'
+ key.write_private_key_file(self.private_key_file)
+
+ # Saves the public key to a file.
+ self.public_key_file = '/tmp/openwrt/id_rsa.pub'
+ with open(self.public_key_file, "w") as f:
+ f.write(self.public_key)
+ logging.info(f"Saved public key to file: {self.public_key_file}")
+ except (ValueError, paramiko.SSHException, PermissionError) as e:
+ logging.error(f"An error occurred while generating the RSA key pair: {e}")
+ except Exception as e:
+ logging.error(f"An unexpected error occurred while generating the RSA key pair: {e}")
+
+ def send_public_key_to_remote_host(self):
+ """
+ Uploads the public key to the remote host.
+
+ Raises:
+ paramiko.AuthenticationException: If authentication to the remote host fails.
+ paramiko.SSHException: If an SSH-related error occurs during the connection.
+ FileNotFoundError: If the public key file or the private key file does not exist.
+ Exception: If an unexpected error occurs while sending the public key.
+ """
+ try:
+ # Connects to the remote host and uploads the public key.
+ logging.info(f"Uploading public key to remote host {self.hostname}...")
+ with paramiko.SSHClient() as ssh:
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ ssh.connect(hostname=self.hostname,
+ port=self.port,
+ username=self.username,
+ password=self.password,
+ key_filename='/tmp/openwrt/id_rsa')
+ with ssh.open_sftp() as sftp:
+ sftp.put(self.public_key_file, _REMOTE_PATH)
+ logging.info('Public key uploaded successfully.')
+ except (paramiko.AuthenticationException, paramiko.SSHException, FileNotFoundError) as e:
+ logging.error(f"An error occurred while sending the public key: {e}")
+ except Exception as e:
+ logging.error(f"An unexpected error occurred while sending the public key: {e}")
diff --git a/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py b/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py
index c0a408d..a29f89b 100644
--- a/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py
+++ b/acts/framework/acts/controllers/openwrt_lib/openwrt_constants.py
@@ -36,3 +36,4 @@
class OpenWrtModelMap:
NETGEAR_R8000 = ("radio2", "radio1")
+ TOTOLINK_X5000R = ("radio1", "radio0")