~smoser/curtin/yakkety.lp1666986

« back to all changes in this revision

Viewing changes to tests/vmtests/__init__.py

  • Committer: Scott Moser
  • Date: 2016-07-12 16:28:59 UTC
  • mto: (58.1.1 pkg)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: smoser@ubuntu.com-20160712162859-f9jmixbnjsn3keu9
Tags: upstream-0.1.0~bzr399
ImportĀ upstreamĀ versionĀ 0.1.0~bzr399

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
 
49
49
 
50
50
DEFAULT_BRIDGE = os.environ.get("CURTIN_VMTEST_BRIDGE", "user")
 
51
OUTPUT_DISK_NAME = 'output_disk.img'
51
52
 
52
53
_TOPDIR = None
53
54
 
223
224
                         "Expected=%s" % (found, expected))
224
225
    for item in results:
225
226
        ftypes[item['ftype']] = item['item_url']
 
227
        last_item = item
226
228
 
227
229
    missing = [(ftype, path) for ftype, path in ftypes.items()
228
230
               if not os.path.exists(path)]
230
232
    if len(missing):
231
233
        raise ValueError("missing files for ftypes: %s" % missing)
232
234
 
233
 
    return ftypes
 
235
    # trusty amd64/hwe-p 20150101
 
236
    version_info = ('%(release)s %(arch)s/%(subarch)s %(version_name)s' %
 
237
                    last_item)
 
238
 
 
239
    return version_info, ftypes
234
240
 
235
241
 
236
242
class ImageStore:
256
262
        self.url = pathlib.Path(self.base_dir).as_uri()
257
263
 
258
264
    def get_image(self, release, arch, krel=None):
259
 
        """Return local path for root image, kernel and initrd, tarball."""
 
265
        """Return tuple of version info, and paths for root image,
 
266
           kernel, initrd, tarball."""
260
267
        if krel is None:
261
268
            krel = release
262
 
        ftypes = get_images(
 
269
        ver_info, ftypes = get_images(
263
270
            self.source_url, self.base_dir, release, arch, krel, self.sync)
264
271
        root_image_path = ftypes['vmtest.root-image']
265
272
        kernel_path = ftypes['boot-kernel']
266
273
        initrd_path = ftypes['boot-initrd']
267
274
        tarball = ftypes['vmtest.root-tgz']
268
 
        return (root_image_path, kernel_path, initrd_path, tarball)
 
275
        return ver_info, (root_image_path, kernel_path, initrd_path, tarball)
269
276
 
270
277
 
271
278
class TempDir(object):
327
334
 
328
335
        # create output disk, mount ro
329
336
        logger.debug('Creating output disk')
330
 
        self.output_disk = os.path.join(self.boot, "output_disk.img")
 
337
        self.output_disk = os.path.join(self.boot, OUTPUT_DISK_NAME)
331
338
        subprocess.check_call(["qemu-img", "create", "-f", TARGET_IMAGE_FORMAT,
332
339
                              self.output_disk, "10M"],
333
340
                              stdout=DEVNULL, stderr=subprocess.STDOUT)
344
351
class VMBaseClass(TestCase):
345
352
    __test__ = False
346
353
    arch_skip = []
 
354
    boot_timeout = 300
 
355
    collect_scripts = []
 
356
    conf_file = "examples/tests/basic.yaml"
347
357
    disk_block_size = 512
 
358
    disk_driver = 'virtio-blk'
348
359
    disk_to_check = {}
 
360
    extra_disks = []
 
361
    extra_kern_args = None
349
362
    fstab_expected = {}
350
 
    extra_kern_args = None
351
 
    recorded_errors = 0
352
 
    recorded_failures = 0
353
363
    image_store_class = ImageStore
354
 
    collect_scripts = []
 
364
    install_timeout = 3000
355
365
    interactive = False
356
 
    conf_file = "examples/tests/basic.yaml"
357
 
    extra_disks = []
 
366
    multipath = False
 
367
    multipath_num_paths = 2
358
368
    nvme_disks = []
359
 
    boot_timeout = 300
360
 
    install_timeout = 3000
 
369
    recorded_errors = 0
 
370
    recorded_failures = 0
361
371
    uefi = False
362
372
 
363
373
    # these get set from base_vm_classes
380
390
        # Disable sync if env var is set.
381
391
        image_store.sync = get_env_var_bool('CURTIN_VMTEST_IMAGE_SYNC', False)
382
392
        logger.debug("Image sync = %s", image_store.sync)
383
 
        (boot_img, boot_kernel, boot_initrd, tarball) = image_store.get_image(
384
 
            cls.release, cls.arch, cls.krel)
385
 
 
 
393
        img_verstr, (boot_img, boot_kernel, boot_initrd, tarball) = (
 
394
            image_store.get_image(cls.release, cls.arch, cls.krel))
 
395
        logger.debug("Image %s\n  boot=%s\n  kernel=%s\n  initrd=%s\n"
 
396
                     "  tarball=%s\n", img_verstr, boot_img, boot_kernel,
 
397
                     boot_initrd, tarball)
386
398
        # set up tempdir
387
399
        cls.td = TempDir(
388
400
            name=cls.__name__,
389
401
            user_data=generate_user_data(collect_scripts=cls.collect_scripts))
390
 
        logger.info('Using tempdir: {}'.format(cls.td.tmpdir))
391
 
 
 
402
        logger.info('Using tempdir: %s , Image: %s', cls.td.tmpdir,
 
403
                    img_verstr)
392
404
        cls.install_log = os.path.join(cls.td.logs, 'install-serial.log')
393
405
        cls.boot_log = os.path.join(cls.td.logs, 'boot-serial.log')
394
406
        logger.debug('Install console log: {}'.format(cls.install_log))
438
450
            netdevs.extend(["--netdev=" + DEFAULT_BRIDGE])
439
451
 
440
452
        # build disk arguments
441
 
        # --disk source:size:driver:block_size
442
 
        extra_disks = []
 
453
        disks = []
 
454
        sc = util.load_file(cls.conf_file)
 
455
        storage_config = yaml.load(sc).get('storage', {}).get('config', {})
 
456
        cls.disk_wwns = ["wwn=%s" % x.get('wwn') for x in storage_config
 
457
                         if 'wwn' in x]
 
458
        cls.disk_serials = ["serial=%s" % x.get('serial')
 
459
                            for x in storage_config if 'serial' in x]
 
460
 
 
461
        target_disk = "{}:{}:{}:{}:".format(cls.td.target_disk,
 
462
                                            "",
 
463
                                            cls.disk_driver,
 
464
                                            cls.disk_block_size)
 
465
        if len(cls.disk_wwns):
 
466
            target_disk += cls.disk_wwns[0]
 
467
 
 
468
        if len(cls.disk_serials):
 
469
            target_disk += cls.disk_serials[0]
 
470
 
 
471
        disks.extend(['--disk', target_disk])
 
472
 
 
473
        # --disk source:size:driver:block_size:devopts
443
474
        for (disk_no, disk_sz) in enumerate(cls.extra_disks):
444
475
            dpath = os.path.join(cls.td.disks, 'extra_disk_%d.img' % disk_no)
445
 
            extra_disks.extend(
446
 
                ['--disk', '{}:{}:{}:{}'.format(dpath, disk_sz, "",
447
 
                                                cls.disk_block_size)])
 
476
            extra_disk = '{}:{}:{}:{}:'.format(dpath, disk_sz,
 
477
                                               cls.disk_driver,
 
478
                                               cls.disk_block_size)
 
479
            if len(cls.disk_wwns):
 
480
                w_index = disk_no + 1
 
481
                if w_index < len(cls.disk_wwns):
 
482
                    extra_disk += cls.disk_wwns[w_index]
 
483
 
 
484
            if len(cls.disk_serials):
 
485
                w_index = disk_no + 1
 
486
                if w_index < len(cls.disk_serials):
 
487
                    extra_disk += cls.disk_serials[w_index]
 
488
 
 
489
            disks.extend(['--disk', extra_disk])
448
490
 
449
491
        # build nvme disk args if needed
450
 
        nvme_disks = []
451
492
        for (disk_no, disk_sz) in enumerate(cls.nvme_disks):
452
493
            dpath = os.path.join(cls.td.disks, 'nvme_disk_%d.img' % disk_no)
453
 
            nvme_disks.extend(
454
 
                ['--disk', '{}:{}:nvme:{}'.format(dpath, disk_sz,
455
 
                                                  cls.disk_block_size)])
 
494
            nvme_disk = '{}:{}:nvme:{}:{}'.format(dpath, disk_sz,
 
495
                                                  cls.disk_block_size,
 
496
                                                  "serial=nvme-%d" % disk_no)
 
497
            disks.extend(['--disk', nvme_disk])
456
498
 
457
499
        # proxy config
458
500
        configs = [cls.conf_file]
477
519
            shutil.copy(OVMF_VARS, nvram)
478
520
            cmd.extend(["--uefi", nvram])
479
521
 
480
 
        # --disk source:size:driver:block_size
481
 
        target_disk = "{}:{}:{}:{}".format(cls.td.target_disk, "", "",
482
 
                                           cls.disk_block_size)
483
 
        cmd.extend(netdevs + ["--disk", target_disk] +
484
 
                   extra_disks + nvme_disks +
 
522
        if cls.multipath:
 
523
            disks = disks * cls.multipath_num_paths
 
524
 
 
525
        cmd.extend(netdevs + disks +
485
526
                   [boot_img, "--kernel=%s" % boot_kernel, "--initrd=%s" %
486
527
                    boot_initrd, "--", "curtin", "-vv", "install"] +
487
528
                   ["--config=%s" % f for f in configs] +
510
551
        logger.debug('')
511
552
        try:
512
553
            if os.path.exists(cls.install_log):
513
 
                with open(cls.install_log) as l:
514
 
                    install_log = l.read()
 
554
                with open(cls.install_log, 'rb') as l:
 
555
                    install_log = l.read().decode('utf-8', errors='replace')
515
556
                errmsg, errors = check_install_log(install_log)
516
557
                if errmsg:
517
558
                    for e in errors:
527
568
            cls.tearDownClass()
528
569
            raise
529
570
 
530
 
        # drop the size parameter if present in extra_disks
531
 
        extra_disks = [x if ":" not in x else x.split(':')[0]
532
 
                       for x in extra_disks]
533
571
        # create --disk params for nvme disks
534
572
        bsize_args = "logical_block_size={}".format(cls.disk_block_size)
535
573
        bsize_args += ",physical_block_size={}".format(cls.disk_block_size)
536
574
        bsize_args += ",min_io_size={}".format(cls.disk_block_size)
537
 
        disk_driver = "virtio-blk"
538
575
 
539
576
        target_disks = []
540
 
        for (disk_no, disk) in enumerate([cls.td.target_disk,
541
 
                                          cls.td.output_disk]):
542
 
            d = '--disk={},driver={},format={},{}'.format(disk, disk_driver,
543
 
                                                          TARGET_IMAGE_FORMAT,
544
 
                                                          bsize_args)
545
 
            target_disks.extend([d])
 
577
        for (disk_no, disk) in enumerate([cls.td.target_disk]):
 
578
            disk = '--disk={},driver={},format={},{}'.format(
 
579
                disk, cls.disk_driver, TARGET_IMAGE_FORMAT, bsize_args)
 
580
            if len(cls.disk_wwns):
 
581
                disk += ",%s" % cls.disk_wwns[0]
 
582
            if len(cls.disk_serials):
 
583
                disk += ",%s" % cls.disk_serials[0]
 
584
 
 
585
            target_disks.extend([disk])
546
586
 
547
587
        extra_disks = []
548
588
        for (disk_no, disk_sz) in enumerate(cls.extra_disks):
549
589
            dpath = os.path.join(cls.td.disks, 'extra_disk_%d.img' % disk_no)
550
 
            d = '--disk={},driver={},format={},{}'.format(dpath, disk_driver,
551
 
                                                          TARGET_IMAGE_FORMAT,
552
 
                                                          bsize_args)
553
 
            extra_disks.extend([d])
 
590
            disk = '--disk={},driver={},format={},{}'.format(
 
591
                dpath, cls.disk_driver, TARGET_IMAGE_FORMAT, bsize_args)
 
592
            if len(cls.disk_wwns):
 
593
                w_index = disk_no + 1
 
594
                if w_index < len(cls.disk_wwns):
 
595
                    disk += ",%s" % cls.disk_wwns[w_index]
 
596
 
 
597
            if len(cls.disk_serials):
 
598
                w_index = disk_no + 1
 
599
                if w_index < len(cls.disk_serials):
 
600
                    disk += ",%s" % cls.disk_serials[w_index]
 
601
 
 
602
            extra_disks.extend([disk])
554
603
 
555
604
        nvme_disks = []
556
605
        disk_driver = 'nvme'
557
606
        for (disk_no, disk_sz) in enumerate(cls.nvme_disks):
558
607
            dpath = os.path.join(cls.td.disks, 'nvme_disk_%d.img' % disk_no)
559
 
            d = '--disk={},driver={},format={},{}'.format(dpath, disk_driver,
560
 
                                                          TARGET_IMAGE_FORMAT,
561
 
                                                          bsize_args)
562
 
            nvme_disks.extend([d])
 
608
            disk = '--disk={},driver={},format={},{}'.format(
 
609
                dpath, disk_driver, TARGET_IMAGE_FORMAT, bsize_args)
 
610
            nvme_disks.extend([disk])
 
611
 
 
612
        if cls.multipath:
 
613
            target_disks = target_disks * cls.multipath_num_paths
 
614
            extra_disks = extra_disks * cls.multipath_num_paths
 
615
            nvme_disks = nvme_disks * cls.multipath_num_paths
 
616
 
 
617
        # output disk is always virtio-blk, with serial of output_disk.img
 
618
        output_disk = '--disk={},driver={},format={},{},{}'.format(
 
619
            cls.td.output_disk, 'virtio-blk',
 
620
            TARGET_IMAGE_FORMAT, bsize_args,
 
621
            'serial=%s' % os.path.basename(cls.td.output_disk))
 
622
        target_disks.extend([output_disk])
563
623
 
564
624
        # create xkvm cmd
565
625
        cmd = (["tools/xkvm", "-v", dowait] + netdevs +
788
848
        self.base_dir = base_dir
789
849
 
790
850
    def get_image(self, release, arch, krel=None):
791
 
        """Return local path for root image, kernel and initrd, tarball."""
 
851
        """Return tuple of version info, and paths for root image,
 
852
           kernel, initrd, tarball."""
792
853
        names = ['psuedo-root-image', 'psuedo-kernel', 'psuedo-initrd',
793
854
                 'psuedo-tarball']
794
 
        return [os.path.join(self.base_dir, release, arch, f) for f in names]
 
855
        return (
 
856
            "psuedo-%s %s/hwe-P 20160101" % (release, arch),
 
857
            [os.path.join(self.base_dir, release, arch, f) for f in names])
795
858
 
796
859
 
797
860
class PsuedoVMBaseClass(VMBaseClass):
940
1003
              'content': yaml.dump(base_cloudconfig, indent=1)},
941
1004
             {'type': 'text/cloud-config', 'content': ssh_keys}]
942
1005
 
 
1006
    output_dir = '/mnt/output'
943
1007
    output_dir_macro = 'OUTPUT_COLLECT_D'
944
 
    output_dir = '/mnt/output'
945
 
    output_device = '/dev/vdb'
 
1008
    output_device = '/dev/disk/by-id/virtio-%s' % OUTPUT_DISK_NAME
946
1009
 
947
1010
    collect_prep = textwrap.dedent("mkdir -p " + output_dir)
948
1011
    collect_post = textwrap.dedent(
950
1013
 
951
1014
    # failsafe poweroff runs on precise only, where power_state does
952
1015
    # not exist.
953
 
    precise_poweroff = textwrap.dedent("""#!/bin/sh
 
1016
    precise_poweroff = textwrap.dedent("""#!/bin/sh -x
954
1017
        [ "$(lsb_release -sc)" = "precise" ] || exit 0;
955
1018
        shutdown -P now "Shutting down on precise"
956
1019
        """)
960
1023
 
961
1024
    for part in scripts:
962
1025
        if not part.startswith("#!"):
963
 
            part = "#!/bin/sh\n" + part
 
1026
            part = "#!/bin/sh -x\n" + part
964
1027
        part = part.replace(output_dir_macro, output_dir)
965
1028
        logger.debug('Cloud config archive content (pre-json):' + part)
966
1029
        parts.append({'content': part, 'type': 'text/x-shellscript'})