示例#1
0
    def _enter_mode(self, target, keystrokes):
        """
        Try to put the device into the specified mode.
        Args:
            keystrokes (string): Path to keystrokes file for booting
            target (string): Boot target: 'test_mode' or 'service_mode'
        Raises:
            aft.errors.AFTDeviceError if device fails to enter the mode or if
            keyboard emulator fails to connect
        """
        if not (target == "test_mode" or target == "service_mode"):
            raise errors.AFTDeviceError(
                "Bad argument: target=" + target +
                " for pcdevice.py: _enter_mode function")

        # Sometimes booting to a mode fails.
        logger.info("Trying to enter " + target + " up to " +
                    str(self._RETRY_ATTEMPTS) + " times.")

        for _ in range(self._RETRY_ATTEMPTS):
            try:
                self._power_cycle()

                if self.kb_emulator:
                    logger.info("Using " + type(self.kb_emulator).__name__ +
                                " to send keyboard sequence " + keystrokes)

                    self.kb_emulator.send_keystrokes(keystrokes)

                else:
                    logger.warning(
                        "No keyboard emulator defined for the device")

                ip_address = self._wait_for_responsive_ip()

                if ip_address:
                    if target == "test_mode" and not \
                      self._verify_mode(self._service_mode_name):
                        logger.info("Correctly booted target image")
                        return
                    if target == "service_mode" and \
                      self._verify_mode(self._service_mode_name):
                        logger.info("Correctly booted support image")
                        return
                else:
                    logger.warning("Failed entering " + target + ".")

            except KeyboardInterrupt:
                raise

            except:
                _err = sys.exc_info()
                logger.error(str(_err[0]).split("'")[1] + ": " + str(_err[1]))

        logger.critical("Unable to get the device in mode " + target)

        raise errors.AFTDeviceError("Could not set the device in mode " +
                                    target)
示例#2
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
示例#3
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)
示例#4
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):
            try:
                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")

            except KeyboardInterrupt:
                raise

            except:
                _err = sys.exc_info()
                logger.error(str(_err[0]).split("'")[1] + ": " + str(_err[1]))

        raise errors.AFTDeviceError("Could not set the device in test mode")
示例#5
0
文件: pcdevice.py 项目: dl9pf/DAFT
    def find_root_partition(self):
        '''
        Find _target_device partition that has /home/root
        '''
        # Find all _target_device partitions
        partitions = []
        target = self._target_device.split("/")[-1]
        lsblk = ssh.remote_execute(self.dev_ip, ["lsblk"])
        lsblk = lsblk.split()
        for line in lsblk:
            if (target + "p") in line:
                line = ''.join(x for x in line if x.isalnum())
                partitions.append(line)

        # Check through partitions if it contains '/home/root' directory
        for partition in partitions:
            ssh.remote_execute(self.dev_ip, [
                "mount", "/dev/" + partition, self._ROOT_PARTITION_MOUNT_POINT
            ])
            files = ssh.remote_execute(
                self.dev_ip, ["ls", self._ROOT_PARTITION_MOUNT_POINT])
            if "home" in files:
                files = ssh.remote_execute(
                    self.dev_ip,
                    ["ls", self._ROOT_PARTITION_MOUNT_POINT + "home/"])
            ssh.remote_execute(self.dev_ip,
                               ["umount", self._ROOT_PARTITION_MOUNT_POINT])
            if "root" in files:
                partition_path = "/dev/" + partition
                return partition_path

        raise errors.AFTDeviceError("Couldn't find root partition")
示例#6
0
文件: pcdevice.py 项目: dl9pf/DAFT
    def _enter_mode(self, mode):
        """
        Try to put the device into the specified mode.

        Args:
            mode (Dictionary):
                Dictionary that contains the mode specific information

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if device fails to enter the mode or if
            keyboard emulator fails to connect
        """
        # Sometimes booting to a mode fails.
        logger.info("Trying to enter " + mode["name"] + " mode up to " +
                    str(self._RETRY_ATTEMPTS) + " times.")

        for _ in range(self._RETRY_ATTEMPTS):
            try:
                self._power_cycle()

                if self.kb_emulator:
                    logger.info("Using " + type(self.kb_emulator).__name__ +
                                " to send keyboard sequence " +
                                mode["sequence"])

                    self.kb_emulator.send_keystrokes(mode["sequence"])

                else:
                    logger.warning(
                        "No keyboard emulator defined for the device")

                ip_address = self._wait_for_responsive_ip()

                if ip_address:
                    if self._verify_mode(mode["name"]):
                        return
                else:
                    logger.warning("Failed entering " + mode["name"] +
                                   " mode.")

            except KeyboardInterrupt:
                raise

            except:
                _err = sys.exc_info()
                logger.error(str(_err[0]).split("'")[1] + ": " + str(_err[1]))

        logger.critical("Unable to get the device in mode " + mode["name"])

        raise errors.AFTDeviceError("Could not set the device in mode " +
                                    mode["name"])
示例#7
0
    def _start_vm(self):
        if self._is_powered_on:
            return

        output = misc.local_execute((
            "VBoxManage startvm " + self._vm_name + " --type headless").split())

        if "error" in output:
            raise errors.AFTDeviceError("Failed to start the VM:\n" + output)

        self._is_powered_on = True
示例#8
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?")
示例#9
0
    def send_keystrokes(self, _file):
        """
        Method to send keystrokes from a file
        """

        try:
            kbemu = self.kbemucontrol.KBEMUControl(_file, kbemu_model ='usbkm232')
            kbemu.open()
            kbemu.perform('seq')

        except:
            raise errors.AFTDeviceError("KM232 Keyboard emulator failed.")
示例#10
0
文件: pcdevice.py 项目: Valtis/AFT
    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")
示例#11
0
    def _flash_image(self):
        """
        Flash boot and root partitions

        Returns:
            None
        """
        logger.info("Flashing image")

        if not self.dev_ip:
            logger.warning("Unable to get ip address for the device")

            raise errors.AFTDeviceError(
                "Could not get device ip (dhcp error or device " +
                "failed to boot?)")

        self._write_boot_partition()
        self._write_root_partition()
示例#12
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. As only one device can be
            # powered on during recovery flashing, we just blacklist the device
            # and recover it later

            logger.critical(
                "Bootloader might be broken - blacklisting the " +
                "device as a precaution (Note: This could be a false positive)"
            )

            common.blacklist_device(
                self._configuration["id"], self._configuration["name"],
                "Bootloader might be broken - recovery flashing " +
                "will be performed as a precaution (Note: This could be a " +
                "false positive")

            self._recover_edison()

            raise errors.AFTDeviceError(
                "Bootloader might be broken - blacklisting the " +
                "device as a precaution (Note: This could be a false positive)"
            )

        return True
示例#13
0
    def _get_usb_nic(self, timeout=120):
        """
        Search and return for the network interface attached to the DUT's
        USB-path

        Args:
            timeout (integer): The timeout value in seconds

        Returns:
            (str): The usb network interface

        Raises:
            aft.errors.AFTDeviceError if USB network interface was not found
        """
        logging.info(
            "Searching for the host network interface from usb path " +
            self._usb_path)

        start = time.time()
        while time.time() - start < timeout:

            interfaces = netifaces.interfaces()
            for interface in interfaces:
                try:
                    # Test if the interface is the correct USB-ethernet NIC
                    nic_path = os.path.realpath(os.path.join(
                        self._NIC_FILESYSTEM_LOCATION, interface))
                    usb_path = _get_nth_parent_dir(nic_path, 3)

                    if os.path.basename(usb_path) == self._usb_path:
                        return interface
                except IOError as err:
                    print "IOError: " + str(err.errno) + " " + err.message
                    print (
                        "Error likely caused by jittering network interface."
                        " Ignoring.")
                    logging.warning(
                        "An IOError occured when testing network interfaces. " +
                        " IOERROR: " + str(err.errno) + " " + err.message)
            time.sleep(1)

        raise errors.AFTDeviceError(
            "Could not find a network interface from USB-path " +
            self._usb_path + " in 120 seconds.")
示例#14
0
    def _enter_mode(self, mode):
        """
        Try to put the device into the specified mode.

        Args:
            mode (Dictionary):
                Dictionary that contains the mode specific information

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if device fails to enter the mode or if
            PEM fails to connect

        """
        # Sometimes booting to a mode fails.

        logging.info("Trying to enter " + mode["name"] + " mode up to " +
                     str(self._RETRY_ATTEMPTS) + " times.")

        for _ in range(self._RETRY_ATTEMPTS):
            self._power_cycle()

            logging.info("Executing PEM with keyboard sequence " +
                         mode["sequence"])

            self._send_PEM_keystrokes(mode["sequence"])

            ip_address = self._wait_for_responsive_ip()

            if ip_address:
                if self._verify_mode(mode["name"]):
                    return
            else:
                logging.warning("Failed entering " + mode["name"] + " mode.")

        logging.critical("Unable to get device " + self.dev_id + " in mode " +
                         mode["name"])

        raise errors.AFTDeviceError("Could not set the device in mode " +
                                    mode["name"])
示例#15
0
    def send_keystrokes(self, _file):
        """
        Method to send keystrokes from a file

        Args:
            keystrokes (str): PEM keystroke file
        Returns:
            None
        Raises:
            aft.errors.AFTDeviceError if PEM connection times out
        """
        from pem.main import main as pem_main

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

        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(60)

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

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

        raise errors.AFTDeviceError("Failed to connect to Arduino keyboard " +
                                    "emulator - check the connections, " +
                                    "AFT settings and emulator hardware")
示例#16
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, err:
            # if the bootloader is broken, the device is bricked until it is
            # recovered through recovery flashing. As only one device can be
            # powered on during recovery flashing, we just blacklist the device
            # and recover it later

            logging.critical(
                "Bootloader seems to have been broken - blacklisting the " +
                "device")

            common.blacklist_device(
                self._configuration["id"],
                self._configuration["name"],
                "Bootloader seems to be broken - recovery flashing " +
                "required")

            self._recover_edison()

            raise errors.AFTDeviceError(
                "Bootloader seems to have been broken - blacklisting the " +
                "device")
示例#17
0
    def _find_mac_address(self):
        """
        Find VM mac address from showvminfo output

        Returns:
            None
        Raises:
            aft.errors.AFTDeviceError:
                If mac address could not be found from showvminfo output
        """
        output = misc.local_execute(
            ("VBoxManage showvminfo " + self._vm_name).split())
        output = output.split("\n")

        # should contain line like:
        # NIC 1: MAC: 080027F3FDC2, Attachment: Host-only Interface 'vboxnet0',
        # Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported
        # speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny, Bandwidth
        # group: none
        #
        # We grab the mac address from it

        for line in output:
            if " MAC: " in line:
                self._mac_address = line.split()[3]
                if self._mac_address.endswith(","):
                    self._mac_address = self._mac_address[:-1]
                # Add colons after every two symbols
                as_array = [self._mac_address[i:i+2] for i in range(0, len(self._mac_address), 2)]
                self._mac_address = ":".join(as_array)
                logger.info("Device mac address: " + self._mac_address)
                return

        raise errors.AFTDeviceError(
            "Failed to find mac address from showvminfo output. Has the " +
            "output format changed")
示例#18
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
        logging.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:
                logging.warning("Failed to enter test mode")

        raise errors.AFTDeviceError("Could not set the device in test mode")
示例#19
0
def _run_tests_on_know_good_image(args, device):

    if device.model.lower() == "edison":
        return (True, "Skipped - produces too many false negatives")

    if args.verbose:
        print("Flashing and testing a known good image")

    logger.info("Flashing and testing a known good image")

    image_directory_path = os.path.join(config.KNOWN_GOOD_IMAGE_FOLDER,
                                        device.model.lower())

    image = None
    if device.model.lower() == "beagleboneblack":
        image = image_directory_path
    elif device.model.lower() == "edison":
        image = os.path.join(image_directory_path, "ostro-image-edison.ext4")
    else:
        image = os.path.join(image_directory_path, "good-image.dsk")

    if args.verbose:
        print("Image file: " + str(image))
        print("Flashing " + str(device.name))

    logger.info("Image file: " + str(image))

    try:

        results_queue = multiprocessing_queue()

        def worker(results):

            os.chdir(os.path.join(image_directory_path, "iottest"))
            # nuke test logs
            for f in os.listdir("."):
                if "ssh_target_log" in f:
                    os.remove(f)

            os.chdir(image_directory_path)
            ## Remove all log and xml files from previous run to prevent clutter
            #for f in os.listdir("."):
            #    if f.endswith(".log") or f.endswith(".xml"):
            #        os.remove(f)

            device.write_image(image)

            tester = Tester(device)
            tester.execute()
            results.put((tester.get_results(), tester.get_results_str()))

        # Run this in a separate process, so that we can change its working
        # directory, without changing the working directory for the rest of
        # the program
        process = Process(target=worker, args=(results_queue, ))

        process.start()
        process.join()

        if results_queue.empty():
            raise errors.AFTDeviceError("No results from test run")

        results = results_queue.get()
        result = reduce(lambda x, y: x and y, results[0])

        result_str = "Image test result: "

        if result:
            result_str += "Ok"
        else:
            result_str += " Failure(s): \n\n" + results[1]

        return (result, result_str)

    except Exception as error:
        return (False, "Image Test result: " + str(error))
示例#20
0
 def _enter_test_mode(self):
     logger.info("Entering test mode")
     self._set_host_only_nic()
     self._start_vm()
     if self.get_ip() == None:
         raise errors.AFTDeviceError("Failed to get responsive ip")
示例#21
0
class PCDevice(Device):
    """
    Class representing a PC-like device.

    Attributes:
        _RETRY_ATTEMPTS (integer):
            How many times the device attempts to enter the requested mode
            (testing/service) before givingup

        _BOOT_TIMEOUT (integer):
            The device boot timeout. Used when waiting for responsive ip address

        _POLLING_INTERVAL (integer):
            The polling interval used when waiting for responsive ip address

        _SSH_IMAGE_WRITING_TIMEOUT (integer):
            The timeout for flashing the image.

        _IMG_NFS_MOUNT_POINT (str):
            The location where the service OS mounts the nfs filesystem so that
            it can access the image file etc.

        _ROOT_PARTITION_MOUNT_POINT (str):
            The location where the service OS mounts the image root filesystem
            for SSH key injection.

        _SUPER_ROOT_MOUNT_POINT (str):
            Mount location used when having to mount two layers



    """
    _RETRY_ATTEMPTS = 8
    _BOOT_TIMEOUT = 240
    _POLLING_INTERVAL = 10
    _SSH_IMAGE_WRITING_TIMEOUT = 1440
    _IMG_NFS_MOUNT_POINT = "/mnt/img_data_nfs"
    _ROOT_PARTITION_MOUNT_POINT = "/mnt/target_root/"
    _SUPER_ROOT_MOUNT_POINT = "/mnt/super_target_root/"

    def __init__(self, parameters, channel):
        """
        Constructor

        Args:
            parameters (Dictionary): Device configuration parameters
            channel (aft.Cutter): Power cutter object
        """

        super(PCDevice, self).__init__(device_descriptor=parameters,
                                       channel=channel)

        self.retry_attempts = 8

        self._leases_file_name = parameters["leases_file_name"]
        self.default_root_patition = parameters["root_partition"]
        self._service_mode_name = parameters["service_mode"]
        self._test_mode_name = parameters["test_mode"]

        self.pem_interface = parameters["pem_interface"]
        self.pem_port = parameters["pem_port"]
        self._test_mode = {
            "name": self._test_mode_name,
            "sequence": parameters["test_mode_keystrokes"]
        }
        self._service_mode = {
            "name": self._service_mode_name,
            "sequence": parameters["service_mode_keystrokes"]
        }
        self._target_device = \
            parameters["target_device"]

        self._config_check_keystrokes = parameters["config_check_keystrokes"]

        self.dev_ip = None
        self._uses_hddimg = None

# pylint: disable=no-self-use

# pylint: enable=no-self-use

    def write_image(self, file_name):
        """
        Method for writing an image to a device.

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

        Returns:
            None
        """
        # NOTE: it is expected that the image is located somewhere
        # underneath config.NFS_FOLDER (default: /home/tester),
        # therefore symlinks outside of it will not work
        # The config.NFS_FOLDER path is exported as nfs and mounted remotely as
        # _IMG_NFS_MOUNT_POINT

        # Bubblegum fix to support both .hddimg and .hdddirect at the same time
        self._uses_hddimg = os.path.splitext(file_name)[-1] == ".hddimg"

        self._enter_mode(self._service_mode)
        file_on_nfs = os.path.abspath(file_name).replace(
            config.NFS_FOLDER, self._IMG_NFS_MOUNT_POINT)

        self._flash_image(nfs_file_name=file_on_nfs)
        self._install_tester_public_key(file_name)

    def _run_tests(self, test_case):
        """
        Boot to test-mode and execute testplan.

        Args:
            test_case (aft.TestCase): Test case object

        Returns:
            The return value of the test_case run()-method
            (implementation class specific)
        """
        self._enter_mode(self._test_mode)
        return test_case.run(self)

    def get_ip(self):
        """
        Returns device ip address

        Returns:
            (str): The device ip address
        """
        return common.get_ip_for_pc_device(self.dev_id,
                                           self.parameters["leases_file_name"])

    def _enter_mode(self, mode):
        """
        Try to put the device into the specified mode.

        Args:
            mode (Dictionary):
                Dictionary that contains the mode specific information

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if device fails to enter the mode or if
            PEM fails to connect

        """
        # Sometimes booting to a mode fails.

        logging.info("Trying to enter " + mode["name"] + " mode up to " +
                     str(self._RETRY_ATTEMPTS) + " times.")

        for _ in range(self._RETRY_ATTEMPTS):
            self._power_cycle()

            logging.info("Executing PEM with keyboard sequence " +
                         mode["sequence"])

            self._send_PEM_keystrokes(mode["sequence"])

            ip_address = self._wait_for_responsive_ip()

            if ip_address:
                if self._verify_mode(mode["name"]):
                    return
            else:
                logging.warning("Failed entering " + mode["name"] + " mode.")

        logging.critical("Unable to get device " + self.dev_id + " in mode " +
                         mode["name"])

        raise errors.AFTDeviceError("Could not set the device in mode " +
                                    mode["name"])

    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, err:
                exceptions.put(err)

        for i in range(attempts):
            logging.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")
示例#22
0
    def _dfu_call(self,
                  alt,
                  source,
                  extras=[],
                  attempts=4,
                  timeout=1800,
                  ignore_errors=False):
        """
        Call DFU-util successively with arguments until it succeeds

        Args:
            alt (str):
                The --alt-argument for the dfu-util program. See relevant man
                page for more information on dfu-util and its arguments.
            source (str):
                The source file, which will be flashed
            extras (list(str)):
                Extra arguments for the dfu-util program
            attempts (interer):
                How many times flashing will be attempted
            timeout (integer):
                The timeout value for a single flashing attempt
            ignore_errors (boolean):
                Ignores error codes from dfu-util. This is a workaround
                for flashing IFWI. Original flashall script checks if the usb
                device is present before attempting to flash by checking that
                vendor and device USB ids are present. This however does not
                work here, as we may have multipe Edisons with identical
                vendor and device ids. Instead, we just try to flash the
                partition, and ignore the errors that occur when the device
                isn't present.

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if flashing has not succeeded after the
            number of attempts specified by the method argument
        """
        attempt = 0
        while attempt < attempts:
            flashing_log_file = open(self._FLASHER_OUTPUT_LOG, "a")
            self._wait_for_device()
            execution = subprocess32.Popen([
                "dfu-util", "-v", "--path", self._usb_path, "--alt", alt, "-D",
                source
            ] + extras,
                                           stdout=flashing_log_file,
                                           stderr=flashing_log_file)

            start = time.time()
            while time.time() - start < timeout:
                status = execution.poll()
                if status == None:
                    continue
                else:
                    flashing_log_file.close()
                    if not ignore_errors and execution.returncode != 0:
                        logger.warning("Return value was non-zero - retrying")
                        break

                    # dfu-util does not return non-zero value when flashing
                    # fails due to download error. Instead, check if last few
                    # lines in the log contain "Error during download"
                    with open(self._FLASHER_OUTPUT_LOG) as flash_log:
                        last_lines = flash_log.readlines()[-10:]
                        break_outer = False
                        for line in last_lines:
                            if "Error during download" in line:
                                logger.warning("Error in log - retrying")
                                break_outer = True
                                break
                        if break_outer:
                            break
                    return

            try:
                execution.kill()
            except OSError as err:
                if err.errno == 3:  # 3 = errno.ESRCH = no such process
                    pass
                else:
                    raise
            attempt += 1
            if time.time() - start >= timeout:
                logger.warning("Flashing timeout")
            logger.warning("Flashing failed on alt " + alt + " for file " +
                           source + " on USB-path " + self._usb_path +
                           ". Rebooting and attempting again for " +
                           str(attempt) + "/" + str(attempts) + " time.")

            self._power_cycle()
        flashing_log_file.close()
        raise errors.AFTDeviceError("Flashing failed " + str(attempts) +
                                    " times. Raising error (aborting).")
示例#23
0
    def _dfu_call(
        self,
        alt,
        source,
        extras=[],
        attempts=4,
        timeout=600,
        ignore_errors=False):
        """
        Call DFU-util successively with arguments until it succeeds

        Args:
            alt (str):
                The --alt-argument for the dfu-util program. See relevant man
                page for more information on dfu-util and its arguments.
            source (str):
                The source file, which will be flashed
            extras (list(str)):
                Extra arguments for the dfu-util program
            attempts (interer):
                How many times flashing will be attempted
            timeout (integer):
                The timeout value for a single flashing attempt
            ignore_errors (boolean):
                Ignores error codes from dfu-util. This is a workaround
                for flashing IFWI. Original flashall script checks if the usb
                device is present before attempting to flash by checking that
                vendor and device USB ids are present. This however does not
                work here, as we may have multipe Edisons with identical
                vendor and device ids. Instead, we just try to flash the
                partition, and ignore the errors that occur when the device
                isn't present.

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if flashing has not succeeded after the
            number of attempts specified by the method argument
        """

        attempt = 0
        while attempt < attempts:
            flashing_log_file = open(self._FLASHER_OUTPUT_LOG, "a")
            self._wait_for_device()
            execution = subprocess32.Popen(
                [
                   "dfu-util", "-v", "--path",
                    self._usb_path,
                    "--alt", alt, "-D",
                    source
                ] + extras,
                stdout=flashing_log_file,
                stderr=flashing_log_file)

            start = time.time()
            while time.time() - start < timeout:
                status = execution.poll()
                if status == None:
                    continue
                else:
                    flashing_log_file.close()
                    if ignore_errors or execution.returncode == 0:
                        return

                    # There was a warning here that dfu-util always returns 0
                    # and as such we should grep ~5 last lines in flash log for
                    # 'Done!' instead. However, my brief experimentation with
                    # dfu-util seems to indicate that dfu-util infact does
                    # return nonzero value on failure, and as such I removed
                    # this log check in favor of return value check. I'm leaving
                    # this comment here in case this turns out to be a bad idea
                    # and some future maintainer can revert this decision

                    break

            try:
                execution.kill()
            except OSError as err:
                if err.errno == 3: # 3 = errno.ESRCH = no such process
                    pass
                else:
                    raise
            attempt += 1

            logging.warning(
                "Flashing failed on alt " + alt + " for file " + source +
                " on USB-path " + self._usb_path +
                ". Rebooting and attempting again for " +
                str(attempt) + "/" + str(attempts) + " time.")

            self._power_cycle()
        flashing_log_file.close()
        raise errors.AFTDeviceError(
            "Flashing failed " + str(attempts) +
            " times. Raising error (aborting).")
示例#24
0
    def _enter_service_mode(self):
        """
        Enter service mode by booting support image over nfs

        Interrupts regular boot, and enters the necessary u-boot commands to
        boot the nfs based support image rather than the image stored on the
        SD-card

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if the device failed to enter the service
            mode
        """

        logging.info("Trying to enter service mode up to " +
                     str(self._SERVICE_MODE_RETRY_ATTEMPTS) + " times.")

        for _ in range(self._SERVICE_MODE_RETRY_ATTEMPTS):

            self._power_cycle()

            tftp_path = self.parameters["support_fs"]
            kernel_image_path = self.parameters["support_kernel_path"]
            dtb_path = self.parameters["support_dtb_path"]
            console = "ttyO0,115200n8"

            stream = serial.Serial(self.parameters["serial_port"],
                                   self.parameters["serial_bauds"],
                                   timeout=0.01,
                                   xonxoff=True)

            counter = 100

            # enter uboot console
            for _ in range(counter):
                serial_write(stream, " ", 0.1)

            # if autoload is on, dhcp command attempts to download kernel
            # as well. We do this later manually over tftp
            serial_write(stream, "setenv autoload no", 1)

            # get ip from dhcp server
            # NOTE: This seems to occasionally fail. This doesn't matter
            # too much, as the next retry attempt propably works.
            serial_write(stream, "dhcp", 15)

            # setup kernel boot arguments (nfs related args and console so that
            # process is printed in case something goes wrong)
            serial_write(
                stream, "setenv bootargs console=" + console +
                ", root=/dev/nfs nfsroot=${serverip}:" + self.nfs_path +
                ",vers=3 rw ip=${ipaddr}", 1)

            # download kernel image into the specified memory address
            serial_write(
                stream, "tftp 0x81000000 " +
                os.path.join(tftp_path, kernel_image_path), 15)

            # download device tree binary into the specified memory location
            # IMPORTANT NOTE: Make sure that the kernel image and device tree
            # binary files do not end up overlapping in the memory, as this
            # ends up overwriting one of the files and boot unsurprisingly fails
            serial_write(
                stream, "tftp 0x80000000 " + os.path.join(tftp_path, dtb_path),
                5)

            # boot, give kernel image and dtb as args (middle arg is ignored,
            # hence the '-')
            serial_write(stream, "bootz 0x81000000 - 0x80000000", 1)
            stream.close()

            self.dev_ip = self._wait_for_responsive_ip()

            if (self.dev_ip
                    and self._verify_mode(self.parameters["service_mode"])):
                return
            else:
                logging.warning("Failed to enter service mode")

        raise errors.AFTDeviceError("Could not set the device in service mode")
示例#25
0
    def _enter_service_mode(self):
        """
        Enter service mode by booting support image over nfs

        Interrupts regular boot, and enters the necessary u-boot commands to
        boot the nfs based support image rather than the image stored on the
        SD-card

        Returns:
            None

        Raises:
            aft.errors.AFTDeviceError if the device failed to enter the service
            mode
        """
        logger.info("Trying to enter service mode up to " +
                    str(self._SERVICE_MODE_RETRY_ATTEMPTS) + " times.")

        for _ in range(self._SERVICE_MODE_RETRY_ATTEMPTS):
            try:
                self._power_cycle()

                stream = serial.Serial(self.parameters["serial_port"],
                                       self.parameters["serial_bauds"],
                                       timeout=0.01,
                                       xonxoff=True)

                counter = 100

                # enter uboot console
                for _ in range(counter):
                    serial_write(stream, " ", 0.1)

                # Load kernel image and device tree binary from usb
                serial_write(
                    stream,
                    "setenv bootargs 'console=ttyO0,115200n8, root=/dev/sda1 rootwait rootfstype=ext4 rw'",
                    1)
                serial_write(stream, "usb start", 5)
                serial_write(
                    stream,
                    "ext4load usb 0:1 0x81000000 /boot/vmlinuz-4.4.9-ti-r25",
                    10)
                serial_write(
                    stream,
                    "ext4load usb 0:1 0x80000000 /boot/dtbs/4.4.9-ti-r25/am335x-boneblack.dtb",
                    5)

                stream.close()
                self.dev_ip = self._wait_for_responsive_ip()
                if (self.dev_ip and self._verify_mode(
                        self.parameters["service_mode"])):
                    return
                else:
                    logger.warning("Failed to enter service mode")

            except KeyboardInterrupt:
                raise

            except:
                _err = sys.exc_info()
                logger.error(str(_err[0]).split("'")[1] + ": " + str(_err[1]))

        raise errors.AFTDeviceError("Could not set the device in service mode")