qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

virtiofs_submounts.py (7280B)


      1 import logging
      2 import re
      3 import os
      4 import subprocess
      5 import time
      6 
      7 from avocado import skipUnless
      8 from avocado_qemu import LinuxTest, BUILD_DIR
      9 from avocado_qemu import has_cmds
     10 from avocado_qemu import run_cmd
     11 from avocado_qemu import wait_for_console_pattern
     12 from avocado.utils import ssh
     13 
     14 
     15 class VirtiofsSubmountsTest(LinuxTest):
     16     """
     17     :avocado: tags=arch:x86_64
     18     :avocado: tags=accel:kvm
     19     """
     20 
     21     def run(self, args, ignore_error=False):
     22         stdout, stderr, ret = run_cmd(args)
     23 
     24         if ret != 0:
     25             cmdline = ' '.join(args)
     26             if not ignore_error:
     27                 self.fail(f'{cmdline}: Returned {ret}: {stderr}')
     28             else:
     29                 self.log.warn(f'{cmdline}: Returned {ret}: {stderr}')
     30 
     31         return (stdout, stderr, ret)
     32 
     33     def set_up_shared_dir(self):
     34         self.shared_dir = os.path.join(self.workdir, 'virtiofs-shared')
     35 
     36         os.mkdir(self.shared_dir)
     37 
     38         self.run(('cp', self.get_data('guest.sh'),
     39                  os.path.join(self.shared_dir, 'check.sh')))
     40 
     41         self.run(('cp', self.get_data('guest-cleanup.sh'),
     42                  os.path.join(self.shared_dir, 'cleanup.sh')))
     43 
     44     def set_up_virtiofs(self):
     45         attmp = os.getenv('AVOCADO_TESTS_COMMON_TMPDIR')
     46         self.vfsdsock = os.path.join(attmp, 'vfsdsock')
     47 
     48         self.run(('sudo', '-n', 'rm', '-f', self.vfsdsock), ignore_error=True)
     49 
     50         self.virtiofsd = \
     51             subprocess.Popen(('sudo', '-n',
     52                               'tools/virtiofsd/virtiofsd',
     53                               f'--socket-path={self.vfsdsock}',
     54                               '-o', f'source={self.shared_dir}',
     55                               '-o', 'cache=always',
     56                               '-o', 'xattr',
     57                               '-o', 'announce_submounts',
     58                               '-f'),
     59                              stdout=subprocess.DEVNULL,
     60                              stderr=subprocess.PIPE,
     61                              universal_newlines=True)
     62 
     63         while not os.path.exists(self.vfsdsock):
     64             if self.virtiofsd.poll() is not None:
     65                 self.fail('virtiofsd exited prematurely: ' +
     66                           self.virtiofsd.communicate()[1])
     67             time.sleep(0.1)
     68 
     69         self.run(('sudo', '-n', 'chmod', 'go+rw', self.vfsdsock))
     70 
     71         self.vm.add_args('-chardev',
     72                          f'socket,id=vfsdsock,path={self.vfsdsock}',
     73                          '-device',
     74                          'vhost-user-fs-pci,queue-size=1024,chardev=vfsdsock' \
     75                              ',tag=host',
     76                          '-object',
     77                          'memory-backend-file,id=mem,size=1G,' \
     78                              'mem-path=/dev/shm,share=on',
     79                          '-numa',
     80                          'node,memdev=mem')
     81 
     82     def set_up_nested_mounts(self):
     83         scratch_dir = os.path.join(self.shared_dir, 'scratch')
     84         try:
     85             os.mkdir(scratch_dir)
     86         except FileExistsError:
     87             pass
     88 
     89         args = ['bash', self.get_data('host.sh'), scratch_dir]
     90         if self.seed:
     91             args += [self.seed]
     92 
     93         out, _, _ = self.run(args)
     94         seed = re.search(r'^Seed: \d+', out)
     95         self.log.info(seed[0])
     96 
     97     def mount_in_guest(self):
     98         self.ssh_command('mkdir -p /mnt/host')
     99         self.ssh_command('mount -t virtiofs host /mnt/host')
    100 
    101     def check_in_guest(self):
    102         self.ssh_command('bash /mnt/host/check.sh /mnt/host/scratch/share')
    103 
    104     def live_cleanup(self):
    105         self.ssh_command('bash /mnt/host/cleanup.sh /mnt/host/scratch')
    106 
    107         # It would be nice if the above was sufficient to make virtiofsd clear
    108         # all references to the mounted directories (so they can be unmounted
    109         # on the host), but unfortunately it is not.  To do so, we have to
    110         # resort to a remount.
    111         self.ssh_command('mount -o remount /mnt/host')
    112 
    113         scratch_dir = os.path.join(self.shared_dir, 'scratch')
    114         self.run(('bash', self.get_data('cleanup.sh'), scratch_dir))
    115 
    116     @skipUnless(*has_cmds(('sudo -n', ('sudo', '-n', 'true')),
    117                           'ssh-keygen', 'bash', 'losetup', 'mkfs.xfs', 'mount'))
    118     def setUp(self):
    119         vmlinuz = self.params.get('vmlinuz')
    120         if vmlinuz is None:
    121             """
    122             The Linux kernel supports FUSE auto-submounts only as of 5.10.
    123             boot_linux.py currently provides Fedora 31, whose kernel is too
    124             old, so this test cannot pass with the on-image kernel (you are
    125             welcome to try, hence the option to force such a test with
    126             -p vmlinuz='').  Therefore, for now the user must provide a
    127             sufficiently new custom kernel, or effectively explicitly
    128             request failure with -p vmlinuz=''.
    129             Once an image with a sufficiently new kernel is available
    130             (probably Fedora 34), we can make -p vmlinuz='' the default, so
    131             that this parameter no longer needs to be specified.
    132             """
    133             self.cancel('vmlinuz parameter not set; you must point it to a '
    134                         'Linux kernel binary to test (to run this test with ' \
    135                         'the on-image kernel, set it to an empty string)')
    136 
    137         self.seed = self.params.get('seed')
    138 
    139         self.ssh_key = os.path.join(self.workdir, 'id_ed25519')
    140 
    141         self.run(('ssh-keygen', '-N', '', '-t', 'ed25519', '-f', self.ssh_key))
    142 
    143         pubkey = self.ssh_key + '.pub'
    144 
    145         super(VirtiofsSubmountsTest, self).setUp(pubkey)
    146 
    147         if vmlinuz:
    148             self.vm.add_args('-kernel', vmlinuz,
    149                              '-append', 'console=ttyS0 root=/dev/sda1')
    150 
    151         self.require_accelerator("kvm")
    152         self.vm.add_args('-accel', 'kvm')
    153 
    154     def tearDown(self):
    155         try:
    156             self.vm.shutdown()
    157         except:
    158             pass
    159 
    160         scratch_dir = os.path.join(self.shared_dir, 'scratch')
    161         self.run(('bash', self.get_data('cleanup.sh'), scratch_dir),
    162                  ignore_error=True)
    163 
    164     def test_pre_virtiofsd_set_up(self):
    165         self.set_up_shared_dir()
    166 
    167         self.set_up_nested_mounts()
    168 
    169         self.set_up_virtiofs()
    170         self.launch_and_wait()
    171         self.mount_in_guest()
    172         self.check_in_guest()
    173 
    174     def test_pre_launch_set_up(self):
    175         self.set_up_shared_dir()
    176         self.set_up_virtiofs()
    177 
    178         self.set_up_nested_mounts()
    179 
    180         self.launch_and_wait()
    181         self.mount_in_guest()
    182         self.check_in_guest()
    183 
    184     def test_post_launch_set_up(self):
    185         self.set_up_shared_dir()
    186         self.set_up_virtiofs()
    187         self.launch_and_wait()
    188 
    189         self.set_up_nested_mounts()
    190 
    191         self.mount_in_guest()
    192         self.check_in_guest()
    193 
    194     def test_post_mount_set_up(self):
    195         self.set_up_shared_dir()
    196         self.set_up_virtiofs()
    197         self.launch_and_wait()
    198         self.mount_in_guest()
    199 
    200         self.set_up_nested_mounts()
    201 
    202         self.check_in_guest()
    203 
    204     def test_two_runs(self):
    205         self.set_up_shared_dir()
    206 
    207         self.set_up_nested_mounts()
    208 
    209         self.set_up_virtiofs()
    210         self.launch_and_wait()
    211         self.mount_in_guest()
    212         self.check_in_guest()
    213 
    214         self.live_cleanup()
    215         self.set_up_nested_mounts()
    216 
    217         self.check_in_guest()