Пример #1
0
    def _do_inject_ssh_key(self):
        """
        Inject ssh key into the mounted virtual hard drive
        """
        logger.info("Injecting ssh key")
        source_file = os.path.join(self._MODULE_DATA_PATH,
                                   self._HARNESS_AUTHORIZED_KEYS_FILE)

        ssh_path = os.path.join(
            os.curdir,
            self._MOUNT_DIRECTORY, "home", "root", ".ssh")

        ssh_file = os.path.join(ssh_path, "authorized_keys")

        logger.info("Injecting ssh key from '" + source_file + "' to '" +
                     ssh_file + "'")

        common.make_directory(ssh_path)
        shutil.copy(source_file, ssh_file)

        sha1sum = misc.local_execute(("sha1sum " +
                ssh_file).split())

        sha1sum = sha1sum.split()[0] # discard the file path

        logger.info("Adding IMA attribute to the ssh-key")

        # The setfattr 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.

        # The script also validates that the ssh_file path is at least somewhat
        # sane. This should be taken account if file or directory names are
        # changed

        # Note: Assumes that this file is under aft/devices, and that the shell
        # script is under aft/tools
        setfattr_script = os.path.join(os.path.dirname(__file__), os.path.pardir,
                                     "tools", "setfattr_script.sh")

        misc.local_execute(
            [
                "sudo",
                setfattr_script,
                "0x01" + sha1sum + " ",
                ssh_file
            ])


        logger.info("Fixing ownership and permissions")
        # ensure .ssh directory and authorized key file is owned by root
        os.chown(ssh_path, 0, 0)
        os.chown(ssh_file, 0, 0)

        # and ensure the permissions are correct
        # Note: incompatibility with Python 3 in chmod octal numbers
        os.chmod(ssh_path, 0700)
        os.chmod(ssh_file, 0600)
Пример #2
0
    def _send_command(self, power_status):
        """
        Either turns power on or off. Retries on failure up to self._RETRIES
        times.

        Args:
            power_status (string):
                Either "0", or "1" to turn power off and on respectively

        Returns:
            None

        Raises:
            subprocess32.CalledProcessError or subprocess32.TimeoutExpired
            on failure
        """
        error = ""
        for _ in range(self._RETRIES):
            try:
                misc.local_execute([
                    "clewarecontrol", "-d",
                    str(self._cutter_id), "-c", "1", "-as",
                    str(self._channel),
                    str(power_status)
                ])
            except (subprocess32.CalledProcessError,
                    subprocess32.TimeoutExpired) as err:
                error = err
                sleep(
                    random.randint(self._MIN_SLEEP_DURATION,
                                   self._MAX_SLEEP_DURATION))
            else:
                return

        raise error
Пример #3
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())
Пример #4
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")
Пример #5
0
    def _clear_dmesg(self):
        """
        Clears kernel message ring buffer

        Used before reading edison related information from the buffer to make
        sure any old Edison related messages do not disrupt configuration.
        """
        local_execute(["dmesg", "-C"])
Пример #6
0
    def _prepare_support_fs(self, root_tarball):
        """
        Create directories and copy all the necessary files to the support fs
        working directory.

        This is done before booting the support image, as the rootfs might be
        read only when accessed through nfs

        Args:
            root_tarball:
                The name of the root fs tarball

        Returns:
            None
        """
        # Note: need to remove the first '/' from file paths when building
        # absolute paths on the testing harness, as these paths are
        # absolute path intended for the support image operations (e.g. /usr/foo
        # rather than usr/foo, when we want to build
        # /path/to/nfs/path/to/rootfs/usr/foo)
        #
        # The need to remove the '/' is due to os.path.join behaviour, where it
        # will discard the current path string when encourtering an absolute
        # path

        logger.info("Creating directories and copying image files")

        local_execute([
            "mount", "-o", "loop,offset=1048576",
            "/root/support_image/support.img", "/root/support_fs/beaglebone/"
        ])

        common.make_directory(
            os.path.join(self.nfs_path, self.working_directory[1:]))
        common.make_directory(os.path.join(self.nfs_path, self.mount_dir[1:]))
        shutil.copy(os.path.join(self.parameters["mlo_file"]),
                    os.path.join(self.nfs_path, self.mlo_file[1:]))
        shutil.copy(os.path.join(self.parameters["u-boot_file"]),
                    os.path.join(self.nfs_path, self.u_boot_file[1:]))

        if "tar.bz2" in root_tarball:
            logger.info("Using command line arg for root tarball")
            shutil.copy(os.path.join(root_tarball),
                        os.path.join(self.nfs_path, self.root_tarball[1:]))
        else:
            logger.info("No tarball name passed - using default value")
            shutil.copy(self.parameters["root_tarball"],
                        os.path.join(self.nfs_path, self.root_tarball[1:]))

        shutil.copy(os.path.join(self.parameters["dtb_file"]),
                    os.path.join(self.nfs_path, self.dtb_file[1:]))
        ssh_file = os.path.join(os.path.dirname(__file__), 'data',
                                "authorized_keys")
        shutil.copy(ssh_file, os.path.join(self.nfs_path, self.ssh_file[1:]))

        local_execute(["umount", "/root/support_fs/beaglebone"])
Пример #7
0
    def _set_default_directory(self, directory):
        """
        Set VirtualBox default directory

        Args:
            directory: The new default VirtualBox VM directory

        """
        misc.local_execute(
            ("VBoxManage setproperty machinefolder " + directory + "").split())
Пример #8
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")
Пример #9
0
 def start_image_usb_emulation(self, args, leases_file):
     """
     Start using the image with USB mass storage emulation
     """
     if self.check_libcomposite_service_running():
         local_execute("systemctl stop libcomposite.service".split())
     self.free_dnsmasq_leases(leases_file)
     image_file = os.path.abspath(args.file_name)
     if not os.path.isfile(image_file):
         print("Image file doesn't exist")
         raise errors.AFTImageNameError("Image file doesn't exist")
     local_execute(("start_libcomposite " + image_file).split())
     logger.info("Started USB mass storage emulation using " + image_file)
Пример #10
0
Файл: ssh.py Проект: Valtis/AFT
def pull(remote_ip,
         source,
         destination,
         timeout=60,
         ignore_return_codes=None,
         user="******"):
    """
    Transmit a file from remote 'source' to local 'destination' over SCP

    Args:
        remote_ip (str): Remote device IP
        source (str): path to file on the remote filesystem
        destination (str): path to the file on local filesystem
        timeout (integer): Timeout in seconds for the operation
        ignore_return_codes (list(integer)):
            List of scp return codes that will be ignored
        user (str): User that will be used with scp


    Returns:
        Scp output on success

    Raises:
        subprocess32.TimeoutExpired:
            If timeout expired
        subprocess32.CalledProcessError:
            If process returns non-zero, non-ignored return code
    """
    scp_args = [
        "scp", "-o", "UserKnownHostsFile=/dev/null", "-o",
        "StrictHostKeyChecking=no", user + "@" + str(remote_ip) + ":" + source,
        destination
    ]
    return tools.local_execute(scp_args, timeout, ignore_return_codes)
Пример #11
0
    def _set_host_only_nic(self):
        """
        Set the nic into host only mode so that the local dnsmasq server
        can lease it the ip address

        Args:
            None
        Returns:
            None
        """
        misc.local_execute(
            ("VBoxManage modifyvm " + self._vm_name +
             " --nic1 hostonly").split())
        misc.local_execute(
            ("VBoxManage modifyvm " + self._vm_name + " --hostonlyadapter1 " +
             "vboxnet0").split())
Пример #12
0
    def _mount_virtual_drive(self):
        """
        Mount the VirtualBox virtual hard drive
        """
        # create mount folder
        common.make_directory(self._MOUNT_DIRECTORY)

        path = os.path.join(
            self._VM_DIRECTORY, self._vm_name,
            self._vhdd);
        logger.info("Mounting '" + path + "' with device '" + self._ROOTFS_DEVICE +
            "' into '" + self._MOUNT_DIRECTORY + "' for ssh key injection")

        misc.local_execute(
            ("guestmount -a " + path +" -m " + self._ROOTFS_DEVICE + " " +
             self._MOUNT_DIRECTORY + " -o allow_other").split())
Пример #13
0
Файл: ssh.py Проект: Valtis/AFT
def push(remote_ip, source, destination, timeout = 60, ignore_return_codes = None, user = "******"):
    """
    Transmit a file from local 'source' to remote 'destination' over SCP
    """
    scp_args = ["scp", source,
                user + "@" + str(remote_ip) + ":" + destination]
    return tools.local_execute(scp_args, timeout, ignore_return_codes)
Пример #14
0
def pull(remote_ip, source, destination,timeout = 60,
         ignore_return_codes = None, user = "******"):
    """
    Transmit a file from remote 'source' to local 'destination' over SCP

    Args:
        remote_ip (str): Remote device IP
        source (str): path to file on the remote filesystem
        destination (str): path to the file on local filesystem
        timeout (integer): Timeout in seconds for the operation
        ignore_return_codes (list(integer)):
            List of scp return codes that will be ignored
        user (str): User that will be used with scp

    Returns:
        Scp output on success

    Raises:
        subprocess32.TimeoutExpired:
            If timeout expired
        subprocess32.CalledProcessError:
            If process returns non-zero, non-ignored return code
    """
    scp_args = [
        "scp",
        "-o",
        "UserKnownHostsFile=/dev/null",
        "-o",
        "StrictHostKeyChecking=no",
        user + "@" + str(remote_ip) + ":" + source,
        destination]
    return tools.local_execute(scp_args, timeout, ignore_return_codes)
Пример #15
0
Файл: ssh.py Проект: Valtis/AFT
def remote_execute(remote_ip, command, timeout = 60, ignore_return_codes = None,
                   user = "******", connect_timeout = 15):
    """
    Execute a Bash command over ssh on a remote device with IP 'remote_ip'.
    Returns combines stdout and stderr if there are no errors. On error raises
    subprocess32 errors.
    """

    ssh_args = ["ssh",
                "-i", "".join([os.path.expanduser("~"), "/.ssh/id_rsa_testing_harness"]),
                "-o", "UserKnownHostsFile=/dev/null",
                "-o", "StrictHostKeyChecking=no",
                "-o", "BatchMode=yes",
                "-o", "LogLevel=ERROR",
                "-o", "ConnectTimeout=" + str(connect_timeout),
                user + "@" + str(remote_ip),
                _get_proxy_settings(),]

    logger.info("Executing " + " ".join(command), filename="ssh.log")

    ret = ""
    try:
        ret = tools.local_execute(ssh_args + command, timeout, ignore_return_codes)
    except subprocess32.CalledProcessError as err:
        logger.error("Command raised exception: " + str(err), filename="ssh.log")
        logger.error("Output: " + str(err.output), filename="ssh.log")
        raise err

    return ret
Пример #16
0
def push(remote_ip, source, destination, timeout = 60, ignore_return_codes = None, user = "******"):
    """
    Transmit a file from local 'source' to remote 'destination' over SCP
    """
    scp_args = ["scp", source,
                user + "@" + str(remote_ip) + ":" + destination]
    return tools.local_execute(scp_args, timeout, ignore_return_codes)
Пример #17
0
    def get_available_cutters():
        """
            Returns list of available cutters

            Returns:
                List of dictionaries with the following format:
                {
                    "type": "cleware",
                    "cutter": (int) cleware_cutter_id
                    "sockets": (int) number_of_sockets
                }
        """

        ids_to_sockets = {}
        ids_to_sockets["512"] = 4
        ids_to_sockets["29"] = 4
        ids_to_sockets["51"] = 1

        output = misc.local_execute(["clewarecontrol", "-l"])
        output = output.split("\n")

        cutter_arrays = [line.split(",") for line in output if "Device: " in line]

        cutter_values = [(line[2].strip().split(" ")[1], line[3].strip().split(" ")[2])
            for line in cutter_arrays]

        cutters = []
        for val in cutter_values:
            cutters.append({
                "type": "cleware",
                "cutter": int(val[1]),
                "sockets": ids_to_sockets[val[0]]
            })

        return cutters
Пример #18
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
Пример #19
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?")
Пример #20
0
 def check_libcomposite_service_running(self):
     """
     Check if libcomposite.service is running. Return 1 if running, else 0
     """
     try:
         out = local_execute(
             "systemctl status libcomposite.service".split())
         if "Active: active" in out:
             return 1
         return 0
     except:
         return 0
Пример #21
0
    def _send_command(self, power_status):
        """
        Either turns power on or off. Retries on failure up to self._RETRIES
        times.

        Args:
            power_status (string):
                Either "0", or "1" to turn power off and on respectively

        Returns:
            None

        Raises:
            subprocess32.CalledProcessError or subprocess32.TimeoutExpired
            on failure
        """
        error = ""
        for _ in range(self._RETRIES):
            try:
                misc.local_execute(
                    [
                        "clewarecontrol",
                        "-d",
                        str(self._cutter_id),
                        "-c",
                        "1",
                        "-as",
                        str(self._channel),
                        str(power_status)
                    ])
            except (subprocess32.CalledProcessError,
                    subprocess32.TimeoutExpired) as err:
                error = err
                sleep(
                    random.randint(
                        self._MIN_SLEEP_DURATION, self._MAX_SLEEP_DURATION))
            else:
                return

        raise error
Пример #22
0
def remote_execute(remote_ip, command, timeout = 60, ignore_return_codes = None,
                   user = "******", connect_timeout = 15):
    """
    Execute a Bash command over ssh on a remote device with IP 'remote_ip'.
    Returns combines stdout and stderr if there are no errors. On error raises
    subprocess32 errors.
    """
    ssh_args = ["ssh",
                "-i", "".join([os.path.expanduser("~"), "/.ssh/id_rsa_testing_harness"]),
                "-o", "UserKnownHostsFile=/dev/null",
                "-o", "StrictHostKeyChecking=no",
                "-o", "BatchMode=yes",
                "-o", "LogLevel=ERROR",
                "-o", "ConnectTimeout=" + str(connect_timeout),
                user + "@" + str(remote_ip),
                _get_proxy_settings(),]

    return tools.local_execute(ssh_args + command, timeout, ignore_return_codes)
Пример #23
0
Файл: ssh.py Проект: Valtis/AFT
def remote_execute(remote_ip,
                   command,
                   timeout=60,
                   ignore_return_codes=None,
                   user="******",
                   connect_timeout=15):
    """
    Execute a Bash command over ssh on a remote device with IP 'remote_ip'.
    Returns combines stdout and stderr if there are no errors. On error raises
    subprocess32 errors.
    """

    ssh_args = [
        "ssh",
        "-i",
        "".join([os.path.expanduser("~"), "/.ssh/id_rsa_testing_harness"]),
        "-o",
        "UserKnownHostsFile=/dev/null",
        "-o",
        "StrictHostKeyChecking=no",
        "-o",
        "BatchMode=yes",
        "-o",
        "LogLevel=ERROR",
        "-o",
        "ConnectTimeout=" + str(connect_timeout),
        user + "@" + str(remote_ip),
        _get_proxy_settings(),
    ]

    logger.info("Executing " + " ".join(command), filename="ssh.log")

    ret = ""
    try:
        ret = tools.local_execute(ssh_args + command, timeout,
                                  ignore_return_codes)
    except subprocess32.CalledProcessError as err:
        logger.error("Command raised exception: " + str(err),
                     filename="ssh.log")
        logger.error("Output: " + str(err.output), filename="ssh.log")
        raise err

    return ret
Пример #24
0
    def get_available_cutters():
        """
            Returns list of available cutters

            Returns:
                List of dictionaries with the following format:
                {
                    "type": "cleware",
                    "cutter": (int) cleware_cutter_id
                    "sockets": (int) number_of_sockets
                }
        """

        ids_to_sockets = {}
        ids_to_sockets["512"] = 4
        ids_to_sockets["29"] = 4
        ids_to_sockets["51"] = 1

        output = misc.local_execute(["clewarecontrol", "-l"])
        output = output.split("\n")

        cutter_arrays = [
            line.split(",") for line in output if "Device: " in line
        ]

        cutter_values = [(line[2].strip().split(" ")[1],
                          line[3].strip().split(" ")[2])
                         for line in cutter_arrays]

        cutters = []
        for val in cutter_values:
            cutters.append({
                "type": "cleware",
                "cutter": int(val[1]),
                "sockets": ids_to_sockets[val[0]]
            })

        return cutters
Пример #25
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")
Пример #26
0
    def _get_edison_configs(self):
        """
        Return list of Edison networking configurations.

        Returns:
            List of Edison networking configurations. Configurations are tuples
            with the following format:
            (
                "usb_device_tree_path",
                "host_interface_ip",
                "edison_network_subnet_ip"
            )
        """
        def connection_opener(queue, subnet_ip, line):
            """
            Helper function for opening Edison network interface

            Args:
                queue (multiprocessing.Queue):
                    Queue used to communicate results back to the main thread.

                subnet_ip (integer): The network subnet assigned for this device

                line (str): Line from dmesg log that contains Edison device
                            registration notification and the usb tree path.

                            Example:
                                [328860.109597] usb 2-1.4.1.2: Product: Edison
            """

            # [:-1]: need to remove ':' from the end
            usb_port = line.split(" ")[2][:-1]

            args = {}
            # Device class constructor expects these keys to be found
            # Probably should extract networking code from EdisonDevice so that
            # this hack\workaround wouldn't be needed

            ### DUMMY DATA START ###
            args["name"] = "dummy"
            args["model"] = "dummy"
            args["id"] = "dummy"
            args["test_plan"] = "dummy"
            ### DUMMY DATA END ###

            args["network_subnet"] = self._config["edison"]["subnet_prefix"] + \
                str(subnet_ip)

            args["edison_usb_port"] = usb_port

            dev = EdisonDevice(args, None)
            dev.open_interface()

            # we do something slightly different here when compared to the
            # PC-like devices: we return the ip address to the usb network
            # interface on the host. We then ping this address instead when
            # detecting if network is still up. This interface disappears when
            # the edison powers down, so we can associate edison configuration
            # data. This also means that edison does not actually need a valid
            # operating system present

            queue.put((usb_port, dev.get_host_ip(), args["network_subnet"]))

        # Makes assumptions regarding dmesg message format. Might be fragile
        dmesg_lines = local_execute("dmesg").split("\n")
        edison_lines = [line for line in dmesg_lines if "Edison" in line]

        ip_addresses = []
        ip_queue = Queue()
        processes = []

        ip = int(self._config["edison"]["ip_start"])

        for line in edison_lines:
            p = Process(target=connection_opener, args=(ip_queue, ip, line))
            p.start()
            processes.append(p)
            ip += 4

        for p in processes:
            p.join()
            ip_addresses.append(ip_queue.get())

        return ip_addresses
Пример #27
0
 def _unmount_virtual_drive(self):
     logger.info("Unmounting virtual hard drive")
     """
     Unmount the VirtualBox virtual hard drive
     """
     misc.local_execute(("guestunmount " + self._MOUNT_DIRECTORY).split())
Пример #28
0
 def _unregister_vm(self):
     logger.info("Unregistering the vm")
     if self._vm_name == None:
         return
     misc.local_execute(("VBoxManage unregistervm " + self._vm_name).split())