示例#1
0
def setup_tests(options):
    """
    Load and instantiate all client tests.

    This function is inspired from runtest() on client/shared/test.py.

    :param options: an object passed in from command line OptionParser.
                    See all options defined on client/autotest.
    """

    assert options.client_test_setup, 'Specify prebuild client tests on the ' \
                                      'command line.'

    requested_tests = options.client_test_setup.split(',')
    candidates, broken_tests = load_all_client_tests(options)

    failed_tests = []
    if 'all' in requested_tests:
        need_to_setup = candidates
        failed_tests += broken_tests
    else:
        need_to_setup = []
        for candidate in candidates:
            if candidate.__class__.__name__ in requested_tests:
                need_to_setup.append(candidate)
        for broken_test in broken_tests:
            if broken_test in requested_tests:
                failed_tests.append(broken_test)

    if need_to_setup:
        cwd = os.getcwd()
        os.chdir(need_to_setup[0].job.clientdir)
        os.system('tools/make_clean')
        os.chdir(cwd)
    elif not failed_tests:
        logging.error('### No test setup candidates ###')
        raise error.AutoservError('No test setup candidates.')

    for client_test in need_to_setup:
        good_setup = setup_test(client_test)
        if not good_setup:
            failed_tests.append(client_test.__class__.__name__)

    logging.info('############################# SUMMARY '
                 '#############################')

    # Print out tests that failed
    if failed_tests:
        logging.info('Finished setup -- The following tests failed')
        for failed_test in failed_tests:
            logging.info(failed_test)
    else:
        logging.info('Finished setup -- All tests built successfully')
    logging.info('######################### END SUMMARY '
                 '##############################')
    if failed_tests:
        raise error.AutoservError('Finished setup with errors.')
示例#2
0
    def install(self,
                host,
                label='autotest',
                default=False,
                kernel_args='',
                install_vmlinux=True):
        """
        Install a kernel on the remote host.

        This will also invoke the guest's bootloader to set this
        kernel as the default kernel if default=True.

        Args:
                host: the host on which to install the kernel
                [kwargs]: remaining keyword arguments will be passed
                        to Bootloader.add_kernel()

        Raises:
                AutoservError: no package has yet been obtained. Call
                        RPMKernel.get() with a .rpm package.
        """
        if len(label) > 15:
            raise error.AutoservError("label for kernel is too long \
            (> 15 chars): %s" % label)
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be \
            specified via get()")
        rpm = self.source_material

        remote_tmpdir = host.get_tmp_dir()
        remote_rpm = os.path.join(remote_tmpdir, os.path.basename(rpm))
        rpm_package = utils.run('/usr/bin/rpm -q -p %s' % rpm).stdout
        vmlinuz = self.get_image_name()
        host.send_file(rpm, remote_rpm)
        host.run('rpm -e ' + rpm_package, ignore_status=True)
        host.run('rpm --force -i ' + remote_rpm)

        # Copy over the uncompressed image if there is one
        if install_vmlinux:
            vmlinux = self.get_vmlinux_name()
            host.run('cd /;rpm2cpio %s | cpio -imuv .%s' %
                     (remote_rpm, vmlinux))
            host.run('ls ' + vmlinux)  # Verify

        host.bootloader.remove_kernel(label)
        host.bootloader.add_kernel(vmlinuz,
                                   label,
                                   args=kernel_args,
                                   default=default)
        if kernel_args:
            host.bootloader.add_args(label, kernel_args)
        if not default:
            host.bootloader.boot_once(label)
    def install(self, host, **kwargs):
        """
        Install a kernel on the remote host.

        This will also invoke the guest's bootloader to set this
        kernel as the default kernel.

        Args:
                host: the host on which to install the kernel
                [kwargs]: remaining keyword arguments will be passed
                        to Bootloader.add_kernel()

        Raises:
                AutoservError: no package has yet been obtained. Call
                        DEBKernel.get() with a .deb package.
        """
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be "
                                      "specified via get()")

        remote_tmpdir = host.get_tmp_dir()
        basename = os.path.basename(self.source_material)
        remote_filename = os.path.join(remote_tmpdir, basename)
        host.send_file(self.source_material, remote_filename)
        host.run('dpkg -i "%s"' % (utils.sh_escape(remote_filename), ))
        host.run('mkinitramfs -o "%s" "%s"' % (
            utils.sh_escape(self.get_initrd_name()),
            utils.sh_escape(self.get_version()),
        ))

        host.bootloader.add_kernel(self.get_image_name(),
                                   initrd=self.get_initrd_name(),
                                   **kwargs)
    def extract(self, host):
        """Extract the kernel package.

        This function is only useful to access the content of the
        package (for example the kernel image) without
        installing it. It is not necessary to run this function to
        install the kernel.

        Args:
                host: the host on which to extract the kernel package.

        Returns:
                The full path to the temporary directory on host where
                the package was extracted.

        Raises:
                AutoservError: no package has yet been obtained. Call
                        DEBKernel.get() with a .deb package.
        """
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be "
                                      "specified via get()")

        remote_tmpdir = host.get_tmp_dir()
        basename = os.path.basename(self.source_material)
        remote_filename = os.path.join(remote_tmpdir, basename)
        host.send_file(self.source_material, remote_filename)
        content_dir = os.path.join(remote_tmpdir, "contents")
        host.run('dpkg -x "%s" "%s"' % (
            utils.sh_escape(remote_filename),
            utils.sh_escape(content_dir),
        ))

        return content_dir
示例#5
0
    def repair(self, host_protection):
        if not self.machines:
            raise error.AutoservError('No machines specified to repair')
        if self.resultdir:
            os.chdir(self.resultdir)
        namespace = {'machines': self.machines, 'job': self,
                     'ssh_user': self._ssh_user, 'ssh_port': self._ssh_port,
                     'ssh_pass': self._ssh_pass,
                     'protection_level': host_protection}

        self._execute_code(REPAIR_CONTROL_FILE, namespace, protect=False)
示例#6
0
 def _install_boottool(self):
     '''
     Installs boottool on the host
     '''
     if self._host() is None:
         raise error.AutoservError(
             "Host does not exist anymore")
     tmpdir = self._host().get_tmp_dir()
     self._host().send_file(os.path.abspath(os.path.join(
         utils.get_server_dir(), BOOTTOOL_CLI_PATH)), tmpdir)
     self._boottool_path = os.path.join(tmpdir,
                                        os.path.basename(BOOTTOOL_CLI_PATH))
示例#7
0
 def verify(self):
     if not self.machines:
         raise error.AutoservError('No machines specified to verify')
     if self.resultdir:
         os.chdir(self.resultdir)
     try:
         namespace = {'machines' : self.machines, 'job' : self,
                      'ssh_user' : self._ssh_user,
                      'ssh_port' : self._ssh_port,
                      'ssh_pass' : self._ssh_pass}
         self._execute_code(VERIFY_CONTROL_FILE, namespace, protect=False)
     except Exception, e:
         msg = ('Verify failed\n' + str(e) + '\n' + traceback.format_exc())
         self.record('ABORT', None, None, msg)
         raise
    def get_initrd_name(self):
        """Get the name of the initrd file to be installed.

        Returns:
                The full path to the initrd file as it will be
                installed on the host. If the package includes no
                initrd file, None is returned

        Raises:
                AutoservError: no package has yet been obtained. Call
                        DEBKernel.get() with a .deb package.
        """
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be "
                                      "specified via get()")

        return "/boot/initrd.img-%s" % (self.get_version(), )
示例#9
0
        def _import_names(module_name, names=()):
            """
            Import a module and assign named attributes into namespace.

            Args:
                module_name: The string module name.
                names: A limiting list of names to import from module_name.  If
                    empty (the default), all names are imported from the module
                    similar to a "from foo.bar import *" statement.
            Raises:
                error.AutoservError: When a name being imported would clobber
                    a name already in namespace.
            """
            module = __import__(module_name, {}, {}, names)

            # No names supplied?  Import * from the lowest level module.
            # (Ugh, why do I have to implement this part myself?)
            if not names:
                for submodule_name in module_name.split('.')[1:]:
                    module = getattr(module, submodule_name)
                if hasattr(module, '__all__'):
                    names = getattr(module, '__all__')
                else:
                    names = dir(module)

            # Install each name into namespace, checking to make sure it
            # doesn't override anything that already exists.
            for name in names:
                # Check for conflicts to help prevent future problems.
                if name in namespace and protect:
                    if namespace[name] is not getattr(module, name):
                        raise error.AutoservError(
                            'importing name '
                            '%s from %s %r would override %r' %
                            (name, module_name, getattr(
                                module, name), namespace[name]))
                    else:
                        # Encourage cleanliness and the use of __all__ for a
                        # more concrete API with less surprises on '*' imports.
                        warnings.warn('%s (%r) being imported from %s for use '
                                      'in server control files is not the '
                                      'first occurrence of that import.' %
                                      (name, namespace[name], module_name))

                namespace[name] = getattr(module, name)
示例#10
0
    def get_version(self):
        """Get the version of the kernel to be installed.

        Returns:
                The version string, as would be returned
                by 'make kernelrelease'.

        Raises:
                AutoservError: no package has yet been obtained. Call
                        DEBKernel.get() with a .deb package.
        """
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be "
                                      "specified via get()")

        retval = utils.run('dpkg-deb -f "%s" version' %
                           utils.sh_escape(self.source_material),)
        return retval.stdout.strip()
示例#11
0
    def get_image_name(self):
        """Get the name of the kernel image to be installed.

        Returns:
                The full path to the kernel image file as it will be
                installed on the host.

        Raises:
                AutoservError: no package has yet been obtained. Call
                        RPMKernel.get() with a .rpm package.
        """
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be \
            specified via get()")

        vmlinuz = utils.run('rpm -q -l -p %s | grep /boot/vmlinuz' %
                            self.source_material).stdout.strip()
        return vmlinuz
示例#12
0
    def get_version(self):
        """Get the version of the kernel to be installed.

        Returns:
                The version string, as would be returned
                by 'make kernelrelease'.

        Raises:
                AutoservError: no package has yet been obtained. Call
                        RPMKernel.get() with a .rpm package.
        """
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be \
            specified via get()")

        retval = utils.run(
            'rpm -qpi %s | grep Version | awk \'{print($3);}\'' %
            utils.sh_escape(self.source_material))
        return retval.stdout.strip()
示例#13
0
def parallel(tasklist, timeout=None, return_results=False):
    """
    Run a set of predefined subcommands in parallel.

    :param tasklist: A list of subcommand instances to execute.
    :param timeout: Number of seconds after which the commands should timeout.
    :param return_results: If True instead of an AutoServError being raised
            on any error a list of the results|exceptions from the tasks is
            returned.  [default: False]
    """
    run_error = False
    for task in tasklist:
        task.fork_start()

    remaining_timeout = None
    if timeout:
        endtime = time.time() + timeout

    results = []
    for task in tasklist:
        if timeout:
            remaining_timeout = max(endtime - time.time(), 1)
        try:
            status = task.fork_waitfor(timeout=remaining_timeout)
        except error.AutoservSubcommandError:
            run_error = True
        else:
            if status != 0:
                run_error = True

        results.append(pickle.load(task.result_pickle))
        task.result_pickle.close()

    if return_results:
        return results
    elif run_error:
        message = 'One or more subcommands failed:\n'
        for task, result in zip(tasklist, results):
            message += 'task: %s returned/raised: %r\n' % (task, result)
        raise error.AutoservError(message)
示例#14
0
    def get_initrd_name(self):
        """Get the name of the initrd file to be installed.

        Returns:
                The full path to the initrd file as it will be
                installed on the host. If the package includes no
                initrd file, None is returned

        Raises:
                AutoservError: no package has yet been obtained. Call
                        RPMKernel.get() with a .rpm package.
        """
        if self.source_material is None:
            raise error.AutoservError("A kernel must first be \
            specified via get()")

        res = utils.run('rpm -q -l -p %s | grep /boot/initrd' %
                        self.source_material,
                        ignore_status=True)
        if res.exit_status:
            return None
        return res.stdout.strip()
示例#15
0
def setup_test(client_test):
    """
    Direct invoke test.setup() method.

    :return: A boolean to represent success or not.
    """

    # TODO: check if its already build. .version? hash?
    test_name = client_test.__class__.__name__
    cwd = os.getcwd()
    good_setup = False
    try:
        try:
            outputdir = os.path.join(client_test.job.resultdir, test_name)
            try:
                os.makedirs(outputdir)
                os.chdir(outputdir)
            except OSError:
                pass
            logging.info('setup %s.' % test_name)
            client_test.setup()

            # Touch .version file under src to prevent further setup on client
            # host. See client/shared/utils.py update_version()
            if os.path.exists(client_test.srcdir):
                versionfile = os.path.join(client_test.srcdir, '.version')
                pickle.dump(client_test.version, open(versionfile, 'w'))
            good_setup = True
        except Exception as err:
            logging.error(err)
            raise error.AutoservError('Failed to build client test %s on '
                                      'server.' % test_name)
    finally:
        # back to original working dir
        os.chdir(cwd)
    return good_setup
示例#16
0
def create_host(hostname,
                auto_monitor=True,
                follow_paths=None,
                pattern_paths=None,
                netconsole=False,
                **args):
    # parse out the profile up-front, if it's there, or else console monitoring
    # will not work
    # Here, ssh_user, ssh_pass and ssh_port are injected in the namespace
    # pylint: disable=E0602
    hostname, args['user'], args['password'], args['port'], args['profile'] = (
        server_utils.parse_machine(hostname, ssh_user, ssh_pass,
                                   ssh_port))  # @UndefinedVariable

    # by default assume we're using SSH support
    if SSH_ENGINE == 'paramiko':
        from autotest.server.hosts import paramiko_host
        classes = [paramiko_host.ParamikoHost]
    elif SSH_ENGINE == 'raw_ssh':
        classes = [ssh_host.SSHHost, ssh_host.AsyncSSHMixin]
    else:
        raise error.AutoservError(
            "Unknown SSH engine %s. Please verify the "
            "value of the configuration key 'ssh_engine' "
            "on autotest's global_config.ini file." % SSH_ENGINE)

    # by default mix in run_test support
    classes.append(autotest_remote.AutotestHostMixin)

    # if the user really wants to use netconsole, let them
    if netconsole:
        classes.append(netconsole.NetconsoleHost)

    if auto_monitor:
        # use serial console support if it's available
        conmux_args = {}
        for key in ("conmux_server", "conmux_attach"):
            if key in args:
                conmux_args[key] = args[key]
        if serial.SerialHost.host_is_supported(hostname, **conmux_args):
            classes.append(serial.SerialHost)
        else:
            # no serial available, fall back to direct dmesg logging
            if follow_paths is None:
                follow_paths = [DEFAULT_FOLLOW_PATH]
            else:
                follow_paths = list(follow_paths) + [DEFAULT_FOLLOW_PATH]

            if pattern_paths is None:
                pattern_paths = [DEFAULT_PATTERNS_PATH]
            else:
                pattern_paths = (list(pattern_paths) + [DEFAULT_PATTERNS_PATH])

            logfile_monitor_class = logfile_monitor.NewLogfileMonitorMixin(
                follow_paths, pattern_paths)
            classes.append(logfile_monitor_class)

    elif follow_paths:
        logfile_monitor_class = logfile_monitor.NewLogfileMonitorMixin(
            follow_paths, pattern_paths)
        classes.append(logfile_monitor_class)

    # do any site-specific processing of the classes list
    site_factory.postprocess_classes(classes,
                                     hostname,
                                     auto_monitor=auto_monitor,
                                     **args)

    # create a custom host class for this machine and return an instance of it
    host_class = type("%s_host" % hostname, tuple(classes), {})
    host_instance = host_class(hostname, **args)

    # call job_start if this is the first time this host is being used
    if hostname not in _started_hostnames:
        host_instance.job_start()
        _started_hostnames.add(hostname)

    return host_instance
示例#17
0
    def _install(self, host=None, autodir=None, use_autoserv=True,
                 use_packaging=True):
        """
        Install autotest.

        :param host A Host instance on which autotest will be installed
        :param autodir Location on the remote host to install to
        :param use_autoserv Enable install modes that depend on the client
            running with the autoserv harness
        :param use_packaging Enable install modes that use the packaging system

        @exception AutoservError If it wasn't possible to install the client
                after trying all available methods
        """
        if not host:
            host = self.host
        if not self.got:
            self.get()
        host.wait_up(timeout=30)
        host.setup()
        logging.info("Installing autotest on %s", host.hostname)

        if self.server_system_wide_install:
            msg_install = ("Autotest seems to be installed in the "
                           "client on a system wide location, proceeding...")

            logging.info("Verifying client package install")
            if _client_system_wide_install(host):
                logging.info(msg_install)
                self.installed = True
                return

            install_cmd = INSTALL_CLIENT_CMD_MAPPING.get(self.os_vendor, None)
            if install_cmd is not None:
                logging.info(msg_install)
                host.run(install_cmd)
                if _client_system_wide_install(host):
                    logging.info("Autotest seems to be installed in the "
                                 "client on a system wide location, proceeding...")
                    self.installed = True
                    return

            raise error.AutoservError("The autotest client package "
                                      "does not seem to be installed "
                                      "on %s" % host.hostname)

        # set up the autotest directory on the remote machine
        if not autodir:
            autodir = self.get_install_dir(host)
        logging.info('Using installation dir %s', autodir)
        host.set_autodir(autodir)
        host.run('mkdir -p %s' % utils.sh_escape(autodir))

        # make sure there are no files in $AUTODIR/results
        results_path = os.path.join(autodir, 'results')
        host.run('rm -rf %s/*' % utils.sh_escape(results_path),
                 ignore_status=True)

        # Fetch the autotest client from the nearest repository
        if use_packaging:
            try:
                self._install_using_packaging(host, autodir)
                self._create_test_output_dir(host, autodir)
                logging.info("Installation of autotest completed")
                self.installed = True
                return
            except (error.PackageInstallError, error.AutoservRunError,
                    SettingsError), e:
                logging.info("Could not install autotest using the packaging "
                             "system: %s. Trying other methods", e)
示例#18
0
class BaseAutotest(installable_object.InstallableObject):
    """
    This class represents the Autotest program.

    Autotest is used to run tests automatically and collect the results.
    It also supports profilers.

    Implementation details:
    This is a leaf class in an abstract class hierarchy, it must
    implement the unimplemented methods in parent classes.
    """
    def __init__(self, host=None):
        self.host = host
        self.got = False
        self.installed = False
        self.serverdir = utils.get_server_dir()
        super(BaseAutotest, self).__init__()

    install_in_tmpdir = False

    @classmethod
    def set_install_in_tmpdir(cls, flag):
        """
        Sets a flag that controls whether or not Autotest should by
        default be installed in a "standard" directory (e.g. /home/autotest) or
        a temporary directory.
        """
        cls.install_in_tmpdir = flag

    @classmethod
    def get_client_autodir_paths(cls, host):
        return global_config.global_config.get_config_value(
            'AUTOSERV', 'client_autodir_paths', type=list)

    @classmethod
    def get_installed_autodir(cls, host):
        """
        Find where the Autotest client is installed on the host.
        @returns an absolute path to an installed Autotest client root.
        @raises AutodirNotFoundError if no Autotest installation can be found.
        """
        autodir = host.get_autodir()
        if autodir:
            logging.debug('Using existing host autodir: %s', autodir)
            return autodir

        for path in Autotest.get_client_autodir_paths(host):
            try:
                autotest_binary = os.path.join(path, 'autotest')
                host.run('test -x %s' % utils.sh_escape(autotest_binary))
                host.run('test -w %s' % utils.sh_escape(path))
                logging.debug('Found existing autodir at %s', path)
                return path
            except error.AutoservRunError:
                logging.debug('%s does not exist on %s', autotest_binary,
                              host.hostname)
        raise AutodirNotFoundError

    @classmethod
    def get_install_dir(cls, host):
        """
        Determines the location where autotest should be installed on
        host. If self.install_in_tmpdir is set, it will return a unique
        temporary directory that autotest can be installed in. Otherwise, looks
        for an existing installation to use; if none is found, looks for a
        usable directory in the global config client_autodir_paths.
        """
        try:
            install_dir = cls.get_installed_autodir(host)
        except AutodirNotFoundError:
            install_dir = cls._find_installable_dir(host)

        if cls.install_in_tmpdir:
            return host.get_tmp_dir(parent=install_dir)
        return install_dir

    @classmethod
    def _find_installable_dir(cls, host):
        client_autodir_paths = cls.get_client_autodir_paths(host)
        for path in client_autodir_paths:
            try:
                host.run('mkdir -p %s' % utils.sh_escape(path))
                host.run('test -w %s' % utils.sh_escape(path))
                return path
            except error.AutoservRunError:
                logging.debug('Failed to create %s', path)
        raise error.AutoservInstallError(
            'Unable to find a place to install Autotest; tried %s' %
            ', '.join(client_autodir_paths))

    def _create_test_output_dir(self, host, autodir):
        tmpdir = os.path.join(autodir, 'tmp')
        state_autodir = global_config.global_config.get_config_value(
            'COMMON', 'test_output_dir', default=tmpdir)
        host.run('mkdir -p %s' % utils.sh_escape(state_autodir))

    def get_fetch_location(self):
        c = global_config.global_config
        repos = c.get_config_value("PACKAGES",
                                   'fetch_location',
                                   type=list,
                                   default=[])
        repos.reverse()
        return repos

    def install(self, host=None, autodir=None):
        self._install(host=host, autodir=autodir)

    def install_full_client(self, host=None, autodir=None):
        self._install(host=host,
                      autodir=autodir,
                      use_autoserv=False,
                      use_packaging=False)

    def install_no_autoserv(self, host=None, autodir=None):
        self._install(host=host, autodir=autodir, use_autoserv=False)

    def _install_using_packaging(self, host, autodir):
        repos = self.get_fetch_location()
        if not repos:
            raise error.PackageInstallError("No repos to install an "
                                            "autotest client from")
        pkgmgr = packages.PackageManager(autodir,
                                         hostname=host.hostname,
                                         repo_urls=repos,
                                         do_locking=False,
                                         run_function=host.run,
                                         run_function_dargs=dict(timeout=600))
        # The packages dir is used to store all the packages that
        # are fetched on that client. (for the tests,deps etc.
        # too apart from the client)
        pkg_dir = os.path.join(autodir, 'packages')
        # clean up the autodir except for the packages directory
        host.run('cd %s && ls | grep -v "^packages$"'
                 ' | xargs rm -rf && rm -rf .[^.]*' % autodir)
        pkgmgr.install_pkg('autotest',
                           'client',
                           pkg_dir,
                           autodir,
                           preserve_install_dir=True)
        self._create_test_output_dir(host, autodir)
        logging.info("Installation of autotest completed")
        self.installed = True

    def _install_using_send_file(self, host, autodir):
        dirs_to_exclude = set(["tests", "site_tests", "deps", "profilers"])
        light_files = [
            os.path.join(self.source_material, f)
            for f in os.listdir(self.source_material)
            if f not in dirs_to_exclude
        ]

        # there should be one and only one grubby tarball
        grubby_glob = os.path.join(self.source_material,
                                   "deps/grubby/grubby-*.tar.bz2")
        grubby_tarball_paths = glob.glob(grubby_glob)
        if grubby_tarball_paths:
            grubby_tarball_path = grubby_tarball_paths[0]
            if os.path.exists(grubby_tarball_path):
                light_files.append(grubby_tarball_path)

        host.send_file(light_files, autodir, delete_dest=True)

        profilers_autodir = os.path.join(autodir, 'profilers')
        profilers_init = os.path.join(self.source_material, 'profilers',
                                      '__init__.py')
        host.run("mkdir -p %s" % profilers_autodir)
        host.send_file(profilers_init, profilers_autodir, delete_dest=True)
        dirs_to_exclude.discard("profilers")

        # create empty dirs for all the stuff we excluded
        commands = []
        for path in dirs_to_exclude:
            abs_path = os.path.join(autodir, path)
            abs_path = utils.sh_escape(abs_path)
            commands.append("mkdir -p '%s'" % abs_path)
            commands.append("touch '%s'/__init__.py" % abs_path)
        host.run(';'.join(commands))

    def _install(self,
                 host=None,
                 autodir=None,
                 use_autoserv=True,
                 use_packaging=True):
        """
        Install autotest.  If get() was not called previously, an
        attempt will be made to install from the autotest svn
        repository.

        @param host A Host instance on which autotest will be installed
        @param autodir Location on the remote host to install to
        @param use_autoserv Enable install modes that depend on the client
            running with the autoserv harness
        @param use_packaging Enable install modes that use the packaging system

        @exception AutoservError If it wasn't possible to install the client
                after trying all available methods
        """
        if not host:
            host = self.host
        if not self.got:
            self.get()
        host.wait_up(timeout=30)
        host.setup()
        logging.info("Installing autotest on %s", host.hostname)

        # set up the autotest directory on the remote machine
        if not autodir:
            autodir = self.get_install_dir(host)
        logging.info('Using installation dir %s', autodir)
        host.set_autodir(autodir)
        host.run('mkdir -p %s' % utils.sh_escape(autodir))

        # make sure there are no files in $AUTODIR/results
        results_path = os.path.join(autodir, 'results')
        host.run('rm -rf %s/*' % utils.sh_escape(results_path),
                 ignore_status=True)

        # Fetch the autotest client from the nearest repository
        if use_packaging:
            try:
                self._install_using_packaging(host, autodir)
                self._create_test_output_dir(host, autodir)
                logging.info("Installation of autotest completed")
                self.installed = True
                return
            except (error.PackageInstallError, error.AutoservRunError,
                    global_config.ConfigError), e:
                logging.info(
                    "Could not install autotest using the packaging "
                    "system: %s. Trying other methods", e)

        # try to install from file or directory
        if self.source_material:
            c = global_config.global_config
            supports_autoserv_packaging = c.get_config_value(
                "PACKAGES", "serve_packages_from_autoserv", type=bool)
            # Copy autotest recursively
            if supports_autoserv_packaging and use_autoserv:
                self._install_using_send_file(host, autodir)
            else:
                host.send_file(self.source_material, autodir, delete_dest=True)
            self._create_test_output_dir(host, autodir)
            logging.info("Installation of autotest completed")
            self.installed = True
            return

        raise error.AutoservError('Could not install autotest on '
                                  'target machine: %s' % host.name)