kvm_installer.py revision ce1b0620fddfb6efa33cc9441d9c91ce06b30de3
1import os, logging, datetime, glob, shutil 2from autotest_lib.client.bin import utils, os_dep 3from autotest_lib.client.common_lib import error 4import virt_utils, virt_installer 5 6 7def kill_qemu_processes(): 8 """ 9 Kills all qemu processes, also kills all processes holding /dev/kvm down. 10 """ 11 logging.debug("Killing any qemu processes that might be left behind") 12 utils.system("pkill qemu", ignore_status=True) 13 # Let's double check to see if some other process is holding /dev/kvm 14 if os.path.isfile("/dev/kvm"): 15 utils.system("fuser -k /dev/kvm", ignore_status=True) 16 17 18def _unload_kvm_modules(mod_list): 19 logging.info("Unloading previously loaded KVM modules") 20 for module in reversed(mod_list): 21 utils.unload_module(module) 22 23 24def _load_kvm_modules(mod_list, module_dir=None, load_stock=False): 25 """ 26 Just load the KVM modules, without killing Qemu or unloading previous 27 modules. 28 29 Load modules present on any sub directory of module_dir. Function will walk 30 through module_dir until it finds the modules. 31 32 @param module_dir: Directory where the KVM modules are located. 33 @param load_stock: Whether we are going to load system kernel modules. 34 @param extra_modules: List of extra modules to load. 35 """ 36 if module_dir: 37 logging.info("Loading the built KVM modules...") 38 kvm_module_path = None 39 kvm_vendor_module_path = None 40 abort = False 41 42 list_modules = ['%s.ko' % (m) for m in mod_list] 43 44 list_module_paths = [] 45 for folder, subdirs, files in os.walk(module_dir): 46 for module in list_modules: 47 if module in files: 48 module_path = os.path.join(folder, module) 49 list_module_paths.append(module_path) 50 51 # We might need to arrange the modules in the correct order 52 # to avoid module load problems 53 list_modules_load = [] 54 for module in list_modules: 55 for module_path in list_module_paths: 56 if os.path.basename(module_path) == module: 57 list_modules_load.append(module_path) 58 59 if len(list_module_paths) != len(list_modules): 60 logging.error("KVM modules not found. If you don't want to use the " 61 "modules built by this test, make sure the option " 62 "load_modules: 'no' is marked on the test control " 63 "file.") 64 raise error.TestError("The modules %s were requested to be loaded, " 65 "but the only modules found were %s" % 66 (list_modules, list_module_paths)) 67 68 for module_path in list_modules_load: 69 try: 70 utils.system("insmod %s" % module_path) 71 except Exception, e: 72 raise error.TestFail("Failed to load KVM modules: %s" % e) 73 74 if load_stock: 75 logging.info("Loading current system KVM modules...") 76 for module in mod_list: 77 utils.system("modprobe %s" % module) 78 79 80def create_symlinks(test_bindir, prefix=None, bin_list=None, unittest=None): 81 """ 82 Create symbolic links for the appropriate qemu and qemu-img commands on 83 the kvm test bindir. 84 85 @param test_bindir: KVM test bindir 86 @param prefix: KVM prefix path 87 @param bin_list: List of qemu binaries to link 88 @param unittest: Path to configuration file unittests.cfg 89 """ 90 qemu_path = os.path.join(test_bindir, "qemu") 91 qemu_img_path = os.path.join(test_bindir, "qemu-img") 92 qemu_unittest_path = os.path.join(test_bindir, "unittests") 93 if os.path.lexists(qemu_path): 94 os.unlink(qemu_path) 95 if os.path.lexists(qemu_img_path): 96 os.unlink(qemu_img_path) 97 if unittest and os.path.lexists(qemu_unittest_path): 98 os.unlink(qemu_unittest_path) 99 100 logging.debug("Linking qemu binaries") 101 102 if bin_list: 103 for bin in bin_list: 104 if os.path.basename(bin) == 'qemu-kvm': 105 os.symlink(bin, qemu_path) 106 elif os.path.basename(bin) == 'qemu-img': 107 os.symlink(bin, qemu_img_path) 108 109 elif prefix: 110 kvm_qemu = os.path.join(prefix, "bin", "qemu-system-x86_64") 111 if not os.path.isfile(kvm_qemu): 112 raise error.TestError('Invalid qemu path') 113 kvm_qemu_img = os.path.join(prefix, "bin", "qemu-img") 114 if not os.path.isfile(kvm_qemu_img): 115 raise error.TestError('Invalid qemu-img path') 116 os.symlink(kvm_qemu, qemu_path) 117 os.symlink(kvm_qemu_img, qemu_img_path) 118 119 if unittest: 120 logging.debug("Linking unittest dir") 121 os.symlink(unittest, qemu_unittest_path) 122 123 124def install_roms(rom_dir, prefix): 125 logging.debug("Path to roms specified. Copying roms to install prefix") 126 rom_dst_dir = os.path.join(prefix, 'share', 'qemu') 127 for rom_src in glob.glob('%s/*.bin' % rom_dir): 128 rom_dst = os.path.join(rom_dst_dir, os.path.basename(rom_src)) 129 logging.debug("Copying rom file %s to %s", rom_src, rom_dst) 130 shutil.copy(rom_src, rom_dst) 131 132 133class KvmInstallException(Exception): 134 pass 135 136 137class FailedKvmInstall(KvmInstallException): 138 pass 139 140 141class KvmNotInstalled(KvmInstallException): 142 pass 143 144 145class BaseInstaller(object): 146 # default value for load_stock argument 147 load_stock_modules = True 148 def __init__(self, mode=None): 149 self.install_mode = mode 150 self._full_module_list = None 151 152 def set_install_params(self, test, params): 153 self.params = params 154 155 load_modules = params.get('load_modules', 'no') 156 if not load_modules or load_modules == 'yes': 157 self.should_load_modules = True 158 elif load_modules == 'no': 159 self.should_load_modules = False 160 default_extra_modules = str(None) 161 self.extra_modules = eval(params.get("extra_modules", 162 default_extra_modules)) 163 164 self.cpu_vendor = virt_installer.cpu_vendor() 165 166 self.srcdir = test.srcdir 167 if not os.path.isdir(self.srcdir): 168 os.makedirs(self.srcdir) 169 170 self.test_bindir = test.bindir 171 self.results_dir = test.resultsdir 172 173 # KVM build prefix, for the modes that do need it 174 prefix = os.path.join(test.bindir, 'build') 175 self.prefix = os.path.abspath(prefix) 176 177 # Current host kernel directory 178 default_host_kernel_source = '/lib/modules/%s/build' % os.uname()[2] 179 self.host_kernel_srcdir = params.get('host_kernel_source', 180 default_host_kernel_source) 181 182 # Extra parameters that can be passed to the configure script 183 self.extra_configure_options = params.get('extra_configure_options', 184 None) 185 186 # Do we want to save the result of the build on test.resultsdir? 187 self.save_results = True 188 save_results = params.get('save_results', 'no') 189 if save_results == 'no': 190 self.save_results = False 191 192 self._full_module_list = list(self._module_list()) 193 194 195 def install_unittests(self): 196 userspace_srcdir = os.path.join(self.srcdir, "kvm_userspace") 197 test_repo = self.params.get("test_git_repo") 198 test_branch = self.params.get("test_branch", "master") 199 test_commit = self.params.get("test_commit", None) 200 test_lbranch = self.params.get("test_lbranch", "master") 201 202 if test_repo: 203 test_srcdir = os.path.join(self.srcdir, "kvm-unit-tests") 204 virt_utils.get_git_branch(test_repo, test_branch, test_srcdir, 205 test_commit, test_lbranch) 206 unittest_cfg = os.path.join(test_srcdir, 'x86', 207 'unittests.cfg') 208 self.test_srcdir = test_srcdir 209 else: 210 unittest_cfg = os.path.join(userspace_srcdir, 'kvm', 'test', 'x86', 211 'unittests.cfg') 212 self.unittest_cfg = None 213 if os.path.isfile(unittest_cfg): 214 self.unittest_cfg = unittest_cfg 215 else: 216 if test_repo: 217 logging.error("No unittest config file %s found, skipping " 218 "unittest build", self.unittest_cfg) 219 220 self.unittest_prefix = None 221 if self.unittest_cfg: 222 logging.info("Building and installing unittests") 223 os.chdir(os.path.dirname(os.path.dirname(self.unittest_cfg))) 224 utils.system('./configure --prefix=%s' % self.prefix) 225 utils.system('make') 226 utils.system('make install') 227 self.unittest_prefix = os.path.join(self.prefix, 'share', 'qemu', 228 'tests') 229 230 231 def full_module_list(self): 232 """Return the module list used by the installer 233 234 Used by the module_probe test, to avoid using utils.unload_module(). 235 """ 236 if self._full_module_list is None: 237 raise KvmNotInstalled("KVM modules not installed yet (installer: %s)" % (type(self))) 238 return self._full_module_list 239 240 241 def _module_list(self): 242 """Generate the list of modules that need to be loaded 243 """ 244 yield 'kvm' 245 yield 'kvm-%s' % (self.cpu_vendor) 246 if self.extra_modules: 247 for module in self.extra_modules: 248 yield module 249 250 251 def _load_modules(self, mod_list): 252 """ 253 Load the KVM modules 254 255 May be overridden by subclasses. 256 """ 257 _load_kvm_modules(mod_list, load_stock=self.load_stock_modules) 258 259 260 def load_modules(self, mod_list=None): 261 if mod_list is None: 262 mod_list = self.full_module_list() 263 self._load_modules(mod_list) 264 265 266 def _unload_modules(self, mod_list=None): 267 """ 268 Just unload the KVM modules, without trying to kill Qemu 269 """ 270 if mod_list is None: 271 mod_list = self.full_module_list() 272 _unload_kvm_modules(mod_list) 273 274 275 def unload_modules(self, mod_list=None): 276 """ 277 Kill Qemu and unload the KVM modules 278 """ 279 kill_qemu_processes() 280 self._unload_modules(mod_list) 281 282 283 def reload_modules(self): 284 """ 285 Reload the KVM modules after killing Qemu and unloading the current modules 286 """ 287 self.unload_modules() 288 self.load_modules() 289 290 291 def reload_modules_if_needed(self): 292 if self.should_load_modules: 293 self.reload_modules() 294 295 296class YumInstaller(BaseInstaller): 297 """ 298 Class that uses yum to install and remove packages. 299 """ 300 load_stock_modules = True 301 def set_install_params(self, test, params): 302 super(YumInstaller, self).set_install_params(test, params) 303 # Checking if all required dependencies are available 304 os_dep.command("rpm") 305 os_dep.command("yum") 306 307 default_pkg_list = str(['qemu-kvm', 'qemu-kvm-tools']) 308 default_qemu_bin_paths = str(['/usr/bin/qemu-kvm', '/usr/bin/qemu-img']) 309 default_pkg_path_list = str(None) 310 self.pkg_list = eval(params.get("pkg_list", default_pkg_list)) 311 self.pkg_path_list = eval(params.get("pkg_path_list", 312 default_pkg_path_list)) 313 self.qemu_bin_paths = eval(params.get("qemu_bin_paths", 314 default_qemu_bin_paths)) 315 316 317 def _clean_previous_installs(self): 318 kill_qemu_processes() 319 removable_packages = "" 320 for pkg in self.pkg_list: 321 removable_packages += " %s" % pkg 322 323 utils.system("yum remove -y %s" % removable_packages) 324 325 326 def _get_packages(self): 327 for pkg in self.pkg_path_list: 328 utils.get_file(pkg, os.path.join(self.srcdir, 329 os.path.basename(pkg))) 330 331 332 def _install_packages(self): 333 """ 334 Install all downloaded packages. 335 """ 336 os.chdir(self.srcdir) 337 utils.system("yum install --nogpgcheck -y *.rpm") 338 339 340 def install(self): 341 self.install_unittests() 342 self._clean_previous_installs() 343 self._get_packages() 344 self._install_packages() 345 create_symlinks(test_bindir=self.test_bindir, 346 bin_list=self.qemu_bin_paths, 347 unittest=self.unittest_prefix) 348 self.reload_modules_if_needed() 349 if self.save_results: 350 virt_installer.save_build(self.srcdir, self.results_dir) 351 352 353class KojiInstaller(YumInstaller): 354 """ 355 Class that handles installing KVM from the fedora build service, koji. 356 357 It uses yum to install and remove packages. Packages are specified 358 according to the syntax defined in the PkgSpec class. 359 """ 360 load_stock_modules = True 361 def set_install_params(self, test, params): 362 """ 363 Gets parameters and initializes the package downloader. 364 365 @param test: kvm test object 366 @param params: Dictionary with test arguments 367 """ 368 super(KojiInstaller, self).set_install_params(test, params) 369 self.tag = params.get("koji_tag", None) 370 self.koji_cmd = params.get("koji_cmd", None) 371 if self.tag is not None: 372 virt_utils.set_default_koji_tag(self.tag) 373 self.koji_pkgs = eval(params.get("koji_pkgs", "[]")) 374 375 376 def _get_packages(self): 377 """ 378 Downloads the specific arch RPMs for the specific build name. 379 """ 380 koji_client = virt_utils.KojiClient(cmd=self.koji_cmd) 381 for pkg_text in self.koji_pkgs: 382 pkg = virt_utils.KojiPkgSpec(pkg_text) 383 if pkg.is_valid(): 384 koji_client.get_pkgs(pkg, dst_dir=self.srcdir) 385 else: 386 logging.error('Package specification (%s) is invalid: %s', pkg, 387 pkg.describe_invalid()) 388 389 390 def _clean_previous_installs(self): 391 kill_qemu_processes() 392 removable_packages = " ".join(self._get_rpm_names()) 393 utils.system("yum -y remove %s" % removable_packages) 394 395 396 def install(self): 397 self._clean_previous_installs() 398 self._get_packages() 399 self._install_packages() 400 self.install_unittests() 401 create_symlinks(test_bindir=self.test_bindir, 402 bin_list=self.qemu_bin_paths, 403 unittest=self.unittest_prefix) 404 self.reload_modules_if_needed() 405 if self.save_results: 406 virt_installer.save_build(self.srcdir, self.results_dir) 407 408 409 def _get_rpm_names(self): 410 all_rpm_names = [] 411 koji_client = virt_utils.KojiClient(cmd=self.koji_cmd) 412 for pkg_text in self.koji_pkgs: 413 pkg = virt_utils.KojiPkgSpec(pkg_text) 414 rpm_names = koji_client.get_pkg_rpm_names(pkg) 415 all_rpm_names += rpm_names 416 return all_rpm_names 417 418 419 def _get_rpm_file_names(self): 420 all_rpm_file_names = [] 421 koji_client = virt_utils.KojiClient(cmd=self.koji_cmd) 422 for pkg_text in self.koji_pkgs: 423 pkg = virt_utils.KojiPkgSpec(pkg_text) 424 rpm_file_names = koji_client.get_pkg_rpm_file_names(pkg) 425 all_rpm_file_names += rpm_file_names 426 return all_rpm_file_names 427 428 429 def _install_packages(self): 430 """ 431 Install all downloaded packages. 432 """ 433 os.chdir(self.srcdir) 434 rpm_file_names = " ".join(self._get_rpm_file_names()) 435 utils.system("yum --nogpgcheck -y localinstall %s" % rpm_file_names) 436 437 438class SourceDirInstaller(BaseInstaller): 439 """ 440 Class that handles building/installing KVM directly from a tarball or 441 a single source code dir. 442 """ 443 def set_install_params(self, test, params): 444 """ 445 Initializes class attributes, and retrieves KVM code. 446 447 @param test: kvm test object 448 @param params: Dictionary with test arguments 449 """ 450 super(SourceDirInstaller, self).set_install_params(test, params) 451 452 self.mod_install_dir = os.path.join(self.prefix, 'modules') 453 self.installed_kmods = False # it will be set to True in case we 454 # installed our own modules 455 456 srcdir = params.get("srcdir", None) 457 self.path_to_roms = params.get("path_to_rom_images", None) 458 459 if self.install_mode == 'localsrc': 460 if srcdir is None: 461 raise error.TestError("Install from source directory specified" 462 "but no source directory provided on the" 463 "control file.") 464 else: 465 shutil.copytree(srcdir, self.srcdir) 466 467 if self.install_mode == 'release': 468 release_tag = params.get("release_tag") 469 release_dir = params.get("release_dir") 470 release_listing = params.get("release_listing") 471 logging.info("Installing KVM from release tarball") 472 if not release_tag: 473 release_tag = virt_utils.get_latest_kvm_release_tag( 474 release_listing) 475 tarball = os.path.join(release_dir, 'kvm', release_tag, 476 "kvm-%s.tar.gz" % release_tag) 477 logging.info("Retrieving release kvm-%s" % release_tag) 478 tarball = utils.unmap_url("/", tarball, "/tmp") 479 480 elif self.install_mode == 'snapshot': 481 logging.info("Installing KVM from snapshot") 482 snapshot_dir = params.get("snapshot_dir") 483 if not snapshot_dir: 484 raise error.TestError("Snapshot dir not provided") 485 snapshot_date = params.get("snapshot_date") 486 if not snapshot_date: 487 # Take yesterday's snapshot 488 d = (datetime.date.today() - 489 datetime.timedelta(1)).strftime("%Y%m%d") 490 else: 491 d = snapshot_date 492 tarball = os.path.join(snapshot_dir, "kvm-snapshot-%s.tar.gz" % d) 493 logging.info("Retrieving kvm-snapshot-%s" % d) 494 tarball = utils.unmap_url("/", tarball, "/tmp") 495 496 elif self.install_mode == 'localtar': 497 tarball = params.get("tarball") 498 if not tarball: 499 raise error.TestError("KVM Tarball install specified but no" 500 " tarball provided on control file.") 501 logging.info("Installing KVM from a local tarball") 502 logging.info("Using tarball %s") 503 tarball = utils.unmap_url("/", params.get("tarball"), "/tmp") 504 505 if self.install_mode in ['release', 'snapshot', 'localtar']: 506 utils.extract_tarball_to_dir(tarball, self.srcdir) 507 508 if self.install_mode in ['release', 'snapshot', 'localtar', 'srcdir']: 509 self.repo_type = virt_utils.check_kvm_source_dir(self.srcdir) 510 p = os.path.join(self.srcdir, 'configure') 511 self.configure_options = virt_installer.check_configure_options(p) 512 513 514 def _build(self): 515 make_jobs = utils.count_cpus() 516 os.chdir(self.srcdir) 517 # For testing purposes, it's better to build qemu binaries with 518 # debugging symbols, so we can extract more meaningful stack traces. 519 cfg = "./configure --prefix=%s" % self.prefix 520 if "--disable-strip" in self.configure_options: 521 cfg += " --disable-strip" 522 steps = [cfg, "make clean", "make -j %s" % make_jobs] 523 logging.info("Building KVM") 524 for step in steps: 525 utils.system(step) 526 527 528 def _install_kmods_old_userspace(self, userspace_path): 529 """ 530 Run the module install command. 531 532 This is for the "old userspace" code, that contained a 'kernel' subdirectory 533 with the kmod build code. 534 535 The code would be much simpler if we could specify the module install 536 path as parameter to the toplevel Makefile. As we can't do that and 537 the module install code doesn't use --prefix, we have to call 538 'make -C kernel install' directly, setting the module directory 539 parameters. 540 541 If the userspace tree doens't have a 'kernel' subdirectory, the 542 module install step will be skipped. 543 544 @param userspace_path: the path the kvm-userspace directory 545 """ 546 kdir = os.path.join(userspace_path, 'kernel') 547 if os.path.isdir(kdir): 548 os.chdir(kdir) 549 # INSTALLDIR is the target dir for the modules 550 # ORIGMODDIR is the dir where the old modules will be removed. we 551 # don't want to mess with the system modules, so set it 552 # to a non-existing directory 553 utils.system('make install INSTALLDIR=%s ORIGMODDIR=/tmp/no-old-modules' % (self.mod_install_dir)) 554 self.installed_kmods = True 555 556 557 def _install_kmods(self, kmod_path): 558 """Run the module install command for the kmod-kvm repository 559 560 @param kmod_path: the path to the kmod-kvm.git working copy 561 """ 562 os.chdir(kmod_path) 563 utils.system('make modules_install DESTDIR=%s' % (self.mod_install_dir)) 564 self.installed_kmods = True 565 566 567 def _install(self): 568 os.chdir(self.srcdir) 569 logging.info("Installing KVM userspace") 570 if self.repo_type == 1: 571 utils.system("make -C qemu install") 572 self._install_kmods_old_userspace(self.srcdir) 573 elif self.repo_type == 2: 574 utils.system("make install") 575 if self.path_to_roms: 576 install_roms(self.path_to_roms, self.prefix) 577 self.install_unittests() 578 create_symlinks(test_bindir=self.test_bindir, 579 prefix=self.prefix, 580 unittest=self.unittest_prefix) 581 582 583 def _load_modules(self, mod_list): 584 # load the installed KVM modules in case we installed them 585 # ourselves. Otherwise, just load the system modules. 586 if self.installed_kmods: 587 logging.info("Loading installed KVM modules") 588 _load_kvm_modules(mod_list, module_dir=self.mod_install_dir) 589 else: 590 logging.info("Loading stock KVM modules") 591 _load_kvm_modules(mod_list, load_stock=True) 592 593 594 def install(self): 595 self._build() 596 self._install() 597 self.reload_modules_if_needed() 598 if self.save_results: 599 virt_installer.save_build(self.srcdir, self.results_dir) 600 601 602class GitInstaller(SourceDirInstaller): 603 def _pull_code(self): 604 """ 605 Retrieves code from git repositories. 606 """ 607 params = self.params 608 609 kernel_repo = params.get("git_repo") 610 user_repo = params.get("user_git_repo") 611 kmod_repo = params.get("kmod_repo") 612 613 kernel_branch = params.get("kernel_branch", "master") 614 user_branch = params.get("user_branch", "master") 615 kmod_branch = params.get("kmod_branch", "master") 616 617 kernel_lbranch = params.get("kernel_lbranch", "master") 618 user_lbranch = params.get("user_lbranch", "master") 619 kmod_lbranch = params.get("kmod_lbranch", "master") 620 621 kernel_commit = params.get("kernel_commit", None) 622 user_commit = params.get("user_commit", None) 623 kmod_commit = params.get("kmod_commit", None) 624 625 kernel_patches = eval(params.get("kernel_patches", "[]")) 626 user_patches = eval(params.get("user_patches", "[]")) 627 kmod_patches = eval(params.get("user_patches", "[]")) 628 629 if not user_repo: 630 message = "KVM user git repository path not specified" 631 logging.error(message) 632 raise error.TestError(message) 633 634 userspace_srcdir = os.path.join(self.srcdir, "kvm_userspace") 635 virt_utils.get_git_branch(user_repo, user_branch, userspace_srcdir, 636 user_commit, user_lbranch) 637 self.userspace_srcdir = userspace_srcdir 638 639 if user_patches: 640 os.chdir(self.userspace_srcdir) 641 for patch in user_patches: 642 utils.get_file(patch, os.path.join(self.userspace_srcdir, 643 os.path.basename(patch))) 644 utils.system('patch -p1 < %s' % os.path.basename(patch)) 645 646 if kernel_repo: 647 kernel_srcdir = os.path.join(self.srcdir, "kvm") 648 virt_utils.get_git_branch(kernel_repo, kernel_branch, kernel_srcdir, 649 kernel_commit, kernel_lbranch) 650 self.kernel_srcdir = kernel_srcdir 651 if kernel_patches: 652 os.chdir(self.kernel_srcdir) 653 for patch in kernel_patches: 654 utils.get_file(patch, os.path.join(self.userspace_srcdir, 655 os.path.basename(patch))) 656 utils.system('patch -p1 < %s' % os.path.basename(patch)) 657 else: 658 self.kernel_srcdir = None 659 660 if kmod_repo: 661 kmod_srcdir = os.path.join (self.srcdir, "kvm_kmod") 662 virt_utils.get_git_branch(kmod_repo, kmod_branch, kmod_srcdir, 663 kmod_commit, kmod_lbranch) 664 self.kmod_srcdir = kmod_srcdir 665 if kmod_patches: 666 os.chdir(self.kmod_srcdir) 667 for patch in kmod_patches: 668 utils.get_file(patch, os.path.join(self.userspace_srcdir, 669 os.path.basename(patch))) 670 utils.system('patch -p1 < %s' % os.path.basename(patch)) 671 else: 672 self.kmod_srcdir = None 673 674 p = os.path.join(self.userspace_srcdir, 'configure') 675 self.configure_options = virt_installer.check_configure_options(p) 676 677 678 def _build(self): 679 make_jobs = utils.count_cpus() 680 cfg = './configure' 681 if self.kmod_srcdir: 682 logging.info('Building KVM modules') 683 os.chdir(self.kmod_srcdir) 684 module_build_steps = [cfg, 685 'make clean', 686 'make sync LINUX=%s' % self.kernel_srcdir, 687 'make'] 688 elif self.kernel_srcdir: 689 logging.info('Building KVM modules') 690 os.chdir(self.userspace_srcdir) 691 cfg += ' --kerneldir=%s' % self.host_kernel_srcdir 692 module_build_steps = [cfg, 693 'make clean', 694 'make -C kernel LINUX=%s sync' % self.kernel_srcdir] 695 else: 696 module_build_steps = [] 697 698 for step in module_build_steps: 699 utils.run(step) 700 701 logging.info('Building KVM userspace code') 702 os.chdir(self.userspace_srcdir) 703 cfg += ' --prefix=%s' % self.prefix 704 if "--disable-strip" in self.configure_options: 705 cfg += ' --disable-strip' 706 if self.extra_configure_options: 707 cfg += ' %s' % self.extra_configure_options 708 utils.system(cfg) 709 utils.system('make clean') 710 utils.system('make -j %s' % make_jobs) 711 712 713 def _install(self): 714 if self.kernel_srcdir: 715 os.chdir(self.userspace_srcdir) 716 # the kernel module install with --prefix doesn't work, and DESTDIR 717 # wouldn't work for the userspace stuff, so we clear WANT_MODULE: 718 utils.system('make install WANT_MODULE=') 719 # and install the old-style-kmod modules manually: 720 self._install_kmods_old_userspace(self.userspace_srcdir) 721 elif self.kmod_srcdir: 722 # if we have a kmod repository, it is easier: 723 # 1) install userspace: 724 os.chdir(self.userspace_srcdir) 725 utils.system('make install') 726 # 2) install kmod: 727 self._install_kmods(self.kmod_srcdir) 728 else: 729 # if we don't have kmod sources, we just install 730 # userspace: 731 os.chdir(self.userspace_srcdir) 732 utils.system('make install') 733 734 if self.path_to_roms: 735 install_roms(self.path_to_roms, self.prefix) 736 self.install_unittests() 737 create_symlinks(test_bindir=self.test_bindir, prefix=self.prefix, 738 bin_list=None, 739 unittest=self.unittest_prefix) 740 741 742 def install(self): 743 self._pull_code() 744 self._build() 745 self._install() 746 self.reload_modules_if_needed() 747 if self.save_results: 748 virt_installer.save_build(self.srcdir, self.results_dir) 749 750 751class PreInstalledKvm(BaseInstaller): 752 # load_modules() will use the stock modules: 753 load_stock_modules = True 754 def install(self): 755 logging.info("Expecting KVM to be already installed. Doing nothing") 756 757 758class FailedInstaller: 759 """ 760 Class used to be returned instead of the installer if a installation fails 761 762 Useful to make sure no installer object is used if KVM installation fails. 763 """ 764 def __init__(self, msg="KVM install failed"): 765 self._msg = msg 766 767 768 def load_modules(self): 769 """Will refuse to load the KVM modules as install failed""" 770 raise FailedKvmInstall("KVM modules not available. reason: %s" % (self._msg)) 771 772 773installer_classes = { 774 'localsrc': SourceDirInstaller, 775 'localtar': SourceDirInstaller, 776 'release': SourceDirInstaller, 777 'snapshot': SourceDirInstaller, 778 'git': GitInstaller, 779 'yum': YumInstaller, 780 'koji': KojiInstaller, 781 'preinstalled': PreInstalledKvm, 782} 783 784 785def _installer_class(install_mode): 786 c = installer_classes.get(install_mode) 787 if c is None: 788 raise error.TestError('Invalid or unsupported' 789 ' install mode: %s' % install_mode) 790 return c 791 792 793def make_installer(params): 794 # priority: 795 # - 'install_mode' param 796 # - 'mode' param 797 mode = params.get("install_mode", params.get("mode")) 798 klass = _installer_class(mode) 799 return klass(mode) 800