@@ -4,7 +4,7 @@ import sys
import urllib
import re
import signal
-from datetime import *
+import datetime
from autotest_lib.client.bin import utils, test
from autotest_lib.client.common_lib import error
@@ -14,19 +14,85 @@ import kvm_utils
def run_kvm_install(test, params, env):
- install_mode = params.get("mode")
- kvm_log.info("Selected installation mode: %s" % install_mode)
+ """
+ Installs KVM using the selected install mode. Most install methods will
+ take kvm source code, build it and install it to a given location.
- srcdir = params.get("srcdir", test.srcdir)
- if not os.path.exists(srcdir):
- os.mkdir(srcdir)
+ @param test: kvm_runtest_2 test object
+ @param params: Dictionary with test parameters
+ @param env: Test environment
+ """
+ known_install_modes = ['noinstall', 'release', 'snapshot', 'git',
+ 'localtar', 'localsrc']
- # do not install
- if install_mode == "noinstall":
+ install_mode = params.get("mode")
+ srcdir = params.get("srcdir", test.srcdir)
+ params["srcdir"] = srcdir
+
+ if install_mode not in known_install_modes:
+ raise error.TestError("Invalid installation mode" % install_mode)
+
+ if not install_mode == 'noinstall':
+ kvm_log.info("Selected installation mode: %s" % install_mode)
+ build_dir = __get_kvm(params)
+ __build_kvm(build_dir)
+ __install_kvm(build_dir, install_mode, test.bindir)
+ __load_kvm_modules(build_dir)
+ kvm_log.info("Done building and installing KVM")
+ else:
kvm_log.info("Skipping installation")
- # install from git
- elif install_mode == "git":
+
+def __get_kvm(params):
+ """
+ Get KVM and returns a source code directory path.
+
+ @param params: Dictionary with all parameters passed to the
+ install test.
+ """
+ install_mode = params.get("mode")
+ srcdir = params.get("srcdir")
+ if not os.path.isdir(srcdir):
+ os.makedirs(srcdir)
+
+ if install_mode in ['release', 'snapshot', 'localtar']:
+ if install_mode == 'release':
+ release_tag = params.get("release_tag")
+ release_dir = params.get("release_dir")
+ kvm_log.info("Installing KVM from release tarball")
+ if not release_tag:
+ release_tag = kvm_utils.get_latest_kvm_release_tag(release_dir)
+ tarball = os.path.join(release_dir, "kvm-%s.tar.gz" % release_tag)
+ kvm_log.info("Retrieving release kvm-%s" % release_tag)
+ tarball = utils.unmap_url("/", tarball, "/tmp")
+ elif install_mode == 'snapshot':
+ kvm_log.info("Installing KVM from snapshot")
+ snapshot_date = params.get("snapshot_date")
+ snapshot_dir = params.get("snapshot_dir")
+ if not snapshot_date:
+ # Take yesterday's snapshot
+ d = (datetime.date.today() -
+ datetime.timedelta(1)).strftime("%Y%m%d")
+ else:
+ d = snapshot_date
+ tarball = os.path.join(snapshot_dir, "kvm-snapshot-%s.tar.gz" % d)
+ kvm_log.info("Retrieving kvm-snapshot-%s" % d)
+ tarball = utils.unmap_url("/", tarball, "/tmp")
+ elif install_mode == 'localtar':
+ tarball = params.get("tarball")
+ if not tarball:
+ raise error.TestError("KVM Tarball install specified but no"
+ " tarball provided on control file.")
+ kvm_log.info("Installing KVM from a local tarball")
+ kvm_log.info("Using tarball %s")
+ tarball = utils.unmap_url("/", params.get("tarball"), "/tmp")
+ os.chdir(srcdir)
+ return os.path.join(srcdir, utils.extract_tarball(tarball))
+
+ elif install_mode == 'localsrc':
+ return params.get('srcdir')
+
+ elif install_mode == 'git':
repo = params.get("git_repo")
user_repo = params.get("user_git_repo")
branch = params.get("git_branch", "master")
@@ -36,248 +102,165 @@ def run_kvm_install(test, params, env):
if not repo:
message = "KVM git repository path not specified"
kvm_log.error(message)
- raise error.TestError, message
+ raise error.TestError(message)
if not user_repo:
message = "KVM user git repository path not specified"
kvm_log.error(message)
- raise error.TestError, message
- __install_kvm_from_git(test, srcdir, repo, user_repo, branch, tag,
- user_tag, lbranch)
-
- # install from release
- elif install_mode == "release":
- release_dir = params.get("release_dir")
- release_tag = params.get("release_tag")
- if not release_dir:
- message = "Release dir not specified"
- kvm_log.error(message)
- raise error.TestError, message
- __install_kvm_release(test, srcdir, release_dir, release_tag)
-
- # install from snapshot
- elif install_mode == "snapshot":
- snapshot_dir = params.get("snapshot_dir")
- snapshot_date = params.get("snapshot_date")
- if not snapshot_dir:
- message = "Snapshot dir not specified"
- kvm_log.error(message)
- raise error.TestError, message
- __install_kvm_from_snapshot(test, srcdir, snapshot_dir, snapshot_date)
-
- # install from tarball
- elif install_mode == "localtar":
- tarball = params.get("tarball")
- if not tarball:
- message = "Local tarball filename not specified"
- kvm_log.error(message)
- raise error.TestError, message
- __install_kvm_from_local_tarball(test, srcdir, tarball)
-
- # install from local sources
- elif install_mode == "localsrc":
- __install_kvm(test, srcdir)
+ raise error.TestError(message)
- # invalid installation mode
- else:
- message = "Invalid installation mode: '%s'" % install_mode
- kvm_log.error(message)
- raise error.TestError, message
+ local_git_srcdir = os.path.join(srcdir, "kvm")
+ if not os.path.exists(local_git_srcdir):
+ os.mkdir(local_git_srcdir)
+ local_user_git_srcdir = os.path.join(srcdir, "kvmuser")
+ if not os.path.exists(local_user_git_srcdir):
+ os.mkdir(local_user_git_srcdir)
- # load kvm modules (unless requested not to)
- if params.get('load_modules', "yes") == "yes":
- __load_kvm_modules()
- else:
- kvm_log.info("user requested not to load kvm modules")
+ kvm_utils.get_git_branch(repo, branch, local_git_srcdir, tag, lbranch)
+ kvm_utils.get_git_branch(user_repo, branch, local_user_git_srcdir,
+ user_tag, lbranch)
-def __cleanup_dir(dir):
- # only alerts if src directory is not empty
- for root, dirs, files in os.walk(dir):
- if dirs or files:
- message = "Directory \'%s\' is not empty" % dir
- kvm_log.error(message)
- raise error.TestError, message
-
-def __install_kvm_release(test, srcdir, release_dir, release_tag):
- if not release_tag:
- try:
- # look for the latest release in the web
- page_url = os.path.join(release_dir, "showfiles.php")
- local_web_page = utils.unmap_url("/", page_url, "/tmp")
- f = open(local_web_page, "r")
- data = f.read()
- f.close()
- rx = re.compile("package_id=(\d+).*\>kvm\<", re.IGNORECASE)
- matches = rx.findall(data)
- package_id = matches[0]
- #package_id = 209008
- rx = re.compile("package_id=%s.*release_id=\d+\">(\d+)" % package_id, re.IGNORECASE)
- matches = rx.findall(data)
- release_tag = matches[0] # the first match contains the latest release tag
- except Exception, e:
- message = "Could not fetch latest KVM release tag (%s)" % str(e)
- kvm_log.error(message)
- raise error.TestError(message)
+ ## TODO: Needs to see how we are syncing up the directories
+ return local_user_git_srcdir
- kvm_log.info("Installing release %s (kvm-%s)" % (release_tag, release_tag))
- tarball = os.path.join(release_dir, "kvm-%s.tar.gz" % release_tag)
- tarball = utils.unmap_url("/", tarball, "/tmp")
- __install_kvm_from_local_tarball(test, srcdir, tarball)
-
-
-def __install_kvm_from_git(test, srcdir, repo, user_repo, branch, tag,
- user_tag, lbranch):
- local_git_srcdir = os.path.join(srcdir, "kvm")
- if not os.path.exists(local_git_srcdir):
- os.mkdir(local_git_srcdir)
- local_user_git_srcdir = os.path.join(srcdir, "kvmuser")
- if not os.path.exists(local_user_git_srcdir):
- os.mkdir(local_user_git_srcdir)
-
- __get_git_branch(repo, branch, local_git_srcdir, tag, lbranch)
- __get_git_branch(user_repo, branch, local_user_git_srcdir, user_tag, lbranch)
- utils.system("cd %s && ./configure && make -C kernel LINUX=%s sync" % (local_user_git_srcdir, local_git_srcdir))
- __install_kvm(test, local_user_git_srcdir)
-
-
-def __get_git_branch(repository, branch, srcdir, commit=None, lbranch=None):
- kvm_log.info("Getting sources from git <REP=%s BRANCH=%s TAG=%s> to local directory <%s>" % (repository, branch, commit, srcdir))
- pwd = os.getcwd()
- os.chdir(srcdir)
- if os.path.exists(".git"):
- utils.system("git reset --hard")
else:
- utils.system("git init")
+ return None
- if not lbranch:
- lbranch = branch
- utils.system("git fetch -q -f -u -t %s %s:%s" %
- (repository, branch, lbranch))
- utils.system("git checkout %s" % lbranch)
- if commit:
- utils.system("git checkout %s" % commit)
+def __build_kvm(build_dir, buildsteps=None):
+ """
+ Builds KVM, given a path to the project source code.
- h = utils.system_output('git log --pretty=format:"%H" -1')
- desc = utils.system_output("git describe")
- kvm_log.info("Commit hash for %s is %s (%s)" % (repository, h.strip(), desc))
- os.chdir(pwd)
+ @param build_dir: Path to KVM source code (toplevel)
+ @param buildsteps: Optional parameter. Alternative sequence of build
+ steps.
+ """
+ if not build_dir:
+ return
+ print build_dir
+ os.chdir(build_dir)
-def __install_kvm_from_snapshot(test, srcdir, snapshot_dir ,snapshot_date):
- kvm_log.info("Source snapshot dir: %s" % snaphost_dir)
- kvm_log.info("Source snapshot date: %s" % snapshot_date)
+ kvm_log.info("Applying patch to fix a small problem on KVM module build")
+ utils.system("patch -p0 < ../../adding_kvm_trace_support_qemu.patch")
- if not snapshot_date:
- d = (date.today() - timedelta(1)).strftime("%Y%m%d") # takes yesterday's snapshot
- else:
- d = snapshot_date
+ kvm_build_dir = os.path.join(build_dir, '..', '..', 'build')
+ kvm_build_dir = os.path.abspath(kvm_build_dir)
- tarball = os.path.join(snaphost_dir, "kvm-snapshot-%s.tar.gz" % d)
- kvm_log.info("Tarball url: %s" % tarball)
- tarball = utils.unmap_url("/", tarball, "/tmp")
- __install_kvm_from_local_tarball(test, srcdir, tarball)
+ if not os.path.exists(kvm_build_dir):
+ os.mkdir(kvm_build_dir)
+ if not buildsteps:
+ repository_type = kvm_utils.check_kvm_source_dir(build_dir)
+ if repository_type == 1:
+ buildsteps = ["./configure --prefix=%s" % kvm_build_dir,
+ "make clean",
+ "make -j %s" % utils.count_cpus()]
+ if not os.path.exists('qemu/pc-bios/bios.bin'):
+ buildsteps.append("make -C bios")
+ buildsteps.append("make -C extboot")
+ buildsteps.append("cp -f bios/BIOS-bochs-latest"
+ " qemu/pc-bios/bios.bin")
+ buildsteps.append("cp -f vgabios/VGABIOS-lgpl-latest.bin"
+ " qemu/pc-bios/vgabios.bin")
+ buildsteps.append("cp -f vgabios/VGABIOS-lgpl-latest.cirrus.bin"
+ " qemu/pc-bios/vgabios-cirrus.bin")
+ buildsteps.append("cp -f extboot/extboot.bin"
+ " qemu/pc-bios/extboot.bin")
+ elif repository_type == 2:
+ buildsteps = ["./configure --prefix=%s"
+ " --with-kvm-trace" % kvm_build_dir,
+ "make clean",
+ "make -j %s" % utils.count_cpus()]
+
+ kvm_log.info("Building KVM")
+ os.chdir(build_dir)
+ for step in buildsteps:
+ utils.system(step)
+
+
+def __install_kvm(build_dir, install_mode, test_bindir):
+ """
+ Installs KVM depending on the installation method and creates
+ appropriate symbolic links on the kvm test directory.
+
+ @param build_dir: KVM source directory
+ @param install_mode: Type of KVM installation
+ @param test_bindir: Path of the KVM test directory
+ """
+ prefix = None
+ if install_mode in ['release', 'snapshot', 'git', 'localtar', 'localsrc']:
+ os.chdir(build_dir)
+ repository_type = kvm_utils.check_kvm_source_dir(build_dir)
+ if repository_type == 1:
+ utils.system("make -C qemu install")
+ if repository_type == 2:
+ utils.system("make install")
+
+ kvm_build_dir = os.path.join(test_bindir, 'build')
+ prefix = os.path.abspath(kvm_build_dir)
+
+ if not prefix:
+ raise error.TestError("Can't determine KVM userspace install prefix")
-def __install_kvm_from_local_tarball(test, srcdir, tarball):
- pwd = os.getcwd()
- os.chdir(srcdir)
- newdir = utils.extract_tarball(tarball)
- if newdir:
- srcdir = os.path.join(srcdir, newdir)
- os.chdir(pwd)
- __install_kvm(test, srcdir)
+ # create symlinks
+ qemu_path = os.path.join(test_bindir, "qemu")
+ qemu_img_path = os.path.join(test_bindir, "qemu-img")
+ if os.path.lexists(qemu_path):
+ os.unlink(qemu_path)
+ if os.path.lexists(qemu_img_path):
+ os.unlink(qemu_img_path)
+ kvm_qemu = os.path.join(prefix, "bin", "qemu-system-x86_64")
+ if not os.path.isfile(kvm_qemu):
+ raise error.TestError('Invalid qemu path')
+ kvm_qemu_img = os.path.join(prefix, "bin", "qemu-img")
+ if not os.path.isfile(kvm_qemu_img):
+ raise error.TestError('Invalid qemu-img path')
+ os.symlink(kvm_qemu, qemu_path)
+ os.symlink(kvm_qemu_img, qemu_img_path)
-def __load_kvm_modules():
- kvm_log.info("Detecting CPU vendor...")
+def __load_kvm_modules(build_dir):
vendor = "intel"
if os.system("grep vmx /proc/cpuinfo 1>/dev/null") != 0:
vendor = "amd"
kvm_log.info("Detected CPU vendor as '%s'" %(vendor))
- #if self.config.load_modules == "yes":
- # remove existing in kernel kvm modules
- kvm_log.info("Unloading loaded KVM modules (if present)...")
- #utils.system("pkill qemu 1>/dev/null 2>&1", ignore_status=True)
+ kvm_log.info("Killing any qemu processes that might be left behind")
utils.system("pkill qemu", ignore_status=True)
- #if utils.system("grep kvm_%s /proc/modules 1>/dev/null" % vendor, ignore_status=True) == 0:
- utils.system("/sbin/rmmod kvm_%s" % vendor, ignore_status=True)
- #if utils.system("grep kvm /proc/modules 1>/dev/null", ignore_status=True) == 0:
- utils.system("/sbin/rmmod kvm", ignore_status=True)
- if utils.system("grep kvm /proc/modules 1>/dev/null", ignore_status=True) == 0:
+ kvm_log.info("Unloading previously loaded KVM modules")
+ kvm_utils.unload_module("kvm")
+ if utils.module_is_loaded("kvm"):
message = "Failed to remove old KVM modules"
kvm_log.error(message)
- raise error.TestError, message
+ raise error.TestError(message)
kvm_log.info("Loading new KVM modules...")
- os.chdir("kernel")
- if os.path.exists("x86"):
- os.chdir("x86")
- utils.system("/sbin/insmod ./kvm.ko && sleep 1 && /sbin/insmod ./kvm-%s.ko" % vendor)
-
- #elif self.config.load_modules == "no":
- #kvm_log.info("user requested not to load kvm modules")
-
- ### no matter if new kvm modules are to be loaded or not
- ### make sure there are kvm modules installed.
- if utils.system("grep kvm_%s /proc/modules 1>/dev/null" %(vendor), ignore_status=True) != 0:
- message = "Failed to load KVM modules"
- kvm_log.error(message)
- raise error.TestError, message
-
-def __install_kvm(test, srcdir):
- # create destination dir
-
- kvm_build_dir = os.path.join(srcdir, '..', '..', 'build')
- kvm_build_dir = os.path.abspath(kvm_build_dir)
-
- if not os.path.exists(kvm_build_dir):
- os.mkdir(kvm_build_dir)
-
- # change to source dir
- os.chdir(srcdir)
-
- # start working...
- kvm_log.info("Building KVM...")
-
- def run(cmd, title, timeout):
- (status, pid, output) = kvm_utils.run_bg(cmd, None, kvm_log.info,
- '(%s)' % title, timeout=timeout)
- if status != 0:
- kvm_utils.safe_kill(pid, signal.SIGTERM)
- raise error.TestFail, "'%s' failed" % cmd
-
- # configure + make
- run("./configure --prefix=%s" % kvm_build_dir, "configure", 30)
- run("make clean", "make clean", 30)
- run("make", "make", 1200)
-
- # make bios binaries if missing
- if not os.path.exists('qemu/pc-bios/bios.bin'):
- run("make -C bios", "make bios", 60)
- run("make -C vgabios", "make vgabios", 60)
- run("make -C extboot", "make extboot", 60)
- cp1 = "cp -f bios/BIOS-bochs-latest qemu/pc-bios/bios.bin"
- cp2 = "cp -f vgabios/VGABIOS-lgpl-latest.bin qemu/pc-bios/vgabios.bin"
- cp3 = "cp -f vgabios/VGABIOS-lgpl-latest.cirrus.bin qemu/pc-bios/vgabios-cirrus.bin"
- cp4 = "cp -f extboot/extboot.bin qemu/pc-bios/extboot.bin"
- cmd = "&& ".join([cp1, cp2, cp3, cp4])
- run(cmd, "copy bios binaries", 30)
-
- # install from qemu directory
- run("make -C qemu install", "(make install) ", 120)
-
- # create symlinks
- qemu_path = os.path.join(test.bindir, "qemu")
- qemu_img_path = os.path.join(test.bindir, "qemu-img")
- if os.path.lexists(qemu_path):
- os.unlink(qemu_path)
- if os.path.lexists(qemu_img_path):
- os.unlink(qemu_img_path)
- kvm_qemu = os.path.join(kvm_build_dir, "bin", "qemu-system-x86_64")
- kvm_qemu_img = os.path.join(kvm_build_dir, "bin", "qemu-img")
- os.symlink(kvm_qemu, qemu_path)
- os.symlink(kvm_qemu_img, qemu_img_path)
- kvm_log.info("Done building and installing KVM")
+ kvm_module_path = None
+ kvm_vendor_module_path = None
+ for folder, subdirs, files in os.walk(build_dir):
+ if "kvm.ko" in files:
+ kvm_module_path = os.path.join(folder, "kvm.ko")
+ kvm_vendor_module_path = os.path.join(folder, "kvm-%s.ko" % vendor)
+
+ abort = False
+ if not kvm_module_path:
+ kvm_log.error("Could not find KVM module that was supposed to be"
+ " built on the source dir")
+ abort = True
+ elif not kvm_vendor_module_path:
+ kvm_log.error("Could not find KVM (%s) module that was supposed to be"
+ " built on the source dir" % vendor)
+ abort = True
+ if abort:
+ raise error.TestError("Could not load KVM modules.")
+
+ utils.system("/sbin/insmod %s" % kvm_module_path)
+ time.sleep(1)
+ utils.system("/sbin/insmod %s" % kvm_vendor_module_path)
+
+ if not utils.module_is_loaded("kvm"):
+ message = "Failed to load the KVM modules built for the test"
+ kvm_log.error(message)
+ raise error.TestError(message)
@@ -15,6 +15,8 @@ import re
import kvm_log
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.bin import utils
# Functions for working with dicts obtained from the test config file
@@ -99,6 +101,100 @@ def safe_kill(pid, signal):
return False
+def get_latest_kvm_release_tag(release_dir):
+ try:
+ page_url = os.path.join(release_dir, "showfiles.php")
+ local_web_page = utils.unmap_url("/", page_url, "/tmp")
+ f = open(local_web_page, "r")
+ data = f.read()
+ f.close()
+ rx = re.compile("package_id=(\d+).*\>kvm\<", re.IGNORECASE)
+ matches = rx.findall(data)
+ package_id = matches[0]
+ #package_id = 209008
+ rx = re.compile("package_id=%s.*release_id=\d+\">(\d+)" % package_id,
+ re.IGNORECASE)
+ matches = rx.findall(data)
+ return matches[0] # the first match contains the latest release tag
+ except Exception, e:
+ message = "Could not fetch latest KVM release tag (%s)" % str(e)
+ kvm_log.error(message)
+ raise error.TestError(message)
+
+
+def get_git_branch(repository, branch, srcdir, commit=None, lbranch=None):
+ """
+ Retrieves a given git code repository.
+
+ @param repository: Git repository URL
+ """
+ kvm_log.info("Getting sources from git <REP=%s BRANCH=%s TAG=%s>"
+ " to local directory <%s>" % (repository, branch, commit,
+ srcdir))
+ pwd = os.getcwd()
+ os.chdir(srcdir)
+ if os.path.exists(".git"):
+ utils.system("git reset --hard")
+ else:
+ utils.system("git init")
+
+ if not lbranch:
+ lbranch = branch
+
+ utils.system("git fetch -q -f -u -t %s %s:%s" %
+ (repository, branch, lbranch))
+ utils.system("git checkout %s" % lbranch)
+ if commit:
+ utils.system("git checkout %s" % commit)
+
+ h = utils.system_output('git log --pretty=format:"%H" -1')
+ desc = utils.system_output("git describe")
+ kvm_log.info("Commit hash for %s is %s (%s)" % (repository, h.strip(),
+ desc))
+ os.chdir(pwd)
+
+
+def unload_module(module_name):
+ """
+ Removes a module. Handles dependencies. If even then it's not possible
+ to remove one of the modules, it will trhow an error.CmdError exception.
+
+ @param module_name: Name of the module we want to remove
+ """
+ l_raw = utils.system_output("/sbin/lsmod").splitlines()
+ lsmod = [x for x in l_raw if x.split()[0] == module_name]
+ if len(lsmod) > 0:
+ line_parts = lsmod[0].split()
+ if len(line_parts) == 4:
+ submodules = line_parts[3].split(",")
+ for submodule in submodules:
+ unload_module(submodule)
+ utils.system("/sbin/modprobe -r %s" % module_name)
+ kvm_log.info("Module %s unloaded" % module_name)
+ else:
+ kvm_log.info("Module %s is already unloaded" % module_name)
+
+
+def check_kvm_source_dir(source_dir):
+ """
+ Inspects the kvm source directory and verifies its disposition. In some
+ occasions build may be dependant on the source directory disposition.
+
+ @param source_dir: Source code path that will be inspected.
+ """
+ os.chdir(source_dir)
+ has_qemu_dir = os.path.isdir('qemu')
+ has_kvm_dir = os.path.isdir('kvm')
+ if has_qemu_dir and not has_kvm_dir:
+ kvm_log.info("qemu directory detected, source dir layout 1")
+ return 1
+ if has_kvm_dir and not has_qemu_dir:
+ kvm_log.info("kvm directory detected, source dir layout 2")
+ return 2
+ else:
+ raise error.TestError("Unknown source dir layout, cannot proceed.")
+
+
# The following are a class and functions used for SSH, SCP and Telnet communication with guests.
class kvm_spawn: