Ejemplo n.º 1
0
    def _find_active_serial_ports_from(self, wait_duration, device_files):
        """
        Find and returns list of active USB serial ports.

        This spawns a process that actually does the work.

        Args:
            device_files (list of strings):
                List of device files that will be checked for serial ports.
                Note that any other device file than ttyUSBx will be ignored.

        Returns:
            List of device files that have active serial port.
            Example: ["ttyUSB2", "ttyUSB4", "ttyUSB7"]

        """
        serial_results = Queue()

        serial_finder = Process(
            target=TopologyBuilder._get_active_serial_device_files,
            args=(self, serial_results, wait_duration, device_files))
        if self._verbose:
            print("Serial thread - Finding active serial ports")

        logger.info("Finding active serial ports")
        serial_finder.start()

        return serial_results
Ejemplo n.º 2
0
    def _enter_test_mode(self):
        """
        Enter test mode by booting from sd card

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if the device failed to enter the test
            mode
        """
        # device by default boots from sd card, so if everything has gone well,
        # we can just power cycle to boot the testable image
        logger.info("Entering test mode")
        for _ in range(self._TEST_MODE_RETRY_ATTEMPTS):
            self._power_cycle()
            self.dev_ip = self._wait_for_responsive_ip()


            if self.dev_ip and self._verify_mode(self.parameters["test_mode"]):
                return
            else:
                logger.warning("Failed to enter test mode")

        raise errors.AFTDeviceError("Could not set the device in test mode")
Ejemplo n.º 3
0
    def _create_configuration(self):
        """
        Create and return ConfigParser object containing the device
        configurations

        Return:
            ConfigParser object containing the configurations
        """
        logger.info("Creating configuration object")
        config = SafeConfigParser()

        device_ids = {}

        for device in self._devices:
            # lack of model generally means that there was an unused power
            # cutter socket
            if not "model" in device:
                continue

            if not device["model"] in device_ids:
                device_ids[device["model"]] = 1

            dev_id = device_ids[device["model"]]
            device_ids[device["model"]] = dev_id + 1

            section = device["model"].upper() + "_" + str(dev_id)

            config.add_section(section)

            for key in device:
                config.set(section, key, str(device[key]))

        return config
Ejemplo n.º 4
0
    def _remove_blacklisted_devices(self, devices):
        """
        Remove blacklisted devices from the device list

        Args:
            List of devices

        Returns:
            Filtered list of devices
        """
        _device_blacklist = self._construct_blacklist()

        filtered_devices = []

        for device in devices:
            for blacklisted_device in _device_blacklist:
                if blacklisted_device["id"] == device.dev_id:
                    msg = ("Removed blacklisted device " +
                            blacklisted_device["name"] + " from device pool " +
                            "(Reason: " + blacklisted_device["reason"] + ")")

                    logger.info(msg)
                    print(msg)
                    break
            else: # else clause for the for loop
                filtered_devices.append(device)

        return filtered_devices
Ejemplo n.º 5
0
    def __init__(self, device):
        self._device = device
        self.test_cases = []
        self._results = []
        self._start_time = None
        self._end_time = None

        test_plan_name = device.test_plan
        test_plan_file = os.path.join("/etc/aft/test_plan/",
                                      device.test_plan + ".cfg")
        test_plan_config = ConfigParser.SafeConfigParser()
        test_plan_config.read(test_plan_file)

        if len(test_plan_config.sections()) == 0:
            raise errors.AFTConfigurationError(
                "Test plan " + str(test_plan_name) + " (" +
                str(test_plan_file) + ") doesn't " +
                "have any test cases. Does the file exist?")

        for test_case_name in test_plan_config.sections():
            test_case_config = dict(test_plan_config.items(test_case_name))
            test_case_config["name"] = test_case_name
            test_case = aft.testcasefactory.build_test_case(test_case_config)
            self.test_cases.append(test_case)

        logger.info("Built test plan with " + str(len(self.test_cases)) +
                    " test cases.")
Ejemplo n.º 6
0
 def disconnect(self):
     try:
         self.rpscontrol.turn_outlet_off(self.cutter_channel)
     except self.RPSError as e:
         logger.error(e)
         logger.error("Unable to turn off outlet " + self.cutter_channel)
         raise e
Ejemplo n.º 7
0
    def _wait_for_device(self, timeout=15):
        """
        Wait until the testing harness detects the Edison after boot

        Args:
            timeout (integer): Timeout for the detection process

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError on timeout
        """
        start = time.time()
        while time.time() - start < timeout:
            output = subprocess32.check_output(
                ["dfu-util", "-l", "-d", self._EDISON_DEV_ID])
            output_lines = output.decode().split("\n")

            fitting_lines = [
                line for line in output_lines
                if 'path="' + self._usb_path + '"' in line
            ]

            if fitting_lines:
                return
            else:
                continue

        err_str = "Could not find the device in DFU-mode in " + str(timeout) + \
            " seconds."
        logger.critical(err_str)
        raise errors.AFTDeviceError(err_str)
Ejemplo n.º 8
0
    def check_poweron(self):
        """
        Checks if device powers on sucessfully by checking if it enters DFU mode
        correctly


        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError on failure to connect to the device after
            running out of retries

            aft.errors.AFTConfigurationError if for some reason all retries fail
            and no other exception is raised
        """
        attempts = 3
        exception = None
        for i in range(attempts):
            logger.info("Attempt " + str(i + 1) + " of " + str(attempts) +
                " to power on the device " + self._configuration["name"])
            try:
                self._power_cycle()
                self._wait_for_device()
            except errors.AFTDeviceError as error:
                exception = error
                pass
            else:
                return

        if exception:
            raise exception


        raise errors.AFTConfigurationError("Failed to power on the device")
Ejemplo n.º 9
0
    def _find_active_serial_ports_from(self, wait_duration, device_files):
        """
        Find and returns list of active USB serial ports.

        This spawns a process that actually does the work.

        Args:
            device_files (list of strings):
                List of device files that will be checked for serial ports.
                Note that any other device file than ttyUSBx will be ignored.

        Returns:
            List of device files that have active serial port.
            Example: ["ttyUSB2", "ttyUSB4", "ttyUSB7"]

        """
        serial_results = Queue()

        serial_finder = Process(
            target=TopologyBuilder._get_active_serial_device_files,
            args=(self, serial_results, wait_duration, device_files),
        )
        if self._verbose:
            print("Serial thread - Finding active serial ports")

        logger.info("Finding active serial ports")
        serial_finder.start()

        return serial_results
Ejemplo n.º 10
0
    def get_root_partition_path(self, image_file_name):
        """
        Select either the default config value to be the root_partition
        or if the disk layout file exists, use the rootfs from it.

        Args:
            image_file_name (str): The name of the image file. Disk layout file
            name is based on this

        Returns:
            (str): path to the disk pseudo file
        """
        layout_file_name = self.get_layout_file_name(image_file_name)

        if not os.path.isfile(layout_file_name):
            logger.info("Disk layout file " + layout_file_name +
                        " doesn't exist. Finding root partition.")
            return self.find_root_partition()

        layout_file = open(layout_file_name, "r")
        disk_layout = json.load(layout_file)
        rootfs_partition = next(
            partition for partition in list(disk_layout.values()) \
            if isinstance(partition, dict) and \
            partition["name"] == "rootfs")
        return os.path.join("/dev", "disk", "by-partuuid",
                            rootfs_partition["uuid"])
Ejemplo n.º 11
0
    def write_image(self, file_name):
        """
        Writes the new image into the Edison

        Args:
            file_name (str):
                The file name of the image that will be flashed on the device
        Returns:
            True

        Raises:
            aft.errors.AFTDeviceError on various failures
            aft.errors.AFTConnectionError if the ssh connection could not be
                formed

        """

        file_name_no_extension = os.path.splitext(file_name)[0]

        self._mount_local(file_name_no_extension)
        self._add_usb_networking()
        self._add_ssh_key()
        self._unmount_local()

        # self._flashing_attempts = 0 # dfu-util may occasionally fail. Extra
        # attempts could be used?
        logger.info("Executing flashing sequence.")
        return self._flash_image(file_name_no_extension)
Ejemplo n.º 12
0
    def get_root_partition_path(self, image_file_name):
        """
        Select either the default config value to be the root_partition
        or if the disk layout file exists, use the rootfs from it.

        Args:
            image_file_name (str): The name of the image file. Disk layout file
            name is based on this

        Returns:
            (str): path to the disk pseudo file
        """
        layout_file_name = self.get_layout_file_name(image_file_name)

        if not os.path.isfile(layout_file_name):
            logger.info("Disk layout file " + layout_file_name  +
                         " doesn't exist. Finding root partition.")
            return self.find_root_partition()

        layout_file = open(layout_file_name, "r")
        disk_layout = json.load(layout_file)
        rootfs_partition = next(
            partition for partition in list(disk_layout.values()) \
            if isinstance(partition, dict) and \
            partition["name"] == "rootfs")
        return os.path.join(
            "/dev",
            "disk",
            "by-partuuid",
            rootfs_partition["uuid"])
Ejemplo n.º 13
0
    def _mount_local(self, file_name_no_extension):
        """
        Mount a image-file to a class-defined folder.
        Aborts if the mount command fails.

        Args:
            file_name_no_extension (str):
                The file name of the image that will be flashed on the device

        Returns:
            None
        """
        logger.info(
            "Mounting the root partition for ssh-key and USB-networking " +
            "service injection.")
        try:
            common.make_directory(self._LOCAL_MOUNT_DIR)

            root_file_system_file = file_name_no_extension + "." + \
                self._root_extension

            subprocess32.check_call(
                ["mount", root_file_system_file, self._LOCAL_MOUNT_DIR])

        except subprocess32.CalledProcessError as err:
            logger.info("Failed to mount.")
            common.log_subprocess32_error_and_abort(err)
Ejemplo n.º 14
0
 def _deploy_file(self, payload, user, timeout, device):
     """
     Deploys a file to the target device.
     """
     #  Test for presence of the file
     full_path_to_payload = os.path.join(self._TEST_DATA_PATH, payload)
     if not os.path.isfile(full_path_to_payload):
         self.output = "Error: media file \"{0}\" not found.".\
             format(full_path_to_payload)
         return False
     #  Push the file to the device
     self.output = device.push(source=full_path_to_payload,
                               destination=self._DUT_TMP,
                               user=user)
     if self.output != None:
         logger.critical("Couldn't copy " + str(full_path_to_payload) + " to " +
                          str(self._DUT_TMP) + ".\n" + str(self.output)
                          .format(full_path_to_payload, self._DUT_TMP,
                                  self.output))
         return False
     self.output = device.execute(
         environment=self._MEDIA_ENV,
         command=('chown', '-R', self.user,
                  os.path.join(self._DUT_TMP, payload)),
         user="******", timeout=timeout)
     return True
Ejemplo n.º 15
0
    def write_image(self, file_name):
        """
        Writes the new image into the Edison

        Args:
            file_name (str):
                The file name of the image that will be flashed on the device
        Returns:
            True

        Raises:
            aft.errors.AFTDeviceError on various failures
            aft.errors.AFTConnectionError if the ssh connection could not be
                formed

        """

        file_name_no_extension = os.path.splitext(file_name)[0]

        self._mount_local(file_name_no_extension)
        self._add_usb_networking()
        self._add_ssh_key()
        self._unmount_local()

        # self._flashing_attempts = 0 # dfu-util may occasionally fail. Extra
        # attempts could be used?
        logger.info("Executing flashing sequence.")
        return self._flash_image(file_name_no_extension)
Ejemplo n.º 16
0
def wait_for_responsive_ip_for_pc_device(
    leases_file_path,
    timeout,
    polling_interval):
    """
    Attempt to acquire active ip address for the device with the given mac
    address up to timeout seconds.

    Args:
        leases_file_path (str): Path to dnsmasq leases file
        timeout (integer): Timeout in seconds
        polling_interval (integer): Time between retries in seconds.

    Returns:
        Ip address as a string, or None if ip address was not responsive.
    """
    logger.info("Waiting for the device to become responsive")
    logger.debug("Timeout: " + str(timeout))
    logger.debug("Polling interval: " + str(polling_interval))

    for _ in range(timeout // polling_interval):
        responsive_ip = get_ip_for_pc_device(leases_file_path)

        if not responsive_ip:
            time.sleep(polling_interval)
            continue

        logger.info("Got a response from " + responsive_ip)
        return responsive_ip

    logger.info("No responsive ip was found")
Ejemplo n.º 17
0
    def _wait_for_device(self, timeout=15):
        """
        Wait until the testing harness detects the Edison after boot

        Args:
            timeout (integer): Timeout for the detection process

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError on timeout
        """
        start = time.time()
        while time.time() - start < timeout:
            output = subprocess32.check_output(
                ["dfu-util", "-l", "-d", self._EDISON_DEV_ID])
            output_lines = output.split("\n")

            fitting_lines = [
                line for line in output_lines
                if 'path="' + self._usb_path + '"' in line]

            if fitting_lines:
                return
            else:
                continue

        err_str = "Could not find the device in DFU-mode in " + str(timeout) + \
            " seconds."
        logger.critical(err_str)
        raise errors.AFTDeviceError(err_str)
Ejemplo n.º 18
0
    def _create_configuration(self):
        """
        Create and return ConfigParser object containing the device
        configurations

        Return:
            ConfigParser object containing the configurations
        """
        logger.info("Creating configuration object")
        config = SafeConfigParser()

        device_ids = {}

        for device in self._devices:
            # lack of model generally means that there was an unused power
            # cutter socket
            if not "model" in device:
                continue

            if not device["model"] in device_ids:
                device_ids[device["model"]] = 1

            dev_id = device_ids[device["model"]]
            device_ids[device["model"]] = dev_id + 1

            section = device["model"].upper() + "_" + str(dev_id)

            config.add_section(section)

            for key in device:
                config.set(section, key, str(device[key]))

        return config
Ejemplo n.º 19
0
def wait_for_responsive_ip_for_pc_device(leases_file_path, timeout,
                                         polling_interval):
    """
    Attempt to acquire active ip address for the device with the given mac
    address up to timeout seconds.

    Args:
        leases_file_path (str): Path to dnsmasq leases file
        timeout (integer): Timeout in seconds
        polling_interval (integer): Time between retries in seconds.

    Returns:
        Ip address as a string, or None if ip address was not responsive.
    """
    logger.info("Waiting for the device to become responsive")
    logger.debug("Timeout: " + str(timeout))
    logger.debug("Polling interval: " + str(polling_interval))

    for _ in range(timeout // polling_interval):
        responsive_ip = get_ip_for_pc_device(leases_file_path)

        if not responsive_ip:
            time.sleep(polling_interval)
            continue

        logger.info("Got a response from " + responsive_ip)
        return responsive_ip

    logger.info("No responsive ip was found")
Ejemplo n.º 20
0
    def check_poweron(self):
        """
        Checks if device powers on sucessfully by checking if it enters DFU mode
        correctly


        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError on failure to connect to the device after
            running out of retries

            aft.errors.AFTConfigurationError if for some reason all retries fail
            and no other exception is raised
        """
        attempts = 3
        exception = None
        for i in range(attempts):
            logger.info("Attempt " + str(i + 1) + " of " + str(attempts) +
                        " to power on the device " +
                        self._configuration["name"])
            try:
                self._power_cycle()
                self._wait_for_device()
            except errors.AFTDeviceError as error:
                exception = error
                pass
            else:
                return

        if exception:
            raise exception

        raise errors.AFTConfigurationError("Failed to power on the device")
Ejemplo n.º 21
0
    def _flash_image(self, file_name_no_extension):
        """
        Flash the new bootloader and image

        Args:
            file_name_no_extension (str):
                Image name without the extension (eg. edison-image.ext4 ->
                    edison-image)

        Returns:
            True

        Raises:
            errors.aft.AFTDeviceError if flashing fails
        """
        self._power_cycle()

        try:
            self._flash_partitions(file_name_no_extension)
        except errors.AFTPotentiallyBrokenBootloader as err:
            # if the bootloader is broken, the device is bricked until it is
            # recovered through recovery flashing.

            logger.critical("Bootloader might be broken " +
                            "(Note: This could be a false positive)")
            raise errors.AFTDeviceError(
                "Bootloader might be broken " +
                "(Note: This could be a false positive)")

        return True
Ejemplo n.º 22
0
 def run_remote_command(self, device):
     """
     Executes a command remotely, on the device.
     """
     self.output = device.execute(self.parameters.split(), timeout=120)
     logger.info("Command: " + str(self.parameters) + "\nresult: " + str(self.output) + ".")
     return self._check_for_success()
Ejemplo n.º 23
0
    def open_interface(self):
        """
        Open the host's network interface for testing

        Returns:
            None
        """
        interface = self._get_usb_nic()
        ip_subnet = self._host_ip + "/30"
        logger.info("Opening the host network interface for testing.")

        # The ifconfig command requires root privileges to run, and in general
        # we would like to run AFT without root privileges. However, we can add
        # a shell script to the sudoers file, which allows us to invoke it with
        # sudo, without the whole program requiring sudo. Hence, the below commands
        # will succeed even without root privileges

        # Note: Assumes that this file is under aft/devices, and that the shell
        # script is under aft/tools
        interface_script = os.path.join(os.path.dirname(__file__),
                                        os.path.pardir, "tools",
                                        "interface_script.sh")
        subprocess32.check_call(["sudo", interface_script, interface, "up"])
        subprocess32.check_call(
            ["sudo", interface_script, interface, ip_subnet])
Ejemplo n.º 24
0
    def __init__(self, config):
        super(ArduinoKeyboard, self).__init__()

        logger.set_root_logger_settings()

        self.emulator_path = config["pem_port"]
        self.interface = config["pem_interface"]
Ejemplo n.º 25
0
 def disconnect(self):
     try:
         self.rpscontrol.turn_outlet_off(self.cutter_channel)
     except self.RPSError as e:
         logger.error(e)
         logger.error("Unable to turn off outlet " + self.cutter_channel)
         raise e
Ejemplo n.º 26
0
    def _stop_vm(self):
        if not self._is_powered_on:
            return

        logger.info("Stopping the vm")
        misc.local_execute((
            "VBoxManage controlvm " + self._vm_name + " poweroff").split())
Ejemplo n.º 27
0
    def _mount_local(self, file_name_no_extension):
        """
        Mount a image-file to a class-defined folder.

        Aborts if the mount command fails.

        Args:
            file_name_no_extension (str):
                The file name of the image that will be flashed on the device

        Returns:
            None
        """
        logger.info(
            "Mounting the root partition for ssh-key and USB-networking " +
            "service injection.")
        try:
            common.make_directory(self._LOCAL_MOUNT_DIR)

            root_file_system_file = file_name_no_extension + "." + \
                self._root_extension

            # guestmount allows us to mount the image without root privileges
            subprocess32.check_call(
                ["guestmount", "-a", root_file_system_file, "-m", "/dev/sda", self._LOCAL_MOUNT_DIR])
        except subprocess32.CalledProcessError as err:
            logger.info("Failed to mount.")
            common.log_subprocess32_error_and_abort(err)
Ejemplo n.º 28
0
    def _get_device_configuration(self, cutter):
        """
        Disconnects a cutter, then checks if any ip, serial port or PEM has
        stopped responding. These will then be associated with each other.

        Args:
            cutter (aft.Cutter): The cutter that will be disconnected


        Returns:
            Dictionary containing all the associated information (ports, cutters
            etc). This varies depending on actual device type and physical
            connections. Edisons for example use USB networking and have
            different attributes present as a result.

            Example dictionary (content can and will vary):
            {
                "model": "MinnowboardMAX"
                "id": "12:34:56:78:90:ab",
                "cutter": "123456",
                "channel": "4",
                "pem_interface": "serialconnection",
                "pem_port": "/dev/ttyUSB9",
                "serial_port" = "/dev/ttyUSB2",
                "serial_bauds": "115200"
            }

        """

        logger.info("Shutting down a cutter")
        if self._verbose:
            print("Disconnected cutter")
            pprint.pprint(cutter.get_cutter_config())
            print("")
            print("Pinging addresses and checking ports for dead ones")

        cutter.disconnect()

        # start the threads as soon as possible so that their results are
        # available as soon as possible
        wait_duration = 30
        pem_results = self._find_active_pem_ports_from(wait_duration, self._pem_ports)

        serial_results = self._find_active_serial_ports_from(wait_duration, self._serial_ports)

        device = {}

        self._set_device_cutter_config(device, cutter)
        self._set_device_network_and_type(device)
        self._set_device_serial_port(device, serial_results)
        self._set_device_pem_port(device, pem_results)

        if self._verbose:
            print("Created device configuration:")
            print("")
            pprint.pprint(device)
            print("")

        return device
Ejemplo n.º 29
0
 def stop_image_usb_emulation(self, leases_file):
     """
     Stop using the image with USB mass storage emulation
     """
     self.free_dnsmasq_leases(leases_file)
     local_execute("stop_libcomposite".split())
     local_execute("systemctl start libcomposite.service".split())
     logger.info("Stopped USB mass storage emulation with an image")
Ejemplo n.º 30
0
Archivo: device.py Proyecto: dl9pf/DAFT
 def _power_cycle(self):
     """
     Reboot the device.
     """
     logger.info("Rebooting the device.")
     self.detach()
     sleep(self._POWER_CYCLE_DELAY)
     self.attach()
Ejemplo n.º 31
0
 def _power_cycle(self):
     """
     Reboot the device.
     """
     logger.info("Rebooting the device.")
     self.detach()
     sleep(self._POWER_CYCLE_DELAY)
     self.attach()
Ejemplo n.º 32
0
 def __init__(self, config):
     super(GadgetKeyboard, self).__init__()
     self.emulator = config["pem_port"] # Initialize path to HID keyboard emulator
     self.filepath = "" # Initialize filepath for send_keystrokes_from_file()
     self.delay_between_keys = 0 # Delay (seconds) between keystrokes
     self.modifier = 0 # On default don't use modifier key
     self.line_number = 0 # Line number we are parsing from filepath
     logger.set_process_prefix()
Ejemplo n.º 33
0
 def __init__(self, emulator_path="/dev/hidg0", write_mode="w"):
     self.emulator = emulator_path  # Initialize path to HID keyboard emulator
     self.write_mode = write_mode  # Change send_key() file write mode
     self.filepath = ""  # Initialize filepath for send_keystrokes_from_file()
     self.delay_between_keys = 0  # Delay (seconds) between keystrokes
     self.modifier = 0  # On default don't use modifier key
     self.line_number = 0  # Line number we are parsing from filepath
     logger.set_process_prefix()
Ejemplo n.º 34
0
    def try_flash_model(self, args):
        '''
        Reserve and flash a machine. By default it tries to flash 2 times,

        Args:
            args: AFT arguments
        Returns:
            device, tester: Reserved machine and tester handles.
        '''
        device = self.reserve()
        if args.testplan:
            device.test_plan = args.testplan
        tester = Tester(device)

        if args.record:
            device.record_serial()

        if not self.check_libcomposite_service_running():
            self.stop_image_usb_emulation(device.leases_file_name)

        if args.emulateusb:
            self.start_image_usb_emulation(args, device.leases_file_name)
            inject_ssh_keys_to_image(args.file_name)
            return device, tester

        if args.noflash:
            return device, tester

        flash_attempt = 0
        flash_retries = args.flash_retries
        while flash_attempt < flash_retries:
            flash_attempt += 1
            try:
                print("Flashing " + str(device.name) + ", attempt " +
                      str(flash_attempt) + " of " + str(flash_retries) + ".")
                device.write_image(args.file_name)
                print("Flashing successful.")
                return device, tester

            except KeyboardInterrupt:
                raise

            except:
                _err = sys.exc_info()
                _err = str(_err[0]).split("'")[1] + ": " + str(_err[1])
                logger.error(_err)
                print(_err)
                if (flash_retries - flash_attempt) == 0:
                    print("Flashing failed " + str(flash_attempt) + " times")
                    self.release(device)
                    raise

                elif (flash_retries - flash_attempt) == 1:
                    print("Flashing failed, trying again one more time")

                elif (flash_retries - flash_attempt) > 1:
                    print("Flashing failed, trying again " +
                          str(flash_retries - flash_attempt) + " more times")
Ejemplo n.º 35
0
 def __init__(self, config):
     super(GadgetKeyboard, self).__init__()
     self.emulator = config[
         "pem_port"]  # Initialize path to HID keyboard emulator
     self.filepath = ""  # Initialize filepath for send_keystrokes_from_file()
     self.delay_between_keys = 0  # Delay (seconds) between keystrokes
     self.modifier = 0  # On default don't use modifier key
     self.line_number = 0  # Line number we are parsing from filepath
     logger.set_process_prefix()
Ejemplo n.º 36
0
    def send_a_key(self, key, timeout=20):
        '''
        HID keyboard message length is 8 bytes and format is:

            [modifier, reserved, Key1, Key2, Key3, Key4, Key6, Key7]

        So first byte is for modifier key and all bytes after third one are for
        normal keys. After sending a key stroke, empty message with zeroes has
        to be sent to stop the key being pressed. Messages are sent by writing
        to the emulated HID usb port in /dev/. US HID keyboard hex codes
        are used for translating keys.

        Args:
            key: A key to send, for example: "a", "z", "3", "F2", "ENTER"
            timeout: how long sending a key will be tried until quitting [s]
        '''
        def writer(path, message, empty):
            while True:
                try:
                    with open(path, "w") as emulator:
                        emulator.write(message.decode())  # Send the key
                        emulator.write(empty)  # Stop the key being pressed
                except IOError:
                    sleep(1)
                else:
                    return 0

        # Empty message which will be sent to stop any keys being pressed
        empty = "\x00\x00\x00\x00\x00\x00\x00\x00"
        usb_message = bytearray(empty.encode())  # Initialize usb message
        hex_key, _modifier = self.key_to_hex(key)  # Translate key to hex code

        # Override self.modifier if the key needs a specific one
        if _modifier:
            modifier = _modifier
        else:
            modifier = self.modifier

        usb_message[2] = hex_key
        usb_message[0] = modifier

        # Do the writing in a subprocess as it hangs in some rare cases
        writer = Process(target=writer,
                         args=(self.emulator, usb_message, empty))
        writer.start()
        writer.join(20)
        if writer.is_alive():
            writer.terminate()
            msg = "Keyboard emulator couldn't connect to host or it froze"
            logger.error(msg, "kb_emulator.log")
            raise TimeoutError(msg)

        logger.info(
            "Sent key: " + key.ljust(5) + "  hex code: " +
            format(hex_key, '#04x') + "  modifier: " +
            format(modifier, '#04x'), "kb_emulator.log")
        return 0
Ejemplo n.º 37
0
 def _save_test_results(self):
     """
     Store the test results.
     """
     logger.info("Storing the test results.")
     xunit_results = self._results_to_xunit()
     results_filename = self.get_results_location()
     with open(results_filename, "w") as results_file:
         results_file.write(xunit_results)
     logger.info("Results saved to " + str(results_filename) + ".")
Ejemplo n.º 38
0
 def _save_test_results(self):
     """
     Store the test results.
     """
     logger.info("Storing the test results.")
     xunit_results = self._results_to_xunit()
     results_filename = self.get_results_location()
     with open(results_filename, "w") as results_file:
         results_file.write(xunit_results)
     logger.info("Results saved to " + str(results_filename) + ".")
Ejemplo n.º 39
0
 def disconnect(self):
     """
     Turns power off
     """
     try:
         self._set_gpio_pin(self._GPIO_CUTTER_OFF)
     except GpioCutterError as e:
         logger.error(e)
         logger.error("Unable to set GPIO controlled cutter off")
         raise e
Ejemplo n.º 40
0
 def _result_has_zero_fails(self):
     """
     Test if there are FAILED test cases in the QA-test case output
     """
     logger.info(self.output)
     failed_matches = re.findall("FAILED", self.output)
     result = True
     if len(failed_matches) > 0:
         result = False
     return result
Ejemplo n.º 41
0
 def _result_has_zero_fails(self):
     """
     Test if there are FAILED test cases in the QA-test case output
     """
     logger.info(self.output)
     failed_matches = re.findall("FAILED", self.output)
     result = True
     if len(failed_matches) > 0:
         result = False
     return result
Ejemplo n.º 42
0
 def disconnect(self):
     """
     Turns power off
     """
     try:
         self._set_gpio_pin(self._GPIO_CUTTER_OFF)
     except GpioCutterError as e:
         logger.error(e)
         logger.error("Unable to set GPIO controlled cutter off")
         raise e
Ejemplo n.º 43
0
    def send_a_key(self, key, timeout=20):
        '''
        HID keyboard message length is 8 bytes and format is:

            [modifier, reserved, Key1, Key2, Key3, Key4, Key6, Key7]

        So first byte is for modifier key and all bytes after third one are for
        normal keys. After sending a key stroke, empty message with zeroes has
        to be sent to stop the key being pressed. Messages are sent by writing
        to the emulated HID usb port in /dev/. US HID keyboard hex codes
        are used for translating keys.

        Args:
            key: A key to send, for example: "a", "z", "3", "F2", "ENTER"
            timeout: how long sending a key will be tried until quitting [s]
        '''
        def writer(path, message, empty):
            while True:
                try:
                    with open(path, "w") as emulator:
                        emulator.write(message.decode()) # Send the key
                        emulator.write(empty) # Stop the key being pressed
                except IOError:
                    sleep(1)
                else:
                    return 0

        # Empty message which will be sent to stop any keys being pressed
        empty = "\x00\x00\x00\x00\x00\x00\x00\x00"
        usb_message = bytearray(empty.encode()) # Initialize usb message
        hex_key, _modifier = self.key_to_hex(key) # Translate key to hex code

        # Override self.modifier if the key needs a specific one
        if _modifier:
            modifier = _modifier
        else:
            modifier = self.modifier

        usb_message[2] = hex_key
        usb_message[0] = modifier

        # Do the writing in a subprocess as it hangs in some rare cases
        writer = Process(target=writer, args=(self.emulator, usb_message, empty))
        writer.start()
        writer.join(20)
        if writer.is_alive():
            writer.terminate()
            msg = "Keyboard emulator couldn't connect to host or it froze"
            logger.error(msg, "kb_emulator.log")
            raise TimeoutError(msg)

        logger.info("Sent key: " + key.ljust(5) + "  hex code: " +
                    format(hex_key, '#04x') + "  modifier: " +
                    format(modifier, '#04x'), "kb_emulator.log")
        return 0
Ejemplo n.º 44
0
Archivo: ssh.py Proyecto: Valtis/AFT
def test_ssh_connectivity(remote_ip, timeout = 10):
    """
    Test whether remote_ip is accessible over ssh.
    """
    try:
        remote_execute(remote_ip, ["echo", "$?"], connect_timeout = timeout)
        return True
    except subprocess32.CalledProcessError as err:
        logger.warning("Could not establish ssh-connection to " + remote_ip +
                        ". SSH return code: " + str(err.returncode) + ".")
        return False
Ejemplo n.º 45
0
Archivo: ssh.py Proyecto: Valtis/AFT
def test_ssh_connectivity(remote_ip, timeout=10):
    """
    Test whether remote_ip is accessible over ssh.
    """
    try:
        remote_execute(remote_ip, ["echo", "$?"], connect_timeout=timeout)
        return True
    except subprocess32.CalledProcessError as err:
        logger.warning("Could not establish ssh-connection to " + remote_ip +
                       ". SSH return code: " + str(err.returncode) + ".")
        return False
Ejemplo n.º 46
0
def log_subprocess32_error_and_abort(err):
    """
    Log subprocess32 error cleanly and abort

    Args:
        err (subprocess32.CalledProcessError): The exception
    """
    logger.critical(str(err.cmd) + " failed with error code: " +
                     str(err.returncode) + " and output: " + str(err.output))
    logger.critical("Aborting")
    sys.exit(1)
Ejemplo n.º 47
0
    def _do_import_vm(self, ova_appliance):
        """
        Import the .ova appliance and grab the virtual hard drive name and VM
        name

        Args:
            ova_appliance (str):
                The ova appliance file

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError:
                If hard drive name or vm name were not set
        """

        output = misc.local_execute(
            ("VBoxManage import " + ova_appliance + "").split())

        # Get virtual hard drive name and VM name from output
        output = output.split("\n")
        for line in output:
            # Get hard drive name
            if "Hard disk image" in line:
                hdd_path_portion = line.split()[7].split("=")
                if hdd_path_portion[0] != "path":
                    break

                self._vhdd = hdd_path_portion[1]

                if self._vhdd.endswith(","):
                    self._vhdd = self._vhdd[:-1]

            # get VM name
            if "Suggested VM name" in line:
                self._vm_name = line.split()[4]

                # Strip starting ", if present
                if self._vm_name.startswith('"'):
                    self._vm_name = self._vm_name[1:]
                # Strip ending ", if present
                if self._vm_name.endswith('"'):
                    self._vm_name = self._vm_name[:-1]

        if self._vhdd and self._vm_name:
            logger.info("VM name: " + self._vm_name)
            logger.info("VHDD name: " + self._vhdd)
            return

        raise errors.AFTDeviceError(
            "Failed to find the VM name or virtual hard drive path. Has the " +
            "VirtualBox output format changed?")
Ejemplo n.º 48
0
def log_subprocess32_error_and_abort(err):
    """
    Log subprocess32 error cleanly and abort

    Args:
        err (subprocess32.CalledProcessError): The exception
    """
    logger.critical(
        str(err.cmd) + " failed with error code: " + str(err.returncode) +
        " and output: " + str(err.output))
    logger.critical("Aborting")
    sys.exit(1)
Ejemplo n.º 49
0
    def _unmount_over_ssh(self):
        """
        Unmount the mounted directory at self.mount_dir

        Returns:
            None
        """
        logger.info("Unmounting " + self.mount_dir)
        try:
            ssh.remote_execute(self.dev_ip, ["umount", self.mount_dir])
        except subprocess32.CalledProcessError as err:
            common.log_subprocess32_error_and_abort(err)
Ejemplo n.º 50
0
 def free_dnsmasq_leases(self, leases_file):
     """
     dnsmasq.leases file needs to be cleared and dnsmasq.service restarted
     or there will be no IP address to give for DUT if same
     image is used in quick succession with and without --emulateusb
     """
     local_execute("systemctl stop dnsmasq.service".split())
     with open(leases_file, "w") as f:
         f.write("")
         f.flush()
     local_execute("systemctl start dnsmasq.service".split())
     logger.info("Freed dnsmasq leases")
Ejemplo n.º 51
0
    def _import_vm(self, ova_appliance):
        """
        Set default VirtualBox directory and import the .ova appliance into
        VirtualBox as a VM
        """
        logger.info("Importing VM appliance")
        self._set_default_directory(
            os.path.join(
                os.getcwd(),
                self._VM_DIRECTORY))

        self._do_import_vm(ova_appliance)
Ejemplo n.º 52
0
    def _mount_single_layer(self, image_file_name):
        """
        Mount a hdddirect partition

        Returns:
            None
        """
        logger.info("Mount one layer.")
        ssh.remote_execute(self.dev_ip,
                           ["mount",
                           self.get_root_partition_path(image_file_name),
                           self._ROOT_PARTITION_MOUNT_POINT])
Ejemplo n.º 53
0
    def _result_has_zero_fails(self):
        """
        Test if there are FAILED test cases in the QA-test case output
        """
        logger.info(self.output)
#        qa_log_file = open("results-runtest.py.log", "r")
#        qa_log = qa_log_file.read()
#        qa_log_file.close()
        failed_matches = re.findall("FAILED", self.output)
        result = True
        if len(failed_matches) > 0:
            result = False
        return result
Ejemplo n.º 54
0
 def execute(self, device):
     """
     Prepare and executes the test case, storing the results.
     """
     start_time = datetime.datetime.now()
     logger.info("Test case start time: " + str(start_time))
     self._prepare()
     # Test cases are run using the Visitor pattern to allow last-minute
     # preparation of the device for the test.
     self.result = device.test(self)
     self.duration = datetime.datetime.now() - start_time
     logger.info("Test Duration: " + str(self.duration))
     self._build_xunit_section()
Ejemplo n.º 55
0
    def _send_PEM_keystrokes(self, keystrokes, attempts=1, timeout=60):
        """
        Try to send keystrokes within the time limit

        Args:
            keystrokes (str): PEM keystroke file
            attempts (integer): How many attempts will be made
            timeout (integer): Timeout for a single attempt

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if PEM connection times out

        """
        def call_pem(exceptions):
            try:
                pem_main(
                [
                    "pem",
                    "--interface", self.pem_interface,
                    "--port", self.pem_port,
                    "--playback", keystrokes
                ])
            except Exception as err:
                exceptions.put(err)

        for i in range(attempts):
            logger.info(
                "Attempt " + str(i + 1) + " of " + str(attempts) + " to send " +
                "keystrokes through PEM")

            exception_queue = Queue()
            process = Process(target=call_pem, args=(exception_queue,))
            # ensure python process is closed in case main process dies but
            # the subprocess is still waiting for timeout
            process.daemon = True

            process.start()
            process.join(timeout)

            if not exception_queue.empty():
                raise exception_queue.get()

            if process.is_alive():
                process.terminate()
            else:
                return

        raise errors.AFTDeviceError("Failed to connect to PEM")