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
15 class VirtiofsSubmountsTest(LinuxTest
):
17 :avocado: tags=arch:x86_64
18 :avocado: tags=accel:kvm
21 def run(self
, args
, ignore_error
=False):
22 stdout
, stderr
, ret
= run_cmd(args
)
25 cmdline
= ' '.join(args
)
27 self
.fail(f
'{cmdline}: Returned {ret}: {stderr}')
29 self
.log
.warn(f
'{cmdline}: Returned {ret}: {stderr}')
31 return (stdout
, stderr
, ret
)
33 def set_up_shared_dir(self
):
34 self
.shared_dir
= os
.path
.join(self
.workdir
, 'virtiofs-shared')
36 os
.mkdir(self
.shared_dir
)
38 self
.run(('cp', self
.get_data('guest.sh'),
39 os
.path
.join(self
.shared_dir
, 'check.sh')))
41 self
.run(('cp', self
.get_data('guest-cleanup.sh'),
42 os
.path
.join(self
.shared_dir
, 'cleanup.sh')))
44 def set_up_virtiofs(self
):
45 attmp
= os
.getenv('AVOCADO_TESTS_COMMON_TMPDIR')
46 self
.vfsdsock
= os
.path
.join(attmp
, 'vfsdsock')
48 self
.run(('sudo', '-n', 'rm', '-f', self
.vfsdsock
), ignore_error
=True)
51 subprocess
.Popen(('sudo', '-n',
52 'tools/virtiofsd/virtiofsd',
53 f
'--socket-path={self.vfsdsock}',
54 '-o', f
'source={self.shared_dir}',
57 '-o', 'announce_submounts',
59 stdout
=subprocess
.DEVNULL
,
60 stderr
=subprocess
.PIPE
,
61 universal_newlines
=True)
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])
69 self
.run(('sudo', '-n', 'chmod', 'go+rw', self
.vfsdsock
))
71 self
.vm
.add_args('-chardev',
72 f
'socket,id=vfsdsock,path={self.vfsdsock}',
74 'vhost-user-fs-pci,queue-size=1024,chardev=vfsdsock' \
77 'memory-backend-file,id=mem,size=1G,' \
78 'mem-path=/dev/shm,share=on',
82 def set_up_nested_mounts(self
):
83 scratch_dir
= os
.path
.join(self
.shared_dir
, 'scratch')
86 except FileExistsError
:
89 args
= ['bash', self
.get_data('host.sh'), scratch_dir
]
93 out
, _
, _
= self
.run(args
)
94 seed
= re
.search(r
'^Seed: \d+', out
)
95 self
.log
.info(seed
[0])
97 def mount_in_guest(self
):
98 self
.ssh_command('mkdir -p /mnt/host')
99 self
.ssh_command('mount -t virtiofs host /mnt/host')
101 def check_in_guest(self
):
102 self
.ssh_command('bash /mnt/host/check.sh /mnt/host/scratch/share')
104 def live_cleanup(self
):
105 self
.ssh_command('bash /mnt/host/cleanup.sh /mnt/host/scratch')
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')
113 scratch_dir
= os
.path
.join(self
.shared_dir
, 'scratch')
114 self
.run(('bash', self
.get_data('cleanup.sh'), scratch_dir
))
116 @skipUnless(*has_cmds(('sudo -n', ('sudo', '-n', 'true')),
117 'ssh-keygen', 'bash', 'losetup', 'mkfs.xfs', 'mount'))
119 vmlinuz
= self
.params
.get('vmlinuz')
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.
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)')
137 self
.seed
= self
.params
.get('seed')
139 self
.ssh_key
= os
.path
.join(self
.workdir
, 'id_ed25519')
141 self
.run(('ssh-keygen', '-N', '', '-t', 'ed25519', '-f', self
.ssh_key
))
143 pubkey
= self
.ssh_key
+ '.pub'
145 super(VirtiofsSubmountsTest
, self
).setUp(pubkey
)
148 self
.vm
.add_args('-kernel', vmlinuz
,
149 '-append', 'console=ttyS0 root=/dev/sda1')
151 self
.require_accelerator("kvm")
152 self
.vm
.add_args('-accel', 'kvm')
160 scratch_dir
= os
.path
.join(self
.shared_dir
, 'scratch')
161 self
.run(('bash', self
.get_data('cleanup.sh'), scratch_dir
),
164 def test_pre_virtiofsd_set_up(self
):
165 self
.set_up_shared_dir()
167 self
.set_up_nested_mounts()
169 self
.set_up_virtiofs()
170 self
.launch_and_wait()
171 self
.mount_in_guest()
172 self
.check_in_guest()
174 def test_pre_launch_set_up(self
):
175 self
.set_up_shared_dir()
176 self
.set_up_virtiofs()
178 self
.set_up_nested_mounts()
180 self
.launch_and_wait()
181 self
.mount_in_guest()
182 self
.check_in_guest()
184 def test_post_launch_set_up(self
):
185 self
.set_up_shared_dir()
186 self
.set_up_virtiofs()
187 self
.launch_and_wait()
189 self
.set_up_nested_mounts()
191 self
.mount_in_guest()
192 self
.check_in_guest()
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()
200 self
.set_up_nested_mounts()
202 self
.check_in_guest()
204 def test_two_runs(self
):
205 self
.set_up_shared_dir()
207 self
.set_up_nested_mounts()
209 self
.set_up_virtiofs()
210 self
.launch_and_wait()
211 self
.mount_in_guest()
212 self
.check_in_guest()
215 self
.set_up_nested_mounts()
217 self
.check_in_guest()